“DESEMPEÑO DE LOS ESTUDIANTES EN LOS EXAMENES”

Equipo No: 13

Integrantes

  • Oscar Daniel Betancourt

  • Diego Isaias López Tapia

  • Juan Daniel Carrillo Mercado

  • Carlos Joel de la Rosa Hernández

Introducción

Por medio de un conjunto de datos, conformado por las calificaciones obtenidas de los estudiantes en asignaturas como matemáticas, lectura y escritura, determinar si diferentes factores que incluye el conjunto de datos influyen en el resultado de los exámenes.

Los factores son:

  • Nivel de educación de los padres.

  • Curso de preparación para el examen

  • Tipo de almuerzo

  • Raza

El conjunto de datos fue obtenido de Kaggle

Para esto, realizaremos una serie de preguntas con respecto a los factores mencionados anteriormente para la formulación de hipótesis

1. ¿Existe una influencia del nivel educativo de los padres en las calificaciones del alumno?

  • Matemáticas
  • Lectura
  • Escritura

2. ¿Existe una diferencia significativa de las calificaciones entre los alumnos que tomaron el curso de preparación y los que no?

  • Matemáticas
  • Lectura
  • Escritura

3. ¿Existe una relación en el desempeños de las calificaciones de los alumnos el tipo de lunch?

  • Matemáticas
  • Lectura
  • Escritura

4. ¿Influye el tipo de raza de los alumnos en el desempeño de los alumnos?

  • Matemáticas
  • Lectura
  • Escritura

Carga de Datos y Análisis Exploratorio

Iniciamos nuestro código cargando las librerias que necesitaremos, así como nuestro conjunto de datos

#Cargamos la libreria para leer el dataset
library(readxl)
library(ggplot2)
library(plotly)
#Asignamos a la variable df la lectura de nuestro archivo exams.xls
df<-read_excel(file.choose())
#Observamos el dataset
head(df)

Definición del dataset

  • La columna gender muestra información del tipo de género del alumno

  • La columna race_ethnicity muestra la informacion clasificada por grupo:

    • group A: Clase alta

    • group B: Clase media-alta

    • group C: Clase media

    • group D: Clase media-baja

    • group E: Clase baja

  • La columna parental_level_of_education muestra información del grado de estudio de los padres

  • La columna lunch muestra información del tipo de alimentación de los alumnos

  • La columna test_preparation_curse muestra información si los alumnos tomaron el curso de preparación

  • Las calificaciones de las materias se encuentran en un estandar del 1 al 100

Análisis de los datos

ggplot(df,aes(gender) )+
  geom_bar(width= 0.5,colour="red", fill="skyblue")+
  scale_y_continuous(limits = c(0,600),
                     breaks = seq(0,1000,1000))+
  labs(title = "Distribución de estudiantes Hombres y Mujeres",
       x="género",
       y= "Alumnos")+
  theme_bw(base_size = 12)+
  
  geom_text(aes(label=..count..), stat='count', 
            position=position_dodge(0.9), 
            vjust=-0.5, 
            size=5.0
            ) 

# Gráfico de barras para comparar el desempeño en matemáticas según el nivel de educación de los padres
ggplot(df, aes(x = parental_level_of_education, y = math_score)) +
  geom_bar(stat = "summary", fun = "mean") +
  labs(title = "Desempeño en Matemáticas según Nivel de Educación de los Padres", x = "Nivel de Educación de los Padres", y = "Calificación Promedio en Matemáticas")

# Gráfico de barras apiladas con facetas por nivel de educación de los padres
ggplot(df, aes(x = gender, y = math_score, fill = lunch)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Distribución de Calificaciones de Matemáticas por Género, Tipo de Almuerzo y Nivel de Educación de los Padres", 
       x = "Género", y = "Calificaciones de Matemáticas", fill = "Tipo de Almuerzo") +
  facet_wrap(~ parental_level_of_education, scales = "free_y", ncol = 2)  # Facetas por nivel de educación de los padres

