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:
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.
LS0tDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgICB0aGVtZTogZmxhdGx5DQogICAgICB0b2M6IHRydWUNCiAgICAgIHRvY19mbG9hdDoNCiAgICAgICAgY29sbGFwc2VkOiB0cnVlDQogICAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlDQotLS0NCiMgIkRFU0VNUEXDkU8gREUgTE9TIEVTVFVESUFOVEVTIEVOIExPUyBFWEFNRU5FUyIgDQoNCioqKkVxdWlwbyBObzogMTMqKioNCg0KKioqSW50ZWdyYW50ZXMqKioNCg0KKyBPc2NhciBEYW5pZWwgQmV0YW5jb3VydA0KDQorIERpZWdvIElzYWlhcyBMw7NwZXogVGFwaWENCg0KKyBKdWFuIERhbmllbCBDYXJyaWxsbyBNZXJjYWRvDQoNCisgQ2FybG9zIEpvZWwgZGUgbGEgUm9zYSBIZXJuw6FuZGV6IA0KDQojIyMgSW50cm9kdWNjacOzbiANClBvciBtZWRpbyBkZSB1biBjb25qdW50byBkZSBkYXRvcywgY29uZm9ybWFkbyBwb3IgbGFzIGNhbGlmaWNhY2lvbmVzIG9idGVuaWRhcyBkZSBsb3MgZXN0dWRpYW50ZXMgZW4gYXNpZ25hdHVyYXMgY29tbyBtYXRlbcOhdGljYXMsIGxlY3R1cmEgeSBlc2NyaXR1cmEsIGRldGVybWluYXIgc2kgZGlmZXJlbnRlcyBmYWN0b3JlcyBxdWUgaW5jbHV5ZSBlbCBjb25qdW50byBkZSBkYXRvcyBpbmZsdXllbiBlbiBlbCByZXN1bHRhZG8gZGUgbG9zIGV4w6FtZW5lcy4gDQoNCkxvcyBmYWN0b3JlcyBzb246DQoNCiogKipOaXZlbCBkZSBlZHVjYWNpw7NuIGRlIGxvcyBwYWRyZXMuKioNCg0KKiAqKkN1cnNvIGRlIHByZXBhcmFjacOzbiBwYXJhIGVsIGV4YW1lbioqDQoNCiogKipUaXBvIGRlIGFsbXVlcnpvKioNCg0KKiAqKlJhemEqKg0KDQpFbCBjb25qdW50byBkZSBkYXRvcyBmdWUgb2J0ZW5pZG8gZGUgW0thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9zcHNjaWVudGlzdC9zdHVkZW50cy1wZXJmb3JtYW5jZS1pbi1leGFtcykNCg0KIyMjIyBQYXJhIGVzdG8sIHJlYWxpemFyZW1vcyB1bmEgc2VyaWUgZGUgcHJlZ3VudGFzIGNvbiByZXNwZWN0byBhIGxvcyBmYWN0b3JlcyBtZW5jaW9uYWRvcyBhbnRlcmlvcm1lbnRlIHBhcmEgbGEgZm9ybXVsYWNpw7NuIGRlIGhpcMOzdGVzaXMNCioqMS4gwr9FeGlzdGUgdW5hIGluZmx1ZW5jaWEgZGVsIG5pdmVsIGVkdWNhdGl2byBkZSBsb3MgcGFkcmVzIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZWwgYWx1bW5vPyoqDQoNCisgTWF0ZW3DoXRpY2FzDQorIExlY3R1cmENCisgRXNjcml0dXJhDQoNCioqMi4gwr9FeGlzdGUgdW5hIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBkZSBsYXMgY2FsaWZpY2FjaW9uZXMgZW50cmUgbG9zIGFsdW1ub3MgcXVlIHRvbWFyb24gZWwgY3Vyc28gZGUgcHJlcGFyYWNpw7NuIHkgbG9zIHF1ZSBubz8qKg0KDQorIE1hdGVtw6F0aWNhcw0KKyBMZWN0dXJhDQorIEVzY3JpdHVyYQ0KDQoqKjMuIMK/RXhpc3RlIHVuYSByZWxhY2nDs24gZW4gZWwgZGVzZW1wZcOxb3MgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxvcyBhbHVtbm9zIGVsIHRpcG8gZGUgbHVuY2g/ICoqDQoNCisgTWF0ZW3DoXRpY2FzDQorIExlY3R1cmENCisgRXNjcml0dXJhDQoNCioqNC4gwr9JbmZsdXllIGVsIHRpcG8gZGUgcmF6YSBkZSBsb3MgYWx1bW5vcyBlbiBlbCBkZXNlbXBlw7FvIGRlIGxvcyBhbHVtbm9zPyoqDQoNCisgTWF0ZW3DoXRpY2FzDQorIExlY3R1cmENCisgRXNjcml0dXJhDQoNCiMgQ2FyZ2EgZGUgRGF0b3MgeSBBbsOhbGlzaXMgRXhwbG9yYXRvcmlvDQpJbmljaWFtb3MgbnVlc3RybyBjw7NkaWdvIGNhcmdhbmRvIGxhcyBsaWJyZXJpYXMgcXVlIG5lY2VzaXRhcmVtb3MsIGFzw60gY29tbyBudWVzdHJvIGNvbmp1bnRvIGRlIGRhdG9zDQpgYGB7cn0NCiNDYXJnYW1vcyBsYSBsaWJyZXJpYSBwYXJhIGxlZXIgZWwgZGF0YXNldA0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCiNBc2lnbmFtb3MgYSBsYSB2YXJpYWJsZSBkZiBsYSBsZWN0dXJhIGRlIG51ZXN0cm8gYXJjaGl2byBleGFtcy54bHMNCmRmPC1yZWFkX2V4Y2VsKGZpbGUuY2hvb3NlKCkpDQojT2JzZXJ2YW1vcyBlbCBkYXRhc2V0DQpoZWFkKGRmKQ0KYGBgDQojIyBEZWZpbmljacOzbiBkZWwgZGF0YXNldA0KKiBMYSBjb2x1bW5hIF9nZW5kZXJfIG11ZXN0cmEgaW5mb3JtYWNpw7NuIGRlbCB0aXBvIGRlIGfDqW5lcm8gZGVsIGFsdW1ubw0KDQoqIExhIGNvbHVtbmEgX3JhY2VfZXRobmljaXR5XyBtdWVzdHJhIGxhIGluZm9ybWFjaW9uIGNsYXNpZmljYWRhIHBvciBncnVwbzoNCiAgDQogICsgX2dyb3VwXyBfQTpfIENsYXNlIGFsdGENCiAgDQogICsgX2dyb3VwXyBfQjpfIENsYXNlIG1lZGlhLWFsdGENCiAgDQogICsgX2dyb3VwXyBfQzpfIENsYXNlIG1lZGlhDQogIA0KICArIF9ncm91cF8gX0Q6XyBDbGFzZSBtZWRpYS1iYWphDQogIA0KICArIF9ncm91cF8gX0U6XyBDbGFzZSBiYWphDQoNCiogTGEgY29sdW1uYSBfcGFyZW50YWxfbGV2ZWxfb2ZfZWR1Y2F0aW9uXyBtdWVzdHJhIGluZm9ybWFjacOzbiBkZWwgZ3JhZG8gZGUgZXN0dWRpbyBkZSBsb3MgcGFkcmVzDQoNCiogTGEgY29sdW1uYSBfbHVuY2hfIG11ZXN0cmEgaW5mb3JtYWNpw7NuIGRlbCB0aXBvIGRlIGFsaW1lbnRhY2nDs24gZGUgbG9zIGFsdW1ub3MNCg0KKiBMYSBjb2x1bW5hIF90ZXN0X3ByZXBhcmF0aW9uX2N1cnNlXyBtdWVzdHJhIGluZm9ybWFjacOzbiBzaSBsb3MgYWx1bW5vcyB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbg0KDQoqIExhcyBjYWxpZmljYWNpb25lcyBkZSBsYXMgbWF0ZXJpYXMgc2UgZW5jdWVudHJhbiBlbiB1biBlc3RhbmRhciBkZWwgMSBhbCAxMDANCg0KDQoNCiMjIEFuw6FsaXNpcyBkZSBsb3MgZGF0b3MNCmBgYHtyfQ0KZ2dwbG90KGRmLGFlcyhnZW5kZXIpICkrDQogIGdlb21fYmFyKHdpZHRoPSAwLjUsY29sb3VyPSJyZWQiLCBmaWxsPSJza3libHVlIikrDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsNjAwKSwNCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLDEwMDAsMTAwMCkpKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgZXN0dWRpYW50ZXMgSG9tYnJlcyB5IE11amVyZXMiLA0KICAgICAgIHg9ImfDqW5lcm8iLA0KICAgICAgIHk9ICJBbHVtbm9zIikrDQogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSsNCiAgDQogIGdlb21fdGV4dChhZXMobGFiZWw9Li5jb3VudC4uKSwgc3RhdD0nY291bnQnLCANCiAgICAgICAgICAgIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKDAuOSksIA0KICAgICAgICAgICAgdmp1c3Q9LTAuNSwgDQogICAgICAgICAgICBzaXplPTUuMA0KICAgICAgICAgICAgKSANCmBgYA0KDQpgYGB7cn0NCiMgR3LDoWZpY28gZGUgYmFycmFzIHBhcmEgY29tcGFyYXIgZWwgZGVzZW1wZcOxbyBlbiBtYXRlbcOhdGljYXMgc2Vnw7puIGVsIG5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcw0KZ2dwbG90KGRmLCBhZXMoeCA9IHBhcmVudGFsX2xldmVsX29mX2VkdWNhdGlvbiwgeSA9IG1hdGhfc2NvcmUpKSArDQogIGdlb21fYmFyKHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWFuIikgKw0KICBsYWJzKHRpdGxlID0gIkRlc2VtcGXDsW8gZW4gTWF0ZW3DoXRpY2FzIHNlZ8O6biBOaXZlbCBkZSBFZHVjYWNpw7NuIGRlIGxvcyBQYWRyZXMiLCB4ID0gIk5pdmVsIGRlIEVkdWNhY2nDs24gZGUgbG9zIFBhZHJlcyIsIHkgPSAiQ2FsaWZpY2FjacOzbiBQcm9tZWRpbyBlbiBNYXRlbcOhdGljYXMiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBiYXJyYXMgYXBpbGFkYXMgY29uIGZhY2V0YXMgcG9yIG5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcw0KZ2dwbG90KGRmLCBhZXMoeCA9IGdlbmRlciwgeSA9IG1hdGhfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgQ2FsaWZpY2FjaW9uZXMgZGUgTWF0ZW3DoXRpY2FzIHBvciBHw6luZXJvLCBUaXBvIGRlIEFsbXVlcnpvIHkgTml2ZWwgZGUgRWR1Y2FjacOzbiBkZSBsb3MgUGFkcmVzIiwgDQogICAgICAgeCA9ICJHw6luZXJvIiwgeSA9ICJDYWxpZmljYWNpb25lcyBkZSBNYXRlbcOhdGljYXMiLCBmaWxsID0gIlRpcG8gZGUgQWxtdWVyem8iKSArDQogIGZhY2V0X3dyYXAofiBwYXJlbnRhbF9sZXZlbF9vZl9lZHVjYXRpb24sIHNjYWxlcyA9ICJmcmVlX3kiLCBuY29sID0gMikgICMgRmFjZXRhcyBwb3Igbml2ZWwgZGUgZWR1Y2FjacOzbiBkZSBsb3MgcGFkcmVzDQpgYGANCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBiYXJyYXMgYXBpbGFkYXMgY29uIGZhY2V0YXMgcG9yIG5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcw0KZ2dwbG90KGRmLCBhZXMoeCA9IGdlbmRlciwgeSA9IG1hdGhfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgQ2FsaWZpY2FjaW9uZXMgZGUgTWF0ZW3DoXRpY2FzIHBvciBHw6luZXJvLCBUaXBvIGRlIEFsbXVlcnpvIHkgTml2ZWwgZGUgRWR1Y2FjacOzbiBkZSBsb3MgcGFkcmVzIikNCmBgYA0KDQoNCg0KIyBQUlVFQkFTIERFIEhJUMOTVEVTSVMNCg0KIyMgMS4gwr9FeGlzdGUgdW5hIGluZmx1ZW5jaWEgZGVsIG5pdmVsIGVkdWNhdGl2byBkZSBsb3MgcGFkcmVzIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZWwgYWx1bW5vPw0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgQU5PVkEgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBtYXRlbcOhdGljYXMgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIE1hdGVtw6F0aWNhcyB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCisgSGlwb3Rlc2lzIGFsdGVybmF0aXZhIChIYSkgRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIE1hdGVtw6F0aWNhcyB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCmBgYHtyfQ0KcGFkcmVzX21hdGVtw6F0aWNhcyA8LSBhb3YobWF0aF9zY29yZSB+IHBhcmVudGFsX2xldmVsX29mX2VkdWNhdGlvbiwgZGF0YSA9IGRmKSAjUmVhbGl6YW1vcyBudWVzdHJhIHBydWViYSBhbm92YQ0Kc3VtbWFyeShwYWRyZXNfbWF0ZW3DoXRpY2FzKSAjTW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBNYXRlbcOhdGljYXMgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioNCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgQU5PVkEgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBsZWN0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBMZWN0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcy4NCg0KKyBIaXBvdGVzaXMgYWx0ZXJuYXRpdmEgKEhhKSBFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgTGVjdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCmBgYHtyfQ0KcGFkcmVzX2xlY3R1cmEgPC0gYW92KHJlYWRpbmdfc2NvcmUgfiBwYXJlbnRhbF9sZXZlbF9vZl9lZHVjYXRpb24sIGRhdGEgPSBkZikgI1JlYWxpemFtb3MgbnVlc3RyYSBwcnVlYmEgYW5vdmENCnN1bW1hcnkocGFkcmVzX2xlY3R1cmEpICNNb3N0cmFtb3MgZWwgcmVzdWx0YWRvDQpgYGANCioqTGEgaGlww7N0ZXNpcyBudWxhIHNlIGRlc2NhcnRhIHkgc2UgYWNlcHRhIGxhIGhpcMOzdGVzaXMgYWx0ZXJuYXRpdmEuKioNCioqRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIExlY3R1cmEgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioNCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgQU5PVkEgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBlc2NyaXR1cmEgeSBlbCBncmFkbyBkZSBlc3R1ZGlvcyBkZSBsb3MgcGFkcmVzKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIEVzY3JpdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQoNCisgSGlwb3Rlc2lzIGFsdGVybmF0aXZhIChIYSkgRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIEVzY3JpdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMuDQpgYGB7cn0NCnBhZHJlc19lc2NyaXR1cmEgPC0gYW92KHdyaXRpbmdfc2NvcmUgfiBwYXJlbnRhbF9sZXZlbF9vZl9lZHVjYXRpb24sIGRhdGEgPSBkZikgI1JlYWxpemFtb3MgbnVlc3RyYSBwcnVlYmEgYW5vdmENCnN1bW1hcnkocGFkcmVzX2VzY3JpdHVyYSkgI21vc3RyYW1vcyBlbCByZXN1bHRhZG8NCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgRXNjcml0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqDQoNCiMjIDIuIMK/RXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGVudHJlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8/DQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxhIG1hdGVyaWEgZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBtYXRlbcOhdGljYXMgZGUgbG9zIGFsdW1ub3MgcXVlIHRvbWFyb24gZWwgY3Vyc28gZGUgcHJlcGFyYWNpw7NuIHkgbG9zIHF1ZSBuby4NCg0KKyBIaXDDs3Rlc2lzIGFsdGVybmF0aXZhIChIYSk6IEV4aXN0ZSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyBkZSBsb3MgYWx1bW5vcyBxdWUgdG9tYXJvbiBlbCBjdXJzbyBkZSBwcmVwYXJhY2nDs24geSBsb3MgcXVlIG5vLg0KYGBge3J9DQp0dGVzdF9tYXRlbcOhdGljYXMgPC0gdC50ZXN0KG1hdGhfc2NvcmUgfiB0ZXN0X3ByZXBhcmF0aW9uX2N1cnNlLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpICNSZWFsaXphbW9zIG51ZXN0cmEgcHJ1ZWJhIHRlc3QNCnR0ZXN0X21hdGVtw6F0aWNhcyAjbW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBNYXRlbcOhdGljYXMgY29uIGxvcyBhbHVtbm9zIHF1ZSBjb21wbGV0YXJvbmVsIGN1cnNvIGRlIHByZXBhcmFjacOzbioqDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxhIG1hdGVyaWEgZGUgZXNjcml0dXJhIHkgZWwgZ3JhZG8gZGUgZXN0dWRpb3MgZGUgbG9zIHBhZHJlcyoqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhIGRlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8uDQoNCisgSGlww7N0ZXNpcyBhbHRlcm5hdGl2YSAoSGEpOiBFeGlzdGUgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhIGRlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8uDQoNCmBgYHtyfQ0KdHRlc3RfbGVjdHVyYSA8LSB0LnRlc3QocmVhZGluZ19zY29yZSB+IHRlc3RfcHJlcGFyYXRpb25fY3Vyc2UsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkgI1JlYWxpemFtb3MgbnVlc3RyYSBwcnVlYmEgdGVzdA0KdHRlc3RfbGVjdHVyYSAjbW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhIGNvbiBsb3MgYWx1bW5vcyBxdWUgY29tcGxldGFyb25lbCBjdXJzbyBkZSBwcmVwYXJhY2nDs24qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIGVzY3JpdHVyYSB5IGVsIGdyYWRvIGRlIGVzdHVkaW9zIGRlIGxvcyBwYWRyZXMqKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGRlIGxvcyBhbHVtbm9zIHF1ZSB0b21hcm9uIGVsIGN1cnNvIGRlIHByZXBhcmFjacOzbiB5IGxvcyBxdWUgbm8uDQoNCisgSGlww7N0ZXNpcyBhbHRlcm5hdGl2YSAoSGEpOiBFeGlzdGUgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBlc2NyaXR1cmEgZGUgbG9zIGFsdW1ub3MgcXVlIHRvbWFyb24gZWwgY3Vyc28gZGUgcHJlcGFyYWNpw7NuIHkgbG9zIHF1ZSBuby4NCg0KYGBge3J9DQp0dGVzdF9lc2NyaXR1cmEgPC0gdC50ZXN0KHdyaXRpbmdfc2NvcmUgfiB0ZXN0X3ByZXBhcmF0aW9uX2N1cnNlLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpICNSZWFsaXphbW9zIG51ZXN0cmEgcHJ1ZWJhIHRlc3QNCnR0ZXN0X2VzY3JpdHVyYSAjbW9zdHJhbW9zIGVsIHJlc3VsdGFkbw0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBlc2NyaXR1cmEgY29uIGxvcyBhbHVtbm9zIHF1ZSBjb21wbGV0YXJvbmVsIGN1cnNvIGRlIHByZXBhcmFjacOzbioqDQoNCiMjIDMuIMK/RXhpc3RlIHVuYSByZWxhY2nDs24gZW4gZWwgZGVzZW1wZcOxb3MgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxvcyBhbHVtbm9zIGVsIHRpcG8gZGUgbHVuY2g/DQogDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIG1hdGVtw6F0aWNhcyB5IGVsIHRpcG8gZGUgbHVuY2gqKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbWF0ZW3DoXRpY2FzIGVudHJlIGxvcyB0aXBvcyBkZSBsdW5jaC4NCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEhhKTogRXhpc3RlIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbWF0ZW3DoXRpY2FzIGVudHJlIGxvcyB0aXBvcyBkZSBsdW5jaC4NCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdChtYXRoX3Njb3JlIH4gbHVuY2gsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkNCnJlc3VsdGFkb190dGVzdA0KYGBgDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBtYXRlbcOhdGljYXMgY29uIGVsIHRpcG8gZGUgbHVuY2gqKg0KDQojIyMgRGVuc2lkYWQgZGUgY2FsaWZpY2FjaW9uZXMgZGUgbWF0ZW3DoXRpY2FzIGNvbiBlbCB0aXBvIGRlIGx1bmNoDQoNCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBEZW5zaWRhZCBwYXJhIENhbGlmaWNhY2lvbmVzIGRlIE1hdGVtw6F0aWNhcw0KZ2dwbG90KGRmLCBhZXMoeCA9IG1hdGhfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiRGVuc2lkYWQgZGUgQ2FsaWZpY2FjaW9uZXMgZGUgTWF0ZW3DoXRpY2FzIiwNCiAgICAgICB4ID0gIkNhbGlmaWNhY2nDs24gZGUgTWF0ZW3DoXRpY2FzIiwgeSA9ICJEZW5zaWRhZCIpDQpgYGANCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgcGFyYSBldmFsdWFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGEgbWF0ZXJpYSBkZSBlc2NyaXR1cmEgeSBlbCB0aXBvIGRlIGx1bmNoKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGVzY3JpdHVyYSBlbnRyZSBsb3MgdGlwb3MgZGUgbHVuY2guDQoNCisgSGlww7N0ZXNpcyBudWxhIChIYSk6IEV4aXN0ZSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGVzY3JpdHVyYSBlbnRyZSBsb3MgdGlwb3MgZGUgbHVuY2guDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdCh3cml0aW5nX3Njb3JlIH4gbHVuY2gsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkNCnJlc3VsdGFkb190dGVzdA0KYGBgDQojIyMgRGVuc2lkYWQgZGUgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGNvbiBlbCB0aXBvIGRlIGx1bmNoDQoNCmBgYHtyfQ0KIyBHcsOhZmljbyBkZSBEZW5zaWRhZCBwYXJhIENhbGlmaWNhY2lvbmVzIGRlIEVzY3JpdHVyYQ0KZ2dwbG90KGRmLCBhZXMoeCA9IHdyaXRpbmdfc2NvcmUsIGZpbGwgPSBsdW5jaCkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiRGVuc2lkYWQgZGUgQ2FsaWZpY2FjaW9uZXMgZGUgRXNjcml0dXJhIiwNCiAgICAgICB4ID0gIkNhbGlmaWNhY2nDs24gZGUgRXNjcml0dXJhIiwgeSA9ICJEZW5zaWRhZCIpDQpgYGANCg0KDQoqKkxhIGhpcMOzdGVzaXMgbnVsYSBzZSBkZXNjYXJ0YSB5IHNlIGFjZXB0YSBsYSBoaXDDs3Rlc2lzIGFsdGVybmF0aXZhLioqDQoqKkV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBlc2NyaXR1cmEgY29uIGVsIHRpcG8gZGUgbHVuY2gqKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIGxlY3R1cmEgeSBlbCB0aXBvIGRlIGx1bmNoKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxlY3R1cmEgZW50cmUgbG9zIHRpcG9zIGRlIGx1bmNoLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhIGVudHJlIGxvcyB0aXBvcyBkZSBsdW5jaC4NCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdChyZWFkaW5nX3Njb3JlIH4gbHVuY2gsIGRhdGEgPSBkZiwgY29uZi5sZXZlbD0gMC45OSkNCnJlc3VsdGFkb190dGVzdA0KYGBgDQojIyMgRGVuc2lkYWQgZGUgY2FsaWZpY2FjaW9uZXMgZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaA0KDQpgYGB7cn0NCiMgR3LDoWZpY28gZGUgRGVuc2lkYWQgcGFyYSBDYWxpZmljYWNpb25lcyBkZSBsZWN0dXJhDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gcmVhZGluZ19zY29yZSwgZmlsbCA9IGx1bmNoKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJEZW5zaWRhZCBkZSBDYWxpZmljYWNpb25lcyBkZSBMZWN0dXJhIiwNCiAgICAgICB4ID0gIkNhbGlmaWNhY2nDs24gZGUgRXNwYcOxb2wiLCB5ID0gIkRlbnNpZGFkIikNCg0KYGBgDQoNCg0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaCoqDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxhIG1hdGVyaWEgZGUgbGVjdHVyYSB5IGVsIHRpcG8gZGUgbHVuY2ggeSBlbCBnw6luZXJvKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIGxlY3R1cmEsIGVsIHRpcG8gZGUgbHVuY2ggeSBlbCBnw6luZXJvLi4NCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEhhKTogRXhpc3RlIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSwgZWwgdGlwbyBkZSBsdW5jaCB5IGVsIGfDqW5lcm8uDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3YocmVhZGluZ19zY29yZSB+IGx1bmNoICsgZ2VuZGVyLCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaCB5IGVsIGfDqW5lcm8qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBBTk9WQSBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBsYSBtYXRlcmlhIGRlIGxlY3R1cmEgeSBlbCB0aXBvIGRlIGx1bmNoIHkgIGVsIGN1cnNvIGRlIHByZXBhcmFjaW9uLioqKg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSDApOiBObyBoYXkgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhLCBlbCB0aXBvIGRlIGx1bmNoIHkgY3Vyc28gZGUgcHJlcGFyYWNpb24uLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhLCBlbCB0aXBvIGRlIGx1bmNoIHkgZWwgY3Vyc28gZGUgcHJlcGFyYWNpb24uDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX2Fub3ZhIDwtIGFvdihyZWFkaW5nX3Njb3JlIH4gbHVuY2ggKyB0ZXN0X3ByZXBhcmF0aW9uX2N1cnNlLCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSBjb24gZWwgdGlwbyBkZSBsdW5jaCB5IGVsIGN1cnNvIGRlIHByZXBhcmFjaW9uICoqDQoNCiMjIDQuIMK/SW5mbHV5ZSBlbCB0aXBvIGRlIGfDqW5lcm8gZGUgbG9zIGFsdW1ub3MgZW4gZWwgZGVzZW1wZcOxbyBkZSBsb3MgYWx1bW5vcz8NCg0KKioqUHJ1ZWJhIGRlIGhpcMOzdGVzaXMgdCBwYXJhIGNvbXBhcmFyIGxhcyBtZWRpYXMgZGUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyBlbnRyZSBsb3MgZ8OpbmVyb3MuKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyBlbnRyZSBsb3MgZ8OpbmVyb3MuDQoNCisgSGlww7N0ZXNpcyBudWxhIChIYSk6IEV4aXN0ZSB1bmEgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVuIGxhcyBjYWxpZmljYWNpb25lcyBkZSBtYXRlbcOhdGljYXMgZW50cmUgbG9zIGfDqW5lcm9zLg0KDQpgYGB7cn0NCnJlc3VsdGFkb190dGVzdCA8LSB0LnRlc3QobWF0aF9zY29yZSB+IGdlbmRlciwgZGF0YSA9IGRmLCBjb25mLmxldmVsPSAwLjk5KQ0KcmVzdWx0YWRvX3R0ZXN0DQpgYGANCioqTGEgaGlww7N0ZXNpcyBudWxhIHNlIGRlc2NhcnRhIHkgc2UgYWNlcHRhIGxhIGhpcMOzdGVzaXMgYWx0ZXJuYXRpdmEuKioNCioqRXhpc3RlIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIG1hdGVtw6F0aWNhcyB5IGVsIGfDqW5lcm8qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyB0IHBhcmEgY29tcGFyYXIgbGFzIG1lZGlhcyBkZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGVjdHVyYSBlbnRyZSBsb3MgZ8OpbmVyb3MuKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxlY3R1cmEgZW50cmUgbG9zIGfDqW5lcm9zLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgdW5hIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbGVjdHVyYSBlbnRyZSBsb3MgZ8OpbmVyb3MuDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdChyZWFkaW5nX3Njb3JlIH4gZ2VuZGVyLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpDQpyZXN1bHRhZG9fdHRlc3QNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSB5IGVsIGfDqW5lcm8qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyB0IHBhcmEgY29tcGFyYXIgbGFzIG1lZGlhcyBkZSBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGVudHJlIGxvcyBnw6luZXJvcy4qKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgZXNjcml0dXJhIGVudHJlIGxvcyBnw6luZXJvcy4NCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEhhKTogRXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW4gbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGVzY3JpdHVyYSBlbnRyZSBsb3MgZ8OpbmVyb3MuDQoNCmBgYHtyfQ0KcmVzdWx0YWRvX3R0ZXN0IDwtIHQudGVzdCh3cml0aW5nX3Njb3JlIH4gZ2VuZGVyLCBkYXRhID0gZGYsIGNvbmYubGV2ZWw9IDAuOTkpDQpyZXN1bHRhZG9fdHRlc3QNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ8OpbmVybyoqDQoNCmBgYHtyfQ0KIyBDYWxjdWxhciBwcm9tZWRpb3MgZW4gdW5hIGVzY2FsYSBkZSAwIGEgMTAwDQpkZl9wcm9tZWRpb3MgPC0gZGYgJT4lDQogIGdyb3VwX2J5KHJhY2VfZXRobmljaXR5KSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lYW5fbWF0aF9zY29yZSA9IG1lYW4obWF0aF9zY29yZSkgKiAxMDAgLyBtYXgoZGYkbWF0aF9zY29yZSksDQogICAgbWVhbl9yZWFkaW5nX3Njb3JlID0gbWVhbihyZWFkaW5nX3Njb3JlKSAqIDEwMCAvIG1heChkZiRyZWFkaW5nX3Njb3JlKSwNCiAgICBtZWFuX3dyaXRpbmdfc2NvcmUgPSBtZWFuKHdyaXRpbmdfc2NvcmUpICogMTAwIC8gbWF4KGRmJHdyaXRpbmdfc2NvcmUpDQogICkNCg0KIyBDcmVhciB1biBncsOhZmljbyBkZSBiYXJyYXMgYWdydXBhZGFzIGNvbiBwbG90bHkNCmdyYWZpY29fYmFycmFzX3Bsb3RseSA8LSBwbG90X2x5KGRmX3Byb21lZGlvcywgeCA9IH5yYWNlX2V0aG5pY2l0eSkgJT4lDQogIGFkZF90cmFjZSh5ID0gfm1lYW5fbWF0aF9zY29yZSwgbmFtZSA9ICdNYXRoJywgdHlwZSA9ICdiYXInLCBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ2xpZ2h0Ymx1ZScpKSAlPiUNCiAgYWRkX3RyYWNlKHkgPSB+bWVhbl9yZWFkaW5nX3Njb3JlLCBuYW1lID0gJ1JlYWRpbmcnLCB0eXBlID0gJ2JhcicsIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnbGlnaHRncmVlbicpKSAlPiUNCiAgYWRkX3RyYWNlKHkgPSB+bWVhbl93cml0aW5nX3Njb3JlLCBuYW1lID0gJ1dyaXRpbmcnLCB0eXBlID0gJ2JhcicsIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnbGlnaHRwaW5rJykpICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSAnRGVzZW1wZcOxbyBkZSBFc3R1ZGlhbnRlcyBwb3IgR3J1cG8gw4l0bmljbyAoUHJvbWVkaW9zIGVuIEVzY2FsYSBkZSAwIGEgMTAwKScsDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0dydXBvIMOJdG5pY28nKSwNCiAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnQ2FsaWZpY2FjacOzbiBQcm9tZWRpbycsIHJhbmdlID0gYygwLCAxMDApKSwNCiAgICBiYXJtb2RlID0gJ2dyb3VwJw0KICApDQojIFZpc3VhbGl6YXIgZWwgZ3LDoWZpY28NCmdyYWZpY29fYmFycmFzX3Bsb3RseQ0KYGBgDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIEFOT1ZBIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIG1hdGVtw6F0aWNhcyB5IGVsIGdydXBvIHNvY2lhbCBhbCBxdWUgcGVydGVuZWNlbi4qKioNCg0KKyBIaXDDs3Rlc2lzIG51bGEgKEgwKTogTm8gaGF5IHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3YobWF0aF9zY29yZSB+IHJhY2VfZXRobmljaXR5LCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbWF0ZW3DoXRpY2FzIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLioqDQoNCioqKlBydWViYSBkZSBoaXDDs3Rlc2lzIEFOT1ZBIHBhcmEgZXZhbHVhciBsYSByZWxhY2nDs24gZW50cmUgbGFzIGNhbGlmaWNhY2lvbmVzIGRlIGxlY3R1cmEgeSBlbCBncnVwbyBzb2NpYWwgYWwgcXVlIHBlcnRlbmVjZW4uKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6IE5vIGhheSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBjYWxpZmljYWNpw7NuIGRlIGxlY3R1cmEgeSBlbCBncnVwbyBzb2NpYWwgYWwgcXVlIHBlcnRlbmVjZW4uDQoNCisgSGlww7N0ZXNpcyBudWxhIChIYSk6IEV4aXN0ZSB1bmEgcmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgY2FsaWZpY2FjacOzbiBkZSBsZWN0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3YocmVhZGluZ19zY29yZSB+IHJhY2VfZXRobmljaXR5LCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgbGVjdHVyYSB5IGVsIGdydXBvIHNvY2lhbCBhbCBxdWUgcGVydGVuZWNlbi4qKg0KDQoqKipQcnVlYmEgZGUgaGlww7N0ZXNpcyBBTk9WQSBwYXJhIGV2YWx1YXIgbGEgcmVsYWNpw7NuIGVudHJlIGxhcyBjYWxpZmljYWNpb25lcyBkZSBlc2NyaXR1cmEgeSBlbCBncnVwbyBzb2NpYWwgYWwgcXVlIHBlcnRlbmVjZW4uKioqDQoNCisgSGlww7N0ZXNpcyBudWxhIChIMCk6Tm8gaGF5IHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQorIEhpcMOzdGVzaXMgbnVsYSAoSGEpOiBFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLg0KDQpgYGB7cn0NCnJlc3VsdGFkb19hbm92YSA8LSBhb3Yod3JpdGluZ19zY29yZSB+IHJhY2VfZXRobmljaXR5LCBkYXRhID0gZGYpDQpzdW1tYXJ5KHJlc3VsdGFkb19hbm92YSkNCmBgYA0KKipMYSBoaXDDs3Rlc2lzIG51bGEgc2UgZGVzY2FydGEgeSBzZSBhY2VwdGEgbGEgaGlww7N0ZXNpcyBhbHRlcm5hdGl2YS4qKg0KKipFeGlzdGUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGNhbGlmaWNhY2nDs24gZGUgZXNjcml0dXJhIHkgZWwgZ3J1cG8gc29jaWFsIGFsIHF1ZSBwZXJ0ZW5lY2VuLioqDQoNCg0KIyBDT05DTFVTSU9ORVMNCg0KRGUgYWN1ZXJkbyBjb24gbGFzIGRpc3RpbnRhcyBwcnVlYmFzIHJlYWxpemFkYXMgdGFudG8gbGEgcHJ1ZWJhIHQgeSBsYSBwcnVlYmEgQU5PVkEgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIHNpIGV4aXN0ZSB1bmEgaW5mbHVlbmNpYSBzaWduaWZpY2F0aXZhIGVudHJlIGxvcyBmYWN0b3JlczsgIk5pdmVsIGRlIGVkdWNhY2nDs24gZGUgbG9zIHBhZHJlcyIsICJDdXJzbyBkZSBwcmVwYXJhY2nDs24gcGFyYSBlbCBleGFtZW4iLCAiVGlwbyBkZSBhbG11ZXJ6byIgeSAiUmF6YSIsIGNvbiBsYXMgY2FsaWZpY2FjaW9uZXMgZGUgbG9zIGFsdW1ub3MuDQpBZGVtw6FzIHNpZW5kbyBlbCBnZW5lcm8gZmVtZW5pbm8gcXVpZW4gb2J0dXZvIHVuIHByb21lZGlvIG1hcyBhbHRvIGVuIHN1cyBjYWxpZmljYWNpb25lcy4gDQoNCg0K