# Gráfico de barras apiladas con facetas por nivel de educación de los padres
ggplot(df, aes(x = gender, y = math_score, fill = lunch)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Distribución de Calificaciones de Matemáticas por Género, Tipo de Almuerzo y Nivel de Educación de los padres")

PRUEBAS DE HIPÓTESIS

1. ¿Existe una influencia del nivel educativo de los padres en las calificaciones del alumno?

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de la materia de matemáticas y el grado de estudios de los padres

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de Matemáticas y el grado de estudios de los padres.

  • Hipotesis alternativa (Ha) Existe una relación significativa entre la calificación de Matemáticas y el grado de estudios de los padres.

padres_matemáticas <- aov(math_score ~ parental_level_of_education, data = df) #Realizamos nuestra prueba anova
summary(padres_matemáticas) #Mostramos el resultado
                             Df Sum Sq Mean Sq F value   Pr(>F)    
parental_level_of_education   5   9562  1912.4    8.57 5.85e-08 ***
Residuals                   994 221815   223.2                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de Matemáticas y el grado de estudios de los padres

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de la materia de lectura y el grado de estudios de los padres

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de Lectura y el grado de estudios de los padres.

  • Hipotesis alternativa (Ha) Existe una relación significativa entre la calificación de Lectura y el grado de estudios de los padres.

padres_lectura <- aov(reading_score ~ parental_level_of_education, data = df) #Realizamos nuestra prueba anova
summary(padres_lectura) #Mostramos el resultado
                             Df Sum Sq Mean Sq F value   Pr(>F)    
parental_level_of_education   5  13332  2666.4   13.39 1.19e-12 ***
Residuals                   994 197983   199.2                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de Lectura y el grado de estudios de los padres

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de la materia de escritura y el grado de estudios de los padres

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de Escritura y el grado de estudios de los padres.

  • Hipotesis alternativa (Ha) Existe una relación significativa entre la calificación de Escritura y el grado de estudios de los padres.

padres_escritura <- aov(writing_score ~ parental_level_of_education, data = df) #Realizamos nuestra prueba anova
summary(padres_escritura) #mostramos el resultado
                             Df Sum Sq Mean Sq F value Pr(>F)    
parental_level_of_education   5  18731    3746   17.93 <2e-16 ***
Residuals                   994 207724     209                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de Escritura y el grado de estudios de los padres

2. ¿Existe una diferencia significativa de las calificaciones entre los alumnos que tomaron el curso de preparación y los que no?

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de matemáticas y el grado de estudios de los padres

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de matemáticas de los alumnos que tomaron el curso de preparación y los que no.

  • Hipótesis alternativa (Ha): Existe diferencia significativa en las calificaciones de matemáticas de los alumnos que tomaron el curso de preparación y los que no.

ttest_matemáticas <- t.test(math_score ~ test_preparation_curse, data = df, conf.level= 0.99) #Realizamos nuestra prueba test
ttest_matemáticas #mostramos el resultado

    Welch Two Sample t-test

data:  math_score by test_preparation_curse
t = 3.7917, df = 743.9, p-value = 0.0001617
alternative hypothesis: true difference in means between group completed and group none is not equal to 0
99 percent confidence interval:
 1.199237 6.321289
sample estimates:
mean in group completed      mean in group none 
               69.40113                65.64087 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de Matemáticas con los alumnos que completaronel curso de preparación

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de escritura y el grado de estudios de los padres

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de lectura de los alumnos que tomaron el curso de preparación y los que no.

  • Hipótesis alternativa (Ha): Existe diferencia significativa en las calificaciones de lectura de los alumnos que tomaron el curso de preparación y los que no.

ttest_lectura <- t.test(reading_score ~ test_preparation_curse, data = df, conf.level= 0.99) #Realizamos nuestra prueba test
ttest_lectura #mostramos el resultado

    Welch Two Sample t-test

data:  reading_score by test_preparation_curse
t = 7.2189, df = 761.03, p-value = 1.272e-12
alternative hypothesis: true difference in means between group completed and group none is not equal to 0
99 percent confidence interval:
 4.283536 9.054922
sample estimates:
mean in group completed      mean in group none 
               74.05932                67.39009 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de lectura con los alumnos que completaronel curso de preparación

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de escritura y el grado de estudios de los padres

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de escritura de los alumnos que tomaron el curso de preparación y los que no.

  • Hipótesis alternativa (Ha): Existe diferencia significativa en las calificaciones de escritura de los alumnos que tomaron el curso de preparación y los que no.

ttest_escritura <- t.test(writing_score ~ test_preparation_curse, data = df, conf.level= 0.99) #Realizamos nuestra prueba test
ttest_escritura #mostramos el resultado

    Welch Two Sample t-test

data:  writing_score by test_preparation_curse
t = 9.871, df = 755.35, p-value < 2.2e-16
alternative hypothesis: true difference in means between group completed and group none is not equal to 0
99 percent confidence interval:
  6.845514 11.696211
sample estimates:
mean in group completed      mean in group none 
               74.45198                65.18111 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de escritura con los alumnos que completaronel curso de preparación

3. ¿Existe una relación en el desempeños de las calificaciones de los alumnos el tipo de lunch?

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de matemáticas y el tipo de lunch

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de matemáticas entre los tipos de lunch.

  • Hipótesis nula (Ha): Existe diferencia significativa en las calificaciones de matemáticas entre los tipos de lunch.

resultado_ttest <- t.test(math_score ~ lunch, data = df, conf.level= 0.99)
resultado_ttest

    Welch Two Sample t-test

data:  math_score by lunch
t = -13.648, df = 696.41, p-value < 2.2e-16
alternative hypothesis: true difference in means between group free/reduced and group standard is not equal to 0
99 percent confidence interval:
 -15.15555 -10.33192
sample estimates:
mean in group free/reduced     mean in group standard 
                  58.68857                   71.43231 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de matemáticas con el tipo de lunch

Densidad de calificaciones de matemáticas con el tipo de lunch

# Gráfico de Densidad para Calificaciones de Matemáticas
ggplot(df, aes(x = math_score, fill = lunch)) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidad de Calificaciones de Matemáticas",
       x = "Calificación de Matemáticas", y = "Densidad")

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de escritura y el tipo de lunch

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de escritura entre los tipos de lunch.

  • Hipótesis nula (Ha): Existe diferencia significativa en las calificaciones de escritura entre los tipos de lunch.

resultado_ttest <- t.test(writing_score ~ lunch, data = df, conf.level= 0.99)
resultado_ttest

    Welch Two Sample t-test

data:  writing_score by lunch
t = -9.3053, df = 708.08, p-value < 2.2e-16
alternative hypothesis: true difference in means between group free/reduced and group standard is not equal to 0
99 percent confidence interval:
 -11.422507  -6.459251
sample estimates:
mean in group free/reduced     mean in group standard 
                  62.65143                   71.59231 

Densidad de calificaciones de escritura con el tipo de lunch

# Gráfico de Densidad para Calificaciones de Escritura
ggplot(df, aes(x = writing_score, fill = lunch)) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidad de Calificaciones de Escritura",
       x = "Calificación de Escritura", y = "Densidad")

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de escritura con el tipo de lunch

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de lectura y el tipo de lunch

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de lectura entre los tipos de lunch.

  • Hipótesis nula (Ha): Existe diferencia significativa en las calificaciones de lectura entre los tipos de lunch.

resultado_ttest <- t.test(reading_score ~ lunch, data = df, conf.level= 0.99)
resultado_ttest

    Welch Two Sample t-test

data:  reading_score by lunch
t = -8.9028, df = 690.31, p-value < 2.2e-16
alternative hypothesis: true difference in means between group free/reduced and group standard is not equal to 0
99 percent confidence interval:
 -10.78520  -5.93436
sample estimates:
mean in group free/reduced     mean in group standard 
                  64.31714                   72.67692 

Densidad de calificaciones de lectura con el tipo de lunch

# Gráfico de Densidad para Calificaciones de lectura
ggplot(df, aes(x = reading_score, fill = lunch)) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidad de Calificaciones de Lectura",
       x = "Calificación de Español", y = "Densidad")

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de lectura con el tipo de lunch

Prueba de hipótesis para evaluar la relación entre las calificaciones de la materia de lectura y el tipo de lunch y el género

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de lectura, el tipo de lunch y el género..

  • Hipótesis nula (Ha): Existe relación significativa entre la calificación de lectura, el tipo de lunch y el género.

resultado_anova <- aov(reading_score ~ lunch + gender, data = df)
summary(resultado_anova)
             Df Sum Sq Mean Sq F value   Pr(>F)    
lunch         1  15899   15899   86.25  < 2e-16 ***
gender        1  11627   11627   63.07 5.35e-15 ***
Residuals   997 183789     184                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de lectura con el tipo de lunch y el género

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de la materia de lectura y el tipo de lunch y el curso de preparacion.

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de lectura, el tipo de lunch y curso de preparacion..

  • Hipótesis nula (Ha): Existe relación significativa entre la calificación de lectura, el tipo de lunch y el curso de preparacion.

resultado_anova <- aov(reading_score ~ lunch + test_preparation_curse, data = df)
summary(resultado_anova)
                        Df Sum Sq Mean Sq F value   Pr(>F)    
lunch                    1  15899   15899   85.37  < 2e-16 ***
test_preparation_curse   1   9744    9744   52.32 9.37e-13 ***
Residuals              997 185672     186                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de lectura con el tipo de lunch y el curso de preparacion

4. ¿Influye el tipo de género de los alumnos en el desempeño de los alumnos?

Prueba de hipótesis t para comparar las medias de las calificaciones de matemáticas entre los géneros.

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de matemáticas entre los géneros.

  • Hipótesis nula (Ha): Existe una diferencia significativa en las calificaciones de matemáticas entre los géneros.

resultado_ttest <- t.test(math_score ~ gender, data = df, conf.level= 0.99)
resultado_ttest

    Welch Two Sample t-test

data:  math_score by gender
t = -5.0442, df = 985.26, p-value = 5.421e-07
alternative hypothesis: true difference in means between group female and group male is not equal to 0
99 percent confidence interval:
 -7.266225 -2.347437
sample estimates:
mean in group female   mean in group male 
            64.46764             69.27447 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de matemáticas y el género

Prueba de hipótesis t para comparar las medias de las calificaciones de lectura entre los géneros.

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de lectura entre los géneros.

  • Hipótesis nula (Ha): Existe una diferencia significativa en las calificaciones de lectura entre los géneros.

resultado_ttest <- t.test(reading_score ~ gender, data = df, conf.level= 0.99)
resultado_ttest

    Welch Two Sample t-test

data:  reading_score by gender
t = 7.4112, df = 991.78, p-value = 2.677e-13
alternative hypothesis: true difference in means between group female and group male is not equal to 0
99 percent confidence interval:
 4.330892 8.958719
sample estimates:
mean in group female   mean in group male 
            73.21294             66.56814 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de lectura y el género

Prueba de hipótesis t para comparar las medias de las calificaciones de escritura entre los géneros.

  • Hipótesis nula (H0): No hay diferencia significativa en las calificaciones de escritura entre los géneros.

  • Hipótesis nula (Ha): Existe una diferencia significativa en las calificaciones de escritura entre los géneros.

resultado_ttest <- t.test(writing_score ~ gender, data = df, conf.level= 0.99)
resultado_ttest

    Welch Two Sample t-test

data:  writing_score by gender
t = 9.3761, df = 985.76, p-value < 2.2e-16
alternative hypothesis: true difference in means between group female and group male is not equal to 0
99 percent confidence interval:
  6.218332 10.941723
sample estimates:
mean in group female   mean in group male 
            72.93319             64.35317 

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de escritura y el género

# Calcular promedios en una escala de 0 a 100
df_promedios <- df %>%
  group_by(race_ethnicity) %>%
  summarise(
    mean_math_score = mean(math_score) * 100 / max(df$math_score),
    mean_reading_score = mean(reading_score) * 100 / max(df$reading_score),
    mean_writing_score = mean(writing_score) * 100 / max(df$writing_score)
  )

# Crear un gráfico de barras agrupadas con plotly
grafico_barras_plotly <- plot_ly(df_promedios, x = ~race_ethnicity) %>%
  add_trace(y = ~mean_math_score, name = 'Math', type = 'bar', marker = list(color = 'lightblue')) %>%
  add_trace(y = ~mean_reading_score, name = 'Reading', type = 'bar', marker = list(color = 'lightgreen')) %>%
  add_trace(y = ~mean_writing_score, name = 'Writing', type = 'bar', marker = list(color = 'lightpink')) %>%
  layout(
    title = 'Desempeño de Estudiantes por Grupo Étnico (Promedios en Escala de 0 a 100)',
    xaxis = list(title = 'Grupo Étnico'),
    yaxis = list(title = 'Calificación Promedio', range = c(0, 100)),
    barmode = 'group'
  )
# Visualizar el gráfico
grafico_barras_plotly

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de matemáticas y el grupo social al que pertenecen.

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de matemáticas y el grupo social al que pertenecen.

  • Hipótesis nula (Ha): Existe una relación significativa entre la calificación de matemáticas y el grupo social al que pertenecen.

resultado_anova <- aov(math_score ~ race_ethnicity, data = df)
summary(resultado_anova)
                Df Sum Sq Mean Sq F value  Pr(>F)    
race_ethnicity   4  16162    4040   18.68 8.1e-15 ***
Residuals      995 215216     216                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de matemáticas y el grupo social al que pertenecen.

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de lectura y el grupo social al que pertenecen.

  • Hipótesis nula (H0): No hay relación significativa entre la calificación de lectura y el grupo social al que pertenecen.

  • Hipótesis nula (Ha): Existe una relación significativa entre la calificación de lectura y el grupo social al que pertenecen.

resultado_anova <- aov(reading_score ~ race_ethnicity, data = df)
summary(resultado_anova)
                Df Sum Sq Mean Sq F value Pr(>F)    
race_ethnicity   4   4618  1154.5   5.557  2e-04 ***
Residuals      995 206697   207.7                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de lectura y el grupo social al que pertenecen.

Prueba de hipótesis ANOVA para evaluar la relación entre las calificaciones de escritura y el grupo social al que pertenecen.

  • Hipótesis nula (H0):No hay relación significativa entre la calificación de escritura y el grupo social al que pertenecen.

  • Hipótesis nula (Ha): Existe una relación significativa entre la calificación de escritura y el grupo social al que pertenecen.

resultado_anova <- aov(writing_score ~ race_ethnicity, data = df)
summary(resultado_anova)
                Df Sum Sq Mean Sq F value  Pr(>F)   
race_ethnicity   4   3561   890.1   3.974 0.00332 **
Residuals      995 222894   224.0                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La hipótesis nula se descarta y se acepta la hipótesis alternativa. Existe una relación significativa entre la calificación de escritura y el grupo social al que pertenecen.

CONCLUSIONES

De acuerdo con las distintas pruebas realizadas tanto la prueba t y la prueba ANOVA se puede observar que si existe una influencia significativa entre los factores; “Nivel de educación de los padres”, “Curso de preparación para el examen”, “Tipo de almuerzo” y “Raza”, con las calificaciones de los alumnos. Además siendo el genero femenino quien obtuvo un promedio mas alto en sus calificaciones.

LS0tDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgICB0aGVtZTogZmxhdGx5DQogICAgICB0b2M6IHRydWUNCiAgICAgIHRvY19mbG9hdDoNCiAgICAgICAgY29sbGFwc2VkOiB0cnVlDQogICAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlDQotLS0NCiMgIkRFU0VNUEXDkU8gREUgTE9TIEVTVFVESUFOVEVTIEVOIExPUyBFWEFNRU5FUyIgDQoNCioqKkVxdWlwbyBObzogMTMqKioNCg0KKioqSW50ZWdyYW50ZXMqKioNCg0KKyBPc2NhciBEYW5pZWwgQmV0YW5jb3VydA0KDQorIERpZWdvIElzYWlhcyBMw7NwZXogVGFwaWENCg0KKyBKdWFuIERhbmllbCBDYXJyaWxsbyBNZXJjYWRvDQoNCisgQ2FybG9zIEpvZWwgZGUgbGEgUm9zYSBIZXJuw6FuZGV6IA0KDQojIyMgSW50cm9kdWNjacOzbiANClBvciBtZWRpbyBkZSB1biBjb25qdW50byBkZSBkYXRvcywgY29uZm9ybWFkbyBwb3IgbGFzIGNhbGlmaWNhY2lvbmVzIG9idGVuaWRhcyBkZSBsb3MgZXN0dWRpYW50ZXMgZW4gYXNpZ25hdHVyYXMgY29tbyBtYXRlbcOhdGljYXMsIGxlY3R1cmEgeSBlc2NyaXR1cmEsIGRldGVybWluYXIgc2kgZGlmZXJlbnRlcyBmYWN0b3JlcyBxdWUgaW5jbHV5ZSBlbCBjb25qdW50byBkZSBkYXRvcyBpbmZsdXllbiBlbiBlbCByZXN1bHRhZG8gZGUgbG9zIGV4w6FtZW5lcy4gDQoNCkxvcyBmYWN0b3JlcyBzb246DQoNCiogKipOaXZlbCBkZSBlZHVjYWNpw7NuIGRlIGxvcyBwYWRyZXMuKioNCg0KKiAqKkN1cnNvIGRlIHByZXBhcmFjacOzbiBwYXJhIGVsIGV4YW1lbioqDQoNCiogKipUaXBvIGRlIGFsbXVlcnpvKioNCg0KKiAqKlJhemEqKg0KDQpFbCBjb25qdW50byBkZSBkYXRvcyBmdWUgb2J0ZW5pZG8gZGUgW0thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9zcHNjaWVudGlzdC9zdHVkZW50cy1wZXJmb3JtYW5jZS1pbi1leGFtcykNCg0KIyMjIyBQYXJhIGVzdG8sIHJlYWxpemFyZW1vcyB1bmEgc2VyaWUgZGUgcHJlZ3VudGFzIGNvbiByZXNwZWN0byBhIGxvcyBmYWN0b3JlcyBtZW5jaW9uYWRvcyBhbnRlcmlvcm1lbnRlIHBhcmEgbGEgZm9ybXVsYWNpw7NuIGRlIGhpcMOzdGVzaXMNCioqMS4gwr9FeGlzdGUgdW5hIGluZmx1ZW5jaWEgZGVsIG5pdmVsIGVkdWNhdGl2byBkZSBsb3MgcGFkcmVzIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZWwgYWx1bW5vPyoqDQoNCisgTWF0ZW3DoXRpY2FzDQorIExlY3R1cmENCisgRXNjcml0dXJhDQoNCioqMi4gwr9FeGlzdGUgdW5hIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBkZSBsYXMgY2FsaWZpY2FjaW9uZXMgZW50cmUgbG9zIGFsdW1ub3MgcXVlIHRvbWFyb24gZWwgY3Vyc28gZGUgcHJlcGFyYWNpw7NuIHkgbG9zIHF1ZSBubz8qKg0KDQorIE1hdGVtw6F0aWNhcw0KKyBMZWN0dXJhDQorIEVzY3JpdHVyYQ0KDQoqKjMuIMK/RXhpc3RlIHVuYSByZWxhY2nDs24gZW4gZWwgZGVzZW1wZcOxb3MgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxvcyBhbHVtbm9zIGVsIHRpcG8gZGUgbHVuY2g/ICoqDQoNCisgTWF0ZW3DoXRpY2FzDQorIExlY3R1cmENCisgRXNjcml0dXJhDQoNCioqNC4gwr9JbmZsdXllIGVsIHRpcG8gZGUgcmF6YSBkZSBsb3MgYWx1bW5vcyBlbiBlbCBkZXNlbXBlw7FvIGRlIGxvcyBhbHVtbm9zPyoqDQoNCisgTWF0ZW3DoXRpY2FzDQorIExlY3R1cmENCisgRXNjcml0dXJhDQoNCiMgQ2FyZ2EgZGUgRGF0b3MgeSBBbsOhbGlzaXMgRXhwbG9yYXRvcmlvDQpJbmljaWFtb3MgbnVlc3RybyBjw7NkaWdvIGNhcmdhbmRvIGxhcyBsaWJyZXJpYXMgcXVlIG5lY2VzaXRhcmVtb3MsIGFzw60gY29tbyBudWVzdHJvIGNvbmp1bnRvIGRlIGRhdG9zDQpgYGB7cn0NCiNDYXJnYW1vcyBsYSBsaWJyZXJpYSBwYXJhIGxlZXIgZWwgZGF0YXNldA0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCiNBc2lnbmFtb3MgYSBsYSB2YXJpYWJsZSBkZiBsYSBsZWN0dXJhIGRlIG51ZXN0cm8gYXJjaGl2byBleGFtcy54bHMNCmRmPC1yZWFkX2V4Y2VsKGZpbGUuY2hvb3NlKCkpDQojT2JzZXJ2YW1vcyBlbCBkYXRhc2V0DQpoZWFkKGRmKQ0KYGBgDQojIyBEZWZpbmljacOzbiBkZWwgZGF0YXNldA0KKiBMYSBjb2x1bW5hIF9nZW5kZXJfIG11ZXN0cmEgaW5mb3JtYWNpw7NuIGRlbCB0aXBvIGRlIGfDqW5lcm8gZGVsIGFsdW1ubw0KDQoqIExhIGNvbHVtbmEgX3JhY2VfZXRobmljaXR5XyBtdWVzdHJhIGxhIGluZm9ybWFjaW9uIGNsYXNpZmljYWRhIHBvciBncnVwbzoNCiAgDQogICsgX2dyb3VwXyBfQTpfIENsYXNlIGFsdGENCiAgDQogICsgX2dyb3VwXyBfQjpfIENsYXNlIG1lZGlhLWFsdGENCiAgDQogICsgX2dyb3VwXyBfQzpfIENsYXNlIG1lZGlhDQogIA0KICArIF9ncm91cF8gX0Q6XyBDbGFzZSBtZWRpYS1iYWphDQogIA0KICArIF9ncm91cF8gX0U6XyBDbGFzZSBiYWphDQoNCiogTGEgY29sdW1uYSBfcGFyZW50YWxfbGV2ZWxfb2ZfZWR1Y2F0aW9uXyBtdWVzdHJhIGluZm9ybWFjacOzbiBkZWwgZ3JhZG8gZGUgZXN0dWRpbyBkZSBsb3MgcGFkcmVzDQoNCiogTGEgY29sdW1uYSBfbHVuY2hfIG11ZXN0cmEgaW5mb3JtYWNpw7NuIGRlbCB0aXBvIGRlIGFsaW1lbnRhY2nDs24gZGUgbG9zIGFsdW1ub3MNCg0KKiBMYSBjb2x1bW5hIF90ZXN0X3ByZXBhcmF0aW9uX2N1cnNlXyBtdWVzdHJhIGluZm9ybWFjacOzbiBzaSBsb3MgYWx1bW5vcyB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbg0KDQoqIExhcyBjYWxpZmljYWNpb25lcyBkZSBsYXMgbWF0ZXJpYXMgc2UgZW5jdWVudHJhbiBlbiB1biBlc3RhbmRhciBkZWwgMSBhbCAxMDANCg0KDQoNCiMjIEFuw6FsaXNpcyBkZSBsb3MgZGF0b3MNCmBgYHtyfQ0KZ2dwbG90KGRmLGFlcyhnZW5kZXIpICkrDQogIGdlb21fYmFyKHdpZHRoPSAwLjUsY29sb3VyPSJyZWQiLCBmaWxsPSJza3libHVlIikrDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNjAwKSwNCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLDEwMDAsMTAwMCkpKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgZXN0dWRpYW50ZXMgSG9tYnJlcyB5IE11amVyZXMiLA0KICAgICAgIHg9ImfDqW5lcm8iLA0KICAgICAgIHk9ICJBbHVtbm9zIikrDQogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSsNCiAgDQogIGdlb21fdGV4dChhZXMobGFiZWw9Li5jb3VudC4uKSwgc3RhdD0nY291bnQnLCANCiAgICAgICAgICAgIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKDAuOSksIA0KICAgICAgICAgICAgdmp1c3Q9LTAuNSwgDQogICAgICAgICAgICBzaXplPTUuMA0KICAgICAgICAgICAgKSANCmBgYA0KDQpgYGB7cn0NCiMgR3LDoWZpY28gZGUgYmFycmFzIHBhcmEgY29tcGFyYXIgZWwgZGVzZW1wZcOxbyBlbiBtYXRlbcOhdGljYXMgc2Vnw7puIGVsIG5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcw0KZ2dwbG90KGRmLCBhZXMoeCA9IHBhcmVudGFsX2xldmVsX29mX2VkdWNhdGlvbiwgeSA9IG1hdGhfc2NvcmUpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIikgKw0KICBsYWJzKHRpdGxlID0gIkRlc2VtcGXDsW8gZW4gTWF0ZW3DoXRpY2FzIHNlZ8O6biBOaXZlbCBkZSBFZHVjYWNpw7NuIGRlIGxvcyBQYWRyZXMiLCB4ID0gIk5pdmVsIGRlIEVkdWNhY2nDs24gZGUgbG9zIFBhZHJlcyIsIHkgPSAiQ2FsaWZpY2FjacOzbiBQcm9tZWRpbyBlbiBNYXRlbcOhdGljYXMiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBiYXJyYXMgYXBpbGFkYXMgY29uIGZhY2V0YXMgcG9yIG5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcw0KZ2dwbG90KGRmLCBhZXMoeCA9IGdlbmRlciwgeSA9IG1hdGhfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgQ2FsaWZpY2FjaW9uZXMgZGUgTWF0ZW3DoXRpY2FzIHBvciBHw6luZXJvLCBUaXBvIGRlIEFsbXVlcnpvIHkgTml2ZWwgZGUgRWR1Y2FjacOzbiBkZSBsb3MgUGFkcmVzIiwgDQogICAgICAgeCA9ICJHw6luZXJvIiwgeSA9ICJDYWxpZmljYWNpb25lcyBkZSBNYXRlbcOhdGljYXMiLCBmaWxsID0gIlRpcG8gZGUgQWxtdWVyem8iKSArDQogIGZhY2V0X3dyYXAofiBwYXJlbnRhbF9sZXZlbF9vZl9lZHVjYXRpb24sIHNjYWxlcyA9ICJmcmVlX3kiLCBuY29sID0gMikgICMgRmFjZXRhcyBwb3Igbml2ZWwgZGUgZWR1Y2FjacOzbiBkZSBsb3MgcGFkcmVzDQpgYGANCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBiYXJyYXMgYXBpbGFkYXMgY29uIGZhY2V0YXMgcG9yIG5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcw0KZ2dwbG90KGRmLCBhZXMoeCA9IGdlbmRlciwgeSA9IG1hdGhfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgQ2FsaWZpY2FjaW9uZXMgZGUgTWF0ZW3DoXRpY2FzIHBvciBHw6luZXJvLCBUaXBvIGRlIEFsbXVlcnpvIHkgTml2ZWwgZGUgRWR1Y2FjacOzbiBkZSBsb3MgcGFkcmVzIikNCmBgYA0KDQoNCg0KIyBQUlVFQkFTIERFIEhJUMOTVEVTSVMNCg0KIyMgMS4gwr9FeGlzdGUgdW5hIGluZmx1ZW5jaWEgZGVsIG5pdmVsIGVkdWNhdGl2byBkZSBsb3MgcGFkcmVzIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZWwgYWx1bW5vPw0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgQU5PVkEgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBtYXRlbcOhdGljYXMgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIE1hdGVtw6F0aWNhcyB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCisgSGlwb3Rlc2lzIGFsdGVybmF0aXZhIChIYSkgRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIE1hdGVtw6F0aWNhcyB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCmBgYHtyfQ0KcGFkcmVzX21hdGVtw6F0aWNhcyA8LSBhb3YobWF0aF9zY29yZSB+IHBhcmVudGFsX2xldmVsX29mX2VkdWNhdGlvbiwgZGF0YSA9IGRmKSAjUmVhbGl6YW1vcyBudWVzdHJhIHBydWViYSBhbm92YQ0Kc3VtbWFyeShwYWRyZXNfbWF0ZW3DoXRpY2FzKSAjTW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBNYXRlbcOhdGljYXMgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioNCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgQU5PVkEgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBsZWN0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBMZWN0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcy4NCg0KKyBIaXBvdGVzaXMgYWx0ZXJuYXRpdmEgKEhhKSBFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgTGVjdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCmBgYHtyfQ0KcGFkcmVzX2xlY3R1cmEgPC0gYW92KHJlYWRpbmdfc2NvcmUgfiBwYXJlbnRhbF9sZXZlbF9vZl9lZHVjYXRpb24sIGRhdGEgPSBkZikgI1JlYWxpemFtb3MgbnVlc3RyYSBwcnVlYmEgYW5vdmENCnN1bW1hcnkocGFkcmVzX2xlY3R1cmEpICNNb3N0cmFtb3MgZWwgcmVzdWx0YWRvDQpgYGANCioqTGEgaGlww7N0ZXNpcyBudWxhIHNlIGRlc2NhcnRhIHkgc2UgYWNlcHRhIGxhIGhpcMOzdGVzaXMgYWx0ZXJuYXRpdmEuKioNCioqRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIExlY3R1cmEgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioNCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgQU5PVkEgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBlc2NyaXR1cmEgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIEVzY3JpdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCisgSGlwb3Rlc2lzIGFsdGVybmF0aXZhIChIYSkgRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIEVzY3JpdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQpgYGB7cn0NCnBhZHJlc19lc2NyaXR1cmEgPC0gYW92KHdyaXRpbmdfc2NvcmUgfiBwYXJlbnRhbF9sZXZlbF9vZl9lZHVjYXRpb24sIGRhdGEgPSBkZikgI1JlYWxpemFtb3MgbnVlc3RyYSBwcnVlYmEgYW5vdmENCnN1bW1hcnkocGFkcmVzX2VzY3JpdHVyYSkgI21vc3RyYW1vcyBlbCByZXN1bHRhZG8NCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgRXNjcml0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqDQoNCiMjIDIuIMK/RXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGVudHJlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8/DQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxhIG1hdGVyaWEgZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBtYXRlbcOhdGljYXMgZGUgbG9zIGFsdW1ub3MgcXVlIHRvbWFyb24gZWwgY3Vyc28gZGUgcHJlcGFyYWNpw7NuIHkgbG9zIHF1ZSBuby4NCg0KKyBIaXDDs3Rlc2lzIGFsdGVybmF0aXZhIChIYSk6IEV4aXN0ZSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyBkZSBsb3MgYWx1bW5vcyBxdWUgdG9tYXJvbiBlbCBjdXJzbyBkZSBwcmVwYXJhY2nDs24geSBsb3MgcXVlIG5vLg0KYGBge3J9DQp0dGVzdF9tYXRlbcOhdGljYXMgPC0gdC50ZXN0KG1hdGhfc2NvcmUgfiB0ZXN0X3ByZXBhcmF0aW9uX2N1cnNlLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpICNSZWFsaXphbW9zIG51ZXN0cmEgcHJ1ZWJhIHRlc3QNCnR0ZXN0X21hdGVtw6F0aWNhcyAjbW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBNYXRlbcOhdGljYXMgY29uIGxvcyBhbHVtbm9zIHF1ZSBjb21wbGV0YXJvbmVsIGN1cnNvIGRlIHByZXBhcmFjacOzbioqDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxhIG1hdGVyaWEgZGUgZXNjcml0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhIGRlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8uDQoNCisgSGlww7N0ZXNpcyBhbHRlcm5hdGl2YSAoSGEpOiBFeGlzdGUgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhIGRlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8uDQoNCmBgYHtyfQ0KdHRlc3RfbGVjdHVyYSA8LSB0LnRlc3QocmVhZGluZ19zY29yZSB+IHRlc3RfcHJlcGFyYXRpb25fY3Vyc2UsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkgI1JlYWxpemFtb3MgbnVlc3RyYSBwcnVlYmEgdGVzdA0KdHRlc3RfbGVjdHVyYSAjbW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhIGNvbiBsb3MgYWx1bW5vcyBxdWUgY29tcGxldGFyb25lbCBjdXJzbyBkZSBwcmVwYXJhY2nDs24qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIGVzY3JpdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMqKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGRlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8uDQoNCisgSGlww7N0ZXNpcyBhbHRlcm5hdGl2YSAoSGEpOiBFeGlzdGUgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBlc2NyaXR1cmEgZGUgbG9zIGFsdW1ub3MgcXVlIHRvbWFyb24gZWwgY3Vyc28gZGUgcHJlcGFyYWNpw7NuIHkgbG9zIHF1ZSBuby4NCg0KYGBge3J9DQp0dGVzdF9lc2NyaXR1cmEgPC0gdC50ZXN0KHdyaXRpbmdfc2NvcmUgfiB0ZXN0X3ByZXBhcmF0aW9uX2N1cnNlLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpICNSZWFsaXphbW9zIG51ZXN0cmEgcHJ1ZWJhIHRlc3QNCnR0ZXN0X2VzY3JpdHVyYSAjbW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBlc2NyaXR1cmEgY29uIGxvcyBhbHVtbm9zIHF1ZSBjb21wbGV0YXJvbmVsIGN1cnNvIGRlIHByZXBhcmFjacOzbioqDQoNCiMjIDMuIMK/RXhpc3RlIHVuYSByZWxhY2nDs24gZW4gZWwgZGVzZW1wZcOxb3MgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxvcyBhbHVtbm9zIGVsIHRpcG8gZGUgbHVuY2g/DQogDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIG1hdGVtw6F0aWNhcyB5IGVsIHRpcG8gZGUgbHVuY2gqKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbWF0ZW3DoXRpY2FzIGVudHJlIGxvcyB0aXBvcyBkZSBsdW5jaC4NCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEhhKTogRXhpc3RlIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbWF0ZW3DoXRpY2FzIGVudHJlIGxvcyB0aXBvcyBkZSBsdW5jaC4NCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdChtYXRoX3Njb3JlIH4gbHVuY2gsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkNCnJlc3VsdGFkb190dGVzdA0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBtYXRlbcOhdGljYXMgY29uIGVsIHRpcG8gZGUgbHVuY2gqKg0KDQojIyMgRGVuc2lkYWQgZGUgY2FsaWZpY2FjaW9uZXMgZGUgbWF0ZW3DoXRpY2FzIGNvbiBlbCB0aXBvIGRlIGx1bmNoDQoNCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBEZW5zaWRhZCBwYXJhIENhbGlmaWNhY2lvbmVzIGRlIE1hdGVtw6F0aWNhcw0KZ2dwbG90KGRmLCBhZXMoeCA9IG1hdGhfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiRGVuc2lkYWQgZGUgQ2FsaWZpY2FjaW9uZXMgZGUgTWF0ZW3DoXRpY2FzIiwNCiAgICAgICB4ID0gIkNhbGlmaWNhY2nDs24gZGUgTWF0ZW3DoXRpY2FzIiwgeSA9ICJEZW5zaWRhZCIpDQpgYGANCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBlc2NyaXR1cmEgeSBlbCB0aXBvIGRlIGx1bmNoKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGVzY3JpdHVyYSBlbnRyZSBsb3MgdGlwb3MgZGUgbHVuY2guDQoNCisgSGlww7N0ZXNpcyBudWxhIChIYSk6IEV4aXN0ZSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGVzY3JpdHVyYSBlbnRyZSBsb3MgdGlwb3MgZGUgbHVuY2guDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdCh3cml0aW5nX3Njb3JlIH4gbHVuY2gsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkNCnJlc3VsdGFkb190dGVzdA0KYGBgDQojIyMgRGVuc2lkYWQgZGUgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGNvbiBlbCB0aXBvIGRlIGx1bmNoDQoNCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBEZW5zaWRhZCBwYXJhIENhbGlmaWNhY2lvbmVzIGRlIEVzY3JpdHVyYQ0KZ2dwbG90KGRmLCBhZXMoeCA9IHdyaXRpbmdfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiRGVuc2lkYWQgZGUgQ2FsaWZpY2FjaW9uZXMgZGUgRXNjcml0dXJhIiwNCiAgICAgICB4ID0gIkNhbGlmaWNhY2nDs24gZGUgRXNjcml0dXJhIiwgeSA9ICJEZW5zaWRhZCIpDQpgYGANCg0KDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBlc2NyaXR1cmEgY29uIGVsIHRpcG8gZGUgbHVuY2gqKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIGxlY3R1cmEgeSBlbCB0aXBvIGRlIGx1bmNoKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxlY3R1cmEgZW50cmUgbG9zIHRpcG9zIGRlIGx1bmNoLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhIGVudHJlIGxvcyB0aXBvcyBkZSBsdW5jaC4NCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdChyZWFkaW5nX3Njb3JlIH4gbHVuY2gsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkNCnJlc3VsdGFkb190dGVzdA0KYGBgDQojIyMgRGVuc2lkYWQgZGUgY2FsaWZpY2FjaW9uZXMgZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaA0KDQpgYGB7cn0NCiMgR3LDoWZpY28gZGUgRGVuc2lkYWQgcGFyYSBDYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gcmVhZGluZ19zY29yZSwgZmlsbCA9IGx1bmNoKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJEZW5zaWRhZCBkZSBDYWxpZmljYWNpb25lcyBkZSBMZWN0dXJhIiwNCiAgICAgICB4ID0gIkNhbGlmaWNhY2nDs24gZGUgRXNwYcOxb2wiLCB5ID0gIkRlbnNpZGFkIikNCg0KYGBgDQoNCg0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaCoqDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxhIG1hdGVyaWEgZGUgbGVjdHVyYSB5IGVsIHRpcG8gZGUgbHVuY2ggeSBlbCBnw6luZXJvKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIGxlY3R1cmEsIGVsIHRpcG8gZGUgbHVuY2ggeSBlbCBnw6luZXJvLi4NCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEhhKTogRXhpc3RlIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSwgZWwgdGlwbyBkZSBsdW5jaCB5IGVsIGfDqW5lcm8uDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3YocmVhZGluZ19zY29yZSB+IGx1bmNoICsgZ2VuZGVyLCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaCB5IGVsIGfDqW5lcm8qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBBTk9WQSBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIGxlY3R1cmEgeSBlbCB0aXBvIGRlIGx1bmNoIHkgIGVsIGN1cnNvIGRlIHByZXBhcmFjaW9uLioqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhLCBlbCB0aXBvIGRlIGx1bmNoIHkgY3Vyc28gZGUgcHJlcGFyYWNpb24uLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhLCBlbCB0aXBvIGRlIGx1bmNoIHkgZWwgY3Vyc28gZGUgcHJlcGFyYWNpb24uDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX2Fub3ZhIDwtIGFvdihyZWFkaW5nX3Njb3JlIH4gbHVuY2ggKyB0ZXN0X3ByZXBhcmF0aW9uX2N1cnNlLCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaCB5IGVsIGN1cnNvIGRlIHByZXBhcmFjaW9uICoqDQoNCiMjIDQuIMK/SW5mbHV5ZSBlbCB0aXBvIGRlIGfDqW5lcm8gZGUgbG9zIGFsdW1ub3MgZW4gZWwgZGVzZW1wZcOxbyBkZSBsb3MgYWx1bW5vcz8NCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgdCBwYXJhIGNvbXBhcmFyIGxhcyBtZWRpYXMgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyBlbnRyZSBsb3MgZ8OpbmVyb3MuKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyBlbnRyZSBsb3MgZ8OpbmVyb3MuDQoNCisgSGlww7N0ZXNpcyBudWxhIChIYSk6IEV4aXN0ZSB1bmEgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBtYXRlbcOhdGljYXMgZW50cmUgbG9zIGfDqW5lcm9zLg0KDQpgYGB7cn0NCnJlc3VsdGFkb190dGVzdCA8LSB0LnRlc3QobWF0aF9zY29yZSB+IGdlbmRlciwgZGF0YSA9IGRmLCBjb25mLmxldmVsPSAwLjk5KQ0KcmVzdWx0YWRvX3R0ZXN0DQpgYGANCioqTGEgaGlww7N0ZXNpcyBudWxhIHNlIGRlc2NhcnRhIHkgc2UgYWNlcHRhIGxhIGhpcMOzdGVzaXMgYWx0ZXJuYXRpdmEuKioNCioqRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIG1hdGVtw6F0aWNhcyB5IGVsIGfDqW5lcm8qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyB0IHBhcmEgY29tcGFyYXIgbGFzIG1lZGlhcyBkZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGVjdHVyYSBlbnRyZSBsb3MgZ8OpbmVyb3MuKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxlY3R1cmEgZW50cmUgbG9zIGfDqW5lcm9zLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgdW5hIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGVjdHVyYSBlbnRyZSBsb3MgZ8OpbmVyb3MuDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdChyZWFkaW5nX3Njb3JlIH4gZ2VuZGVyLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpDQpyZXN1bHRhZG9fdHRlc3QNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSB5IGVsIGfDqW5lcm8qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyB0IHBhcmEgY29tcGFyYXIgbGFzIG1lZGlhcyBkZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGVudHJlIGxvcyBnw6luZXJvcy4qKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGVudHJlIGxvcyBnw6luZXJvcy4NCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEhhKTogRXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGVzY3JpdHVyYSBlbnRyZSBsb3MgZ8OpbmVyb3MuDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdCh3cml0aW5nX3Njb3JlIH4gZ2VuZGVyLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpDQpyZXN1bHRhZG9fdHRlc3QNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ8OpbmVybyoqDQoNCmBgYHtyfQ0KIyBDYWxjdWxhciBwcm9tZWRpb3MgZW4gdW5hIGVzY2FsYSBkZSAwIGEgMTAwDQpkZl9wcm9tZWRpb3MgPC0gZGYgJT4lDQogIGdyb3VwX2J5KHJhY2VfZXRobmljaXR5KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fbWF0aF9zY29yZSA9IG1lYW4obWF0aF9zY29yZSkgKiAxMDAgLyBtYXgoZGYkbWF0aF9zY29yZSksDQogICAgbWVhbl9yZWFkaW5nX3Njb3JlID0gbWVhbihyZWFkaW5nX3Njb3JlKSAqIDEwMCAvIG1heChkZiRyZWFkaW5nX3Njb3JlKSwNCiAgICBtZWFuX3dyaXRpbmdfc2NvcmUgPSBtZWFuKHdyaXRpbmdfc2NvcmUpICogMTAwIC8gbWF4KGRmJHdyaXRpbmdfc2NvcmUpDQogICkNCg0KIyBDcmVhciB1biBncsOhZmljbyBkZSBiYXJyYXMgYWdydXBhZGFzIGNvbiBwbG90bHkNCmdyYWZpY29fYmFycmFzX3Bsb3RseSA8LSBwbG90X2x5KGRmX3Byb21lZGlvcywgeCA9IH5yYWNlX2V0aG5pY2l0eSkgJT4lDQogIGFkZF90cmFjZSh5ID0gfm1lYW5fbWF0aF9zY29yZSwgbmFtZSA9ICdNYXRoJywgdHlwZSA9ICdiYXInLCBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2xpZ2h0Ymx1ZScpKSAlPiUNCiAgYWRkX3RyYWNlKHkgPSB+bWVhbl9yZWFkaW5nX3Njb3JlLCBuYW1lID0gJ1JlYWRpbmcnLCB0eXBlID0gJ2JhcicsIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnbGlnaHRncmVlbicpKSAlPiUNCiAgYWRkX3RyYWNlKHkgPSB+bWVhbl93cml0aW5nX3Njb3JlLCBuYW1lID0gJ1dyaXRpbmcnLCB0eXBlID0gJ2JhcicsIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnbGlnaHRwaW5rJykpICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSAnRGVzZW1wZcOxbyBkZSBFc3R1ZGlhbnRlcyBwb3IgR3J1cG8gw4l0bmljbyAoUHJvbWVkaW9zIGVuIEVzY2FsYSBkZSAwIGEgMTAwKScsDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0dydXBvIMOJdG5pY28nKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnQ2FsaWZpY2FjacOzbiBQcm9tZWRpbycsIHJhbmdlID0gYygwLCAxMDApKSwNCiAgICBiYXJtb2RlID0gJ2dyb3VwJw0KICApDQojIFZpc3VhbGl6YXIgZWwgZ3LDoWZpY28NCmdyYWZpY29fYmFycmFzX3Bsb3RseQ0KYGBgDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIEFOT1ZBIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyB5IGVsIGdydXBvIHNvY2lhbCBhbCBxdWUgcGVydGVuZWNlbi4qKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3YobWF0aF9zY29yZSB+IHJhY2VfZXRobmljaXR5LCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLioqDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIEFOT1ZBIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxlY3R1cmEgeSBlbCBncnVwbyBzb2NpYWwgYWwgcXVlIHBlcnRlbmVjZW4uKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIGxlY3R1cmEgeSBlbCBncnVwbyBzb2NpYWwgYWwgcXVlIHBlcnRlbmVjZW4uDQoNCisgSGlww7N0ZXNpcyBudWxhIChIYSk6IEV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3YocmVhZGluZ19zY29yZSB+IHJhY2VfZXRobmljaXR5LCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSB5IGVsIGdydXBvIHNvY2lhbCBhbCBxdWUgcGVydGVuZWNlbi4qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBBTk9WQSBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBlc2NyaXR1cmEgeSBlbCBncnVwbyBzb2NpYWwgYWwgcXVlIHBlcnRlbmVjZW4uKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6Tm8gaGF5IHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3Yod3JpdGluZ19zY29yZSB+IHJhY2VfZXRobmljaXR5LCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLioqDQoNCg0KIyBDT05DTFVTSU9ORVMNCg0KRGUgYWN1ZXJkbyBjb24gbGFzIGRpc3RpbnRhcyBwcnVlYmFzIHJlYWxpemFkYXMgdGFudG8gbGEgcHJ1ZWJhIHQgeSBsYSBwcnVlYmEgQU5PVkEgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIHNpIGV4aXN0ZSB1bmEgaW5mbHVlbmNpYSBzaWduaWZpY2F0aXZhIGVudHJlIGxvcyBmYWN0b3JlczsgIk5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcyIsICJDdXJzbyBkZSBwcmVwYXJhY2nDs24gcGFyYSBlbCBleGFtZW4iLCAiVGlwbyBkZSBhbG11ZXJ6byIgeSAiUmF6YSIsIGNvbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbG9zIGFsdW1ub3MuDQpBZGVtw6FzIHNpZW5kbyBlbCBnZW5lcm8gZmVtZW5pbm8gcXVpZW4gb2J0dXZvIHVuIHByb21lZGlvIG1hcyBhbHRvIGVuIHN1cyBjYWxpZmljYWNpb25lcy4gDQoNCg0K