Intervalos de Confianza

Introducción:

Un intervalo de confianza (IC) es un rango de valores dentro del cual podemos decir, - con cierto nivel de confianza (e.g., 95%), que se encuentra el valor verdadero - de un parámetro poblacional (como la media). Es importante recordar que un IC - NO mide la variabilidad de los datos, sino la precisión de la estimación de un parametro, por ejemplo de la media.

Ejercicio:

Explicación paso a paso

  1. Creación de datos simulados:

    • Generamos un conjunto de datos ficticio representando los niveles de glucosa en 50 personas.
  2. Cálculo de la media y el error estándar:

    • La media es la estimación puntual de los datos.

    • El error estándar mide la precisión de la media en base al tamaño de la muestra.

  3. Cálculo del intervalo de confianza:

    • Usamos la distribución t de Student debido al tamaño de muestra (n<30).

    • Calculamos el margen de error multiplicando el error estándar por el valor crítico de t.

  4. Resultados:

    • El intervalo de confianza nos da el rango dentro del cual, con un 95% de confianza, creemos que se encuentra la verdadera media poblacional.
  5. Visualización:

    • Un gráfico muestra la distribución de los datos y los límites del IC para interpretar fácilmente los resultados.

Paso 1: Crear un conjunto de datos

Simularemos un conjunto de datos que represente los niveles de glucosa (mg/dL) de 50 personas.

set.seed(123) #Aseguramos reproducibilidad
niveles_glucosa <- rnorm(50, mean = 100, sd = 15) # Media = 100, Desviación estándar = 15

niveles_glucosa
 [1]  91.59287  96.54734 123.38062 101.05763 101.93932 125.72597 106.91374  81.02408  89.69721  93.31507 118.36123 105.39721 106.01157
[14] 101.66024  91.66238 126.80370 107.46776  70.50074 110.52034  92.90813  83.98264  96.73038  84.60993  89.06663  90.62441  74.69960
[27] 112.56681 102.30060  82.92795 118.80722 106.39696  95.57393 113.42688 113.17200 112.32372 110.32960 108.30876  99.07132  95.41056
[40]  94.29293  89.57940  96.88124  81.01905 132.53434 118.11943  83.15337  93.95673  93.00017 111.69948  98.74946
str(niveles_glucosa)
 num [1:50] 91.6 96.5 123.4 101.1 101.9 ...
media <- mean(niveles_glucosa) #Media de los datos
sd <- sd(niveles_glucosa) #Desviación estándar
n <- length(niveles_glucosa) #Tamaño de la muestra
se <- sd / sqrt(n) #Error estándar de la media

media
[1] 100.5161
sd
[1] 13.88805
n
[1] 50
se
[1] 1.964067

Paso 3: Calcular el intervalo de confianza del 95%

Determinamos los límites del intervalo de confianza

El cálculo de un Intervalo de Confianza (IC) del 95% implica varios pasos clave. Vamos a desglosar y entender cada uno de ellos detalladamente.

Para calcular un IC de la media poblacional (𝜇) basado en una muestra, usamos la siguiente formula:

Paso 1: Nivel de significancia (𝛼)

El nivel de confianza (1 −𝛼) indica qué tan seguro estamos de que el intervalo contiene el valor verdadero de la media poblacional:

  • Para un IC del 95%, el nivel de confianza es 0.95 (𝛼= 0.05).

α=1−Nivel de Confianza

Paso 2: Valor crítico (𝑡𝛼/2)

El valor crítico (𝑡𝛼/2) determina cuántos errores estándar necesitamos sumar y restar para abarcar el 95% de los datos. Se calcula utilizando la distribución 𝑡 t de Student y depende de:

Nivel de confianza (1−α): Para un IC del 95%, usamos 𝛼/2= 0.025 para calcular el límite superior e inferior.

df <- n - 1
alpha <- 0.05 #Nivel de significancia (1-95%)
t_critico <- qt(1-alpha / 2, df = n - 1) #Valor crítico t para el 95%
margen_error <- t_critico * se #Margen de error

margen_error
[1] 3.94694

La función qt en R calcula el valor crítico basado en:

  • 1−α/2: Área acumulada de la cola inferior.

  • Grados de libertad (df).

Paso 3: Margen de error

El margen de error define qué tan lejos de la media muestral (x̄) se extiende el intervalo de confianza. Se calcula multiplicando el valor crítico (𝑡𝛼/2) por el error estándar (𝑆𝐸):

  • S=desviación estándar de la muestra).

  • n= tamaño de la muestra.

margen_error
[1] 3.94694

Finalmente, el Intervalo de Confianza se construye sumando y restando el margen de error a la media muestral:

ic_inf <- media - margen_error
ic_inf
[1] 96.56911
ic_sup <- media + margen_error
ic_sup
[1] 104.463
# Resultado
cat("Media:", round(media, 2), "\n")
Media: 100.52 
cat("Intervalo de Confianza del 95%: [", round(ic_inf, 2), ",", round(ic_sup, 2), "]\n")
Intervalo de Confianza del 95%: [ 96.57 , 104.46 ]

Podemos interpretar que con un 95% de confianza, la verdadera media de glucosa en la población se encuentra entre 96.5 mg/dL y 104.53 mg/dL

Este análisis es esencial para reportar resultados en investigaciones científicas, ya que muestra no solo la estimación puntual sino también la precisión de la misma.

Ejemplo práctico

Supongamos:

  • Media muestral (x̄) = 100

  • Desviación estándar (S) = 15

  • Tamaño de muestra (n) = 30

# Establecemos Parámetros
alpha <- 0.05
n <- 15
S <- 30
media <- 100

# Error estándar
se <- S / sqrt(n)

# Valor crítico t
t_critico <- qt(1 - alpha / 2, df = n - 1)

# Margen de error
margen_error <- t_critico * se

# Intervalo de confianza
ic_inf <- media - margen_error
ic_sup <- media + margen_error

cat("Intervalo de Confianza del 95%:", round(ic_inf, 2), "-", round(ic_sup, 2), "\n")
Intervalo de Confianza del 95%: 83.39 - 116.61 

Resumen gráfico

Puedes visualizar el cálculo del IC en un gráfico para mayor claridad:

library(ggplot2)

# Crear un data frame
df <- data.frame(
  media = media,
  ic_inf = ic_inf,
  ic_sup = ic_sup
)

# Graficar el IC
ggplot(df, aes(x = 1, y = media)) +
  geom_point(size = 3, color = "red") + 
  ylim(0,200) +
  geom_errorbar(aes(ymin = ic_inf, ymax = ic_sup), width = 0.2, color = "blue") +
  labs(title = "Intervalo de Confianza del 95% para la Media",
       x = "Muestra",
       y = "Media") +
  theme_minimal()

Fórmulas clave

El intervalo de confianza para la media poblacional u, basado en una muestra, se calcula con la fórmula:

IC= XIta/2• SE

Donde:

  • X: Media muestral.

  • ta/2: Valor crítico de la distribución t de Student, que depende del nivel de confianza y los grados de libertad (n- 1).

  • SE: Error estándar de la media:

  • S: Desviación estándar muestral.

  • n: Tamaño de la muestra.

Cálculo paso a paso

Paso 1: Establecer el nivel de significancia a

El nivel de significancia está relacionado con el nivel de confianza deseado (1 - a). Para un IC del 95%:

a = 1 - 0.95 = 0.05

Esto significa que existe un 5% de probabilidad de que el verdadero valor poblacional u quede fuera del intervalo calculado.

Paso 2: Obtener el valor crítico ta/2

El valor crítico ta/2 se obtiene de la distribución t de Student. Este valor depende de:

  • a/ 2: Mitad del nivel de significancia, ya que el IC tiene dos colas (a/ 2 en cada lado).

  • Grados de libertad (df): Para una muestra, df = n - 1.

En R, calculamos esto usando la función qt :

t_critico <- qt(1-alpha / 2, df = n - 1)

Paso 3: Calcular el error estándar (SE)

El error estándar de la media estima cuánto varía la media muestral con respecto a la media poblacional.

Paso 4: Calcular el margen de error

El margen de error mide cuánto podemos desviar la estimación puntual (media muestral) para construir el intervalo.

Paso 5: Construir el intervalo de confianza

Finalmente, construimos el IC sumando y restando el margen de error de la media muestral ($).

Calculo en R

# datos simulados
set.seed(123)
datos <- rnorm(30, mean = 100, sd = 15)

# calcular estadísticas
media <- mean(datos) 
sd <- sd(datos) # desviación estándar muestral
n <- length(datos) #tamaño de la muestra
se <- sd / sqrt(n) # error estandar

# nivel de significancia 
alpha <- 0.05

# valor crítico t
t_critico <- qt(1 - alpha / 2, df = n - 1)

#margen de eror 
margen_error <- t_critico * se

# intervalo de confianza
ic_inf <- media - margen_error
ic_sup <- media + margen_error

cat("Media:", round(media, 2), "\n")
Media: 99.29 
cat("Intervalo de Confianza del 95%: [", round(ic_inf, 2), ",", round(ic_sup, 2), "]\n")
Intervalo de Confianza del 95%: [ 93.8 , 104.79 ]

Diferencias entre Intervalos de Confianza y el Valor p

  1. Intervalos de Confianza (IC):

    • Los IC nos dan un rango plausible para el valor verdadero de un parámetro (como la media o una diferencia entre medias).

    • Interpretación: Un IC del 95% indica que, si repitiéramos el estudio múltiples veces, el 95% de esos intervalos incluiría el valor verdadero del parámetro.

  2. Valor p:

    • El valor p indica la probabilidad de observar un efecto tan extremo (o más) que el encontrado, bajo la hipótesis nula (H0​).

    • Es una herramienta para tomar decisiones sobre rechazar o no H0.

  3. Diferencia práctica:

    • El IC proporciona información sobre la magnitud y precisión del efecto estimado.

    • El valor p solo indica si un efecto es estadísticamente significativo, sin proporcionar información directa sobre su magnitud.

Uso de R: Comparación entre IC y valor p

Paso 1: Datos del Ejemplo

Simulamos datos de niveles de glucosa:

Paso 2: Cálculo del IC 95%

Paso 3: Cálculo del Valor p

Supongamos que queremos probar si la media poblacional es igual a 95 ( H0​:μ=95):

# prueba t para media poblacional de 95
t_test <- t.test(niveles_glucosa, mu = 95) #hipótesis nula: media = 95

#resultado del valor p
cat("Valor p:", t_test$p.value, "\n")
Valor p: 2.2747e-06 

Resultados:

  1. IC 95%: Muestra el rango en el que creemos que está la verdadera media de los niveles de glucosa.

    • Ejemplo: Si el IC es 

      93.8,103.2

      , sabemos que con un 95% de confianza, la verdadera media de la población está dentro de este rango.

  2. Valor p: Mide si los datos respaldan o rechazan la H0​.

    • Ejemplo: Si el valor p es < 0.05, rechazamos H0​ (es decir, creemos que la media no es 95).

Visualización: IC vs Valor p

Podemos usar un gráfico para explicar cómo el IC y el valor p se relacionan visualmente.

Interpretación del Gráfico

  1. Intervalo de Confianza:

    • La línea punteada muestra el rango plausible para la verdadera media de la población.

    • Si H0=95 cae fuera del intervalo (línea negra discontinua), podemos concluir que es improbable que μ=95

  2. Valor p:

    • Si el valor p es menor que α=0.05, rechazamos H0​, que es consistente con el hecho de que el IC no incluye 95.

Ventaja de combinar IC y valor p

  1. IC: Proporciona una visión más integrativa, mostrando la magnitud del efecto y su precisión.

  2. Valor p: Permite tomar decisiones rápidas sobre la hipótesis nula, pero no indica la magnitud del efecto.

Conclusión

  • En investigaciones epidemiológicas, clínicas o biologicas. Los IC son preferibles porque no solo indican si un efecto es significativo, sino también qué tan grande o preciso es el efecto estimado.

  • El valor p complementa este análisis, ayudándonos a determinar si debemos rechazar una hipótesis nula específica.

Cuando comparamos dos grupos, los Intervalos de Confianza (IC) y el valor p son herramientas complementarias para interpretar las diferencias. A continuación, te presento un ejemplo detallado en R para comparar dos grupos con un enfoque en la estimación de IC y el valor p.

Comparación de Dos Grupos

Supongamos que queremos comparar los niveles de glucosa entre dos grupos: grupo control y grupo experimental.

(Datos Simulados)

Paso 1: Cálculo del Intervalo de Confianza para la Diferencia de Medias

Fórmula:

Código para IC

# Estadísticas descriptivas
media_control <- mean(grupo_control)
media_experimental <- mean(grupo_experimental)
sd_control <- sd(grupo_control)
sd_experimental <- sd(grupo_experimental)
n_control <- length(grupo_control)
n_experimental <- length(grupo_experimental)

# Diferencia de medias
diferencia <- media_experimental - media_control

# Error estándar combinado
se <- sqrt((sd_control^2 / n_control) + (sd_experimental^2 / n_experimental))

# Valor crítico t para IC del 95%
alpha <- 0.05
t_critico <- qt(1 - alpha / 2, df = n_control + n_experimental - 2)

# Margen de error
margen_error <- t_critico * se

# Límites del IC
ic_inf <- diferencia - margen_error
ic_sup <- diferencia + margen_error

cat("Diferencia de medias:", round(diferencia, 2), "\n")
Diferencia de medias: 13.38 
cat("Intervalo de Confianza del 95%: [", round(ic_inf, 2), ",", round(ic_sup, 2), "]\n")
Intervalo de Confianza del 95%: [ 6.32 , 20.44 ]

Paso 2: Prueba de Hipótesis y Valor p

Usamos una prueba t para dos muestras independientes para determinar si la diferencia es estadísticamente significativa.

Código para Prueba t

# Prueba t para dos muestras independientes
t_test <- t.test(grupo_control, grupo_experimental, var.equal = TRUE)

# Resultados
cat("Valor p:", t_test$p.value, "\n")
Valor p: 0.0003576581 
cat("Diferencia estimada (t-test):", t_test$estimate, "\n")
Diferencia estimada (t-test): 99.29344 112.6751 

Paso 3: Visualización de los Resultados

Podemos graficar las distribuciones de ambos grupos y superponer los IC para la diferencia de medias.

Código para Visualización

library(ggplot2)

# Crear un data frame con los datos
df <- data.frame(
  grupo = rep(c("Control", "Experimental"), each = 30),
  niveles_glucosa = c(grupo_control, grupo_experimental)
)

# Graficar los datos
ggplot(df, aes(x = grupo, y = niveles_glucosa, fill = grupo)) +
  geom_boxplot(alpha = 0.7, outlier.colour = "red") +
  geom_point(position = position_jitter(width = 0.1), alpha = 0.5) +
  labs(
    title = "Comparación de Niveles de Glucosa entre Grupos",
    x = "Grupo",
    y = "Niveles de Glucosa (mg/dL)"
  ) +
  theme_minimal() +
  scale_fill_manual(values = c("#00BFC4", "#F8766D"))

AGREGAR SIGNIFICANCIA AL GRÁFICO

# Instalar ggpubr si no lo tienes
# install.packages("ggpubr")

library(ggplot2)
library(ggpubr)

# Crear un data frame con los datos
df <- data.frame(
  grupo = rep(c("Control", "Experimental"), each = 30),
  niveles_glucosa = c(grupo_control, grupo_experimental)
)

# Graficar los datos con significancia
ggplot(df, aes(x = grupo, y = niveles_glucosa, fill = grupo)) +
  geom_boxplot(alpha = 0.7, outlier.colour = "red") +
  geom_point(position = position_jitter(width = 0.1), alpha = 0.5) +
  labs(
    title = "Comparación de Niveles de Glucosa entre Grupos",
    x = "Grupo",
    y = "Niveles de Glucosa (mg/dL)"
  ) +
  theme_minimal() +
  scale_fill_manual(values = c("#00BFC4", "#F8766D")) +
  stat_compare_means(
    method = "t.test", # Realizar prueba t
    label = "p.format", # Mostrar el valor p en formato estándar o lo puedes cambiar por "p.signif" para asteriscos
    label.y = max(df$niveles_glucosa) + 5 # Ajustar la posición de la etiqueta
  ,label.x=1.5)

  1. stat_compare_means():

    • Agrega la significancia estadística al gráfico.

    • El argumento method especifica el tipo de prueba estadística (en este caso, t.test para comparar dos medias).

  2. label = "p.format":

    • Formatea el valor p que se mostrará en el gráfico.
  3. label.y:

    • Ajusta la posición vertical de la etiqueta para que no interfiera con los datos.

Interpretación del Gráfico

  • Ahora, el gráfico incluye un indicador visual del valor p, mostrando si la diferencia entre los grupos es estadísticamente significativa.

  • Si el valor p es menor a 0.05, los resultados son considerados estadísticamente significativos.

    Entonces:

  • Intervalo de Confianza (IC):

    • Proporciona un rango para la diferencia entre medias.

    • Ejemplo: Si el IC es 

      8.5,13.2

      , podemos decir con un 95% de confianza que la verdadera diferencia de medias está en este rango.

  • Valor p:

    • Determina si la diferencia entre las medias es estadísticamente significativa.

    • Ejemplo: Si p<0.05, rechazamos la hipótesis nula de que las medias son iguales.

Interpretación: IC vs Valor p

  1. El IC:

    • Nos dice no solo si la diferencia es significativa, sino también cuán grande es la diferencia y qué tan precisa es la estimación.
  2. El Valor p:

    • Solo nos dice si la diferencia es significativa a un nivel específico (α=0.05).

En este ejemplo:

  • El IC muestra la magnitud y precisión de la diferencia de medias.

  • El valor p complementa este análisis al indicar si la diferencia es estadísticamente significativa.

Este enfoque integrado es esencial para reportar resultados significativos en nuestras investigaciones.

LS0tCnRpdGxlOiAiSW50ZXJ2YWxvcyBkZSBDb25maWFuemEgeSBUZW9yZW1hIGRlbCBsaW1pdGUgY2VudHJhbCIKQXV0aG9yOiAiTENCTS4gSmVzw7pzIEFuZ2VsIEhlcm7DoW5kZXogQ2jDoXZleiIKRGF0ZTogIjI3LzEyLzIwMjUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgKipJbnRlcnZhbG9zIGRlIENvbmZpYW56YSoqCgojIyAqKkludHJvZHVjY2nDs246KioKClVuIGludGVydmFsbyBkZSBjb25maWFuemEgKElDKSBlcyB1biByYW5nbyBkZSB2YWxvcmVzIGRlbnRybyBkZWwgY3VhbCBwb2RlbW9zIGRlY2lyLCAtIGNvbiBjaWVydG8gbml2ZWwgZGUgY29uZmlhbnphIChlLmcuLCA5NSUpLCBxdWUgc2UgZW5jdWVudHJhIGVsIHZhbG9yIHZlcmRhZGVybyAtIGRlIHVuIHBhcsOhbWV0cm8gcG9ibGFjaW9uYWwgKGNvbW8gbGEgbWVkaWEpLiBFcyBpbXBvcnRhbnRlIHJlY29yZGFyIHF1ZSB1biBJQyAtIE5PIG1pZGUgbGEgdmFyaWFiaWxpZGFkIGRlIGxvcyBkYXRvcywgc2lubyBsYSBwcmVjaXNpw7NuIGRlIGxhIGVzdGltYWNpw7NuIGRlIHVuIHBhcmFtZXRybywgcG9yIGVqZW1wbG8gZGUgbGEgbWVkaWEuCgoqKkVqZXJjaWNpbzpcClwKRXhwbGljYWNpw7NuIHBhc28gYSBwYXNvKioKCjEuICAqKkNyZWFjacOzbiBkZSBkYXRvcyBzaW11bGFkb3M6KioKCiAgICAtICAgR2VuZXJhbW9zIHVuIGNvbmp1bnRvIGRlIGRhdG9zIGZpY3RpY2lvIHJlcHJlc2VudGFuZG8gbG9zIG5pdmVsZXMgZGUgZ2x1Y29zYSBlbiA1MCBwZXJzb25hcy4KCjIuICAqKkPDoWxjdWxvIGRlIGxhIG1lZGlhIHkgZWwgZXJyb3IgZXN0w6FuZGFyOioqCgogICAgLSAgIExhwqAqKm1lZGlhKirCoGVzIGxhIGVzdGltYWNpw7NuIHB1bnR1YWwgZGUgbG9zIGRhdG9zLgoKICAgIC0gICBFbMKgKiplcnJvciBlc3TDoW5kYXIqKsKgbWlkZSBsYSBwcmVjaXNpw7NuIGRlIGxhIG1lZGlhIGVuIGJhc2UgYWwgdGFtYcOxbyBkZSBsYSBtdWVzdHJhLgoKMy4gICoqQ8OhbGN1bG8gZGVsIGludGVydmFsbyBkZSBjb25maWFuemE6KioKCiAgICAtICAgVXNhbW9zIGxhIGRpc3RyaWJ1Y2nDs24gdCBkZSBTdHVkZW50IGRlYmlkbyBhbCB0YW1hw7FvIGRlIG11ZXN0cmEgKG5cPDMwKS4KCiAgICAtICAgQ2FsY3VsYW1vcyBlbCBtYXJnZW4gZGUgZXJyb3IgbXVsdGlwbGljYW5kbyBlbCBlcnJvciBlc3TDoW5kYXIgcG9yIGVsIHZhbG9yIGNyw610aWNvIGRlIHQuCgo0LiAgKipSZXN1bHRhZG9zOioqCgogICAgLSAgIEVsIGludGVydmFsbyBkZSBjb25maWFuemEgbm9zIGRhIGVsIHJhbmdvIGRlbnRybyBkZWwgY3VhbCwgY29uIHVuIDk1JSBkZSBjb25maWFuemEsIGNyZWVtb3MgcXVlIHNlIGVuY3VlbnRyYSBsYSB2ZXJkYWRlcmEgbWVkaWEgcG9ibGFjaW9uYWwuCgo1LiAgKipWaXN1YWxpemFjacOzbjoqKgoKICAgIC0gICBVbiBncsOhZmljbyBtdWVzdHJhIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zIHkgbG9zIGzDrW1pdGVzIGRlbCBJQyBwYXJhIGludGVycHJldGFyIGbDoWNpbG1lbnRlIGxvcyByZXN1bHRhZG9zLgoKIyMgKipQYXNvIDE6IENyZWFyIHVuIGNvbmp1bnRvIGRlIGRhdG9zKioKClNpbXVsYXJlbW9zIHVuIGNvbmp1bnRvIGRlIGRhdG9zIHF1ZSByZXByZXNlbnRlIGxvcyBuaXZlbGVzIGRlIGdsdWNvc2EgKG1nL2RMKSBkZSA1MCBwZXJzb25hcy4KCmBgYHtyfQpzZXQuc2VlZCgxMjMpICNBc2VndXJhbW9zIHJlcHJvZHVjaWJpbGlkYWQKbml2ZWxlc19nbHVjb3NhIDwtIHJub3JtKDUwLCBtZWFuID0gMTAwLCBzZCA9IDE1KSAjIE1lZGlhID0gMTAwLCBEZXN2aWFjacOzbiBlc3TDoW5kYXIgPSAxNQoKbml2ZWxlc19nbHVjb3NhCmBgYAoKYGBge3J9CnN0cihuaXZlbGVzX2dsdWNvc2EpCmBgYAoKYGBge3J9Cm1lZGlhIDwtIG1lYW4obml2ZWxlc19nbHVjb3NhKSAjTWVkaWEgZGUgbG9zIGRhdG9zCnNkIDwtIHNkKG5pdmVsZXNfZ2x1Y29zYSkgI0Rlc3ZpYWNpw7NuIGVzdMOhbmRhcgpuIDwtIGxlbmd0aChuaXZlbGVzX2dsdWNvc2EpICNUYW1hw7FvIGRlIGxhIG11ZXN0cmEKc2UgPC0gc2QgLyBzcXJ0KG4pICNFcnJvciBlc3TDoW5kYXIgZGUgbGEgbWVkaWEKCm1lZGlhCmBgYAoKYGBge3J9CnNkCmBgYAoKYGBge3J9Cm4KYGBgCgpgYGB7cn0Kc2UKYGBgCgojIyAqKlBhc28gMzogQ2FsY3VsYXIgZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBkZWwgOTUlKioKCiMjIyAqKkRldGVybWluYW1vcyBsb3MgbMOtbWl0ZXMgZGVsIGludGVydmFsbyBkZSBjb25maWFuemEqKgoKRWwgY8OhbGN1bG8gZGUgdW4gSW50ZXJ2YWxvIGRlIENvbmZpYW56YSAoSUMpIGRlbCA5NSUgaW1wbGljYSB2YXJpb3MgcGFzb3MgY2xhdmUuIFZhbW9zIGEgZGVzZ2xvc2FyIHkgZW50ZW5kZXIgY2FkYSB1bm8gZGUgZWxsb3MgZGV0YWxsYWRhbWVudGUuCgpQYXJhIGNhbGN1bGFyIHVuIElDIGRlIGxhIG1lZGlhIHBvYmxhY2lvbmFsICjwnZyHKSBiYXNhZG8gZW4gdW5hIG11ZXN0cmEsIHVzYW1vcyBsYSBzaWd1aWVudGUgZm9ybXVsYToKCiMjIyAqKlBhc28gMTogTml2ZWwgZGUgc2lnbmlmaWNhbmNpYSAo8J2bvCkqKgoKRWwgbml2ZWwgZGUgY29uZmlhbnphICgxIOKIkvCdm7wpIGluZGljYSBxdcOpIHRhbiBzZWd1cm8gZXN0YW1vcyBkZSBxdWUgZWwgaW50ZXJ2YWxvIGNvbnRpZW5lIGVsIHZhbG9yIHZlcmRhZGVybyBkZSBsYSBtZWRpYSBwb2JsYWNpb25hbDoKCi0gICBQYXJhIHVuIElDIGRlbCA5NSUsIGVsIG5pdmVsIGRlIGNvbmZpYW56YSBlcyAwLjk1ICjwnZu8PSAwLjA1KS4KCs6xPTHiiJJOaXZlbCBkZSBDb25maWFuemEKCiMjIyAqKlBhc28gMjogVmFsb3IgY3LDrXRpY28gKPCdkaHwnZu8LzIpKioKCkVsIHZhbG9yIGNyw610aWNvICjwnZGh8J2bvC8yKSBkZXRlcm1pbmEgY3XDoW50b3MgZXJyb3JlcyBlc3TDoW5kYXIgbmVjZXNpdGFtb3Mgc3VtYXIgeSByZXN0YXIgcGFyYSBhYmFyY2FyIGVsIDk1JSBkZSBsb3MgZGF0b3MuIFNlIGNhbGN1bGEgdXRpbGl6YW5kbyBsYSBkaXN0cmlidWNpw7NuIPCdkaEgdCBkZSBTdHVkZW50IHkgZGVwZW5kZSBkZToKCk5pdmVsIGRlIGNvbmZpYW56YSAoMeKIks6xKTogUGFyYSB1biBJQyBkZWwgOTUlLCB1c2Ftb3Mg8J2bvC8yPSAwLjAyNSBwYXJhIGNhbGN1bGFyIGVsIGzDrW1pdGUgc3VwZXJpb3IgZSBpbmZlcmlvci4KCmBgYHtyfQpkZiA8LSBuIC0gMQphbHBoYSA8LSAwLjA1ICNOaXZlbCBkZSBzaWduaWZpY2FuY2lhICgxLTk1JSkKdF9jcml0aWNvIDwtIHF0KDEtYWxwaGEgLyAyLCBkZiA9IG4gLSAxKSAjVmFsb3IgY3LDrXRpY28gdCBwYXJhIGVsIDk1JQptYXJnZW5fZXJyb3IgPC0gdF9jcml0aWNvICogc2UgI01hcmdlbiBkZSBlcnJvcgoKbWFyZ2VuX2Vycm9yCmBgYAoKTGEgZnVuY2nDs27CoGBxdGDCoGVuIFIgY2FsY3VsYSBlbCB2YWxvciBjcsOtdGljbyBiYXNhZG8gZW46CgotICAgMeKIks6xLzI6IMOBcmVhIGFjdW11bGFkYSBkZSBsYSBjb2xhIGluZmVyaW9yLgoKLSAgIEdyYWRvcyBkZSBsaWJlcnRhZCAoZGYpLgoKIyMjICoqUGFzbyAzOiBNYXJnZW4gZGUgZXJyb3IqKgoKRWwgbWFyZ2VuIGRlIGVycm9yIGRlZmluZSBxdcOpIHRhbiBsZWpvcyBkZSBsYSBtZWRpYSBtdWVzdHJhbCAoeMyEKSBzZSBleHRpZW5kZSBlbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphLiBTZSBjYWxjdWxhIG11bHRpcGxpY2FuZG8gZWwgdmFsb3IgY3LDrXRpY28gKPCdkaHwnZu8LzIpIHBvciBlbCBlcnJvciBlc3TDoW5kYXIgKPCdkYbwnZC4KToKCiFbXShpbWFnZXMvY2xpcGJvYXJkLTg1Mjc4NDAwMC5wbmcpCgotICAgUz1kZXN2aWFjacOzbiBlc3TDoW5kYXIgZGUgbGEgbXVlc3RyYSkuCgotICAgbj0gdGFtYcOxbyBkZSBsYSBtdWVzdHJhLgoKYGBge3J9Cm1hcmdlbl9lcnJvcgpgYGAKCkZpbmFsbWVudGUsIGVsIEludGVydmFsbyBkZSBDb25maWFuemEgc2UgY29uc3RydXllIHN1bWFuZG8geSByZXN0YW5kbyBlbCBtYXJnZW4gZGUgZXJyb3IgYSBsYSBtZWRpYSBtdWVzdHJhbDoKCiFbXShpbWFnZXMvY2xpcGJvYXJkLTEzMjczMjQyMTYucG5nKQoKYGBge3J9CmljX2luZiA8LSBtZWRpYSAtIG1hcmdlbl9lcnJvcgppY19pbmYKYGBgCgpgYGB7cn0KaWNfc3VwIDwtIG1lZGlhICsgbWFyZ2VuX2Vycm9yCmljX3N1cApgYGAKCmBgYHtyfQojIFJlc3VsdGFkbwpjYXQoIk1lZGlhOiIsIHJvdW5kKG1lZGlhLCAyKSwgIlxuIikKYGBgCgpgYGB7cn0KY2F0KCJJbnRlcnZhbG8gZGUgQ29uZmlhbnphIGRlbCA5NSU6IFsiLCByb3VuZChpY19pbmYsIDIpLCAiLCIsIHJvdW5kKGljX3N1cCwgMiksICJdXG4iKQpgYGAKClBvZGVtb3MgaW50ZXJwcmV0YXIgcXVlIGNvbiB1biA5NSUgZGUgY29uZmlhbnphLCBsYSB2ZXJkYWRlcmEgbWVkaWEgZGUgZ2x1Y29zYSBlbiBsYSBwb2JsYWNpw7NuIHNlIGVuY3VlbnRyYSBlbnRyZSA5Ni41IG1nL2RMIHkgMTA0LjUzIG1nL2RMCgpFc3RlIGFuw6FsaXNpcyBlcyBlc2VuY2lhbCBwYXJhIHJlcG9ydGFyIHJlc3VsdGFkb3MgZW4gaW52ZXN0aWdhY2lvbmVzIGNpZW50w61maWNhcywgeWEgcXVlIG11ZXN0cmEgbm8gc29sbyBsYSBlc3RpbWFjacOzbiBwdW50dWFsIHNpbm8gdGFtYmnDqW4gbGEgcHJlY2lzacOzbiBkZSBsYSBtaXNtYS4KCiMjIyAqKkVqZW1wbG8gcHLDoWN0aWNvKioKClN1cG9uZ2Ftb3M6CgotICAgTWVkaWEgbXVlc3RyYWwgKHjMhCkgPSAxMDAKCi0gICBEZXN2aWFjacOzbiBlc3TDoW5kYXIgKFMpID0gMTUKCi0gICBUYW1hw7FvIGRlIG11ZXN0cmEgKG4pID0gMzAKCmBgYHtyfQojIEVzdGFibGVjZW1vcyBQYXLDoW1ldHJvcwphbHBoYSA8LSAwLjA1Cm4gPC0gMTUKUyA8LSAzMAptZWRpYSA8LSAxMDAKCiMgRXJyb3IgZXN0w6FuZGFyCnNlIDwtIFMgLyBzcXJ0KG4pCgojIFZhbG9yIGNyw610aWNvIHQKdF9jcml0aWNvIDwtIHF0KDEgLSBhbHBoYSAvIDIsIGRmID0gbiAtIDEpCgojIE1hcmdlbiBkZSBlcnJvcgptYXJnZW5fZXJyb3IgPC0gdF9jcml0aWNvICogc2UKCiMgSW50ZXJ2YWxvIGRlIGNvbmZpYW56YQppY19pbmYgPC0gbWVkaWEgLSBtYXJnZW5fZXJyb3IKaWNfc3VwIDwtIG1lZGlhICsgbWFyZ2VuX2Vycm9yCgpjYXQoIkludGVydmFsbyBkZSBDb25maWFuemEgZGVsIDk1JToiLCByb3VuZChpY19pbmYsIDIpLCAiLSIsIHJvdW5kKGljX3N1cCwgMiksICJcbiIpCmBgYAoKIyMjICoqUmVzdW1lbiBncsOhZmljbyoqCgpQdWVkZXMgdmlzdWFsaXphciBlbCBjw6FsY3VsbyBkZWwgSUMgZW4gdW4gZ3LDoWZpY28gcGFyYSBtYXlvciBjbGFyaWRhZDoKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIENyZWFyIHVuIGRhdGEgZnJhbWUKZGYgPC0gZGF0YS5mcmFtZSgKICBtZWRpYSA9IG1lZGlhLAogIGljX2luZiA9IGljX2luZiwKICBpY19zdXAgPSBpY19zdXAKKQoKIyBHcmFmaWNhciBlbCBJQwpnZ3Bsb3QoZGYsIGFlcyh4ID0gMSwgeSA9IG1lZGlhKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yID0gInJlZCIpICsgCiAgeWxpbSgwLDIwMCkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBpY19pbmYsIHltYXggPSBpY19zdXApLCB3aWR0aCA9IDAuMiwgY29sb3IgPSAiYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIkludGVydmFsbyBkZSBDb25maWFuemEgZGVsIDk1JSBwYXJhIGxhIE1lZGlhIiwKICAgICAgIHggPSAiTXVlc3RyYSIsCiAgICAgICB5ID0gIk1lZGlhIikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCioqRsOzcm11bGFzIGNsYXZlKioKCkVsIGludGVydmFsbyBkZSBjb25maWFuemEgcGFyYSBsYSBtZWRpYSBwb2JsYWNpb25hbCB1LCBiYXNhZG8gZW4gdW5hIG11ZXN0cmEsIHNlIGNhbGN1bGEgY29uIGxhIGbDs3JtdWxhOgoKKklDPSBYSXRhLzLigKIgU0UqCgpEb25kZToKCi0gICDvu7/vu79YOiBNZWRpYSBtdWVzdHJhbC4KCi0gICDvu790YS8yOiBWYWxvciBjcsOtdGljbyBkZSBsYSBkaXN0cmlidWNpw7NuIHQgZGUgU3R1ZGVudCwgcXVlIGRlcGVuZGUgZGVsIG5pdmVsIGRlIGNvbmZpYW56YSB5IGxvcyBncmFkb3MgZGUgbGliZXJ0YWQgKG4tIDEpLgoKLSAgIO+7v1NFOiBFcnJvciBlc3TDoW5kYXIgZGUgbGEgbWVkaWE6CgogICAgIVtdKGltYWdlcy9jbGlwYm9hcmQtMzg4Mjc5MTcxNy5wbmcpCgotICAgUzogRGVzdmlhY2nDs24gZXN0w6FuZGFyIG11ZXN0cmFsLgoKLSAgIG46IFRhbWHDsW8gZGUgbGEgbXVlc3RyYS4KCioqQ8OhbGN1bG8gcGFzbyBhIHBhc28qKgoKKipQYXNvIDE6IEVzdGFibGVjZXIgZWwgbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSBhKioKCkVsIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEgZXN0w6EgcmVsYWNpb25hZG8gY29uIGVsIG5pdmVsIGRlIGNvbmZpYW56YSBkZXNlYWRvICgxIC0gYSkuIFBhcmEgdW4gSUMgZGVsIDk1JToKCmEgPSAxIC0gMC45NSA9IDAuMDUKCkVzdG8gc2lnbmlmaWNhIHF1ZSBleGlzdGUgdW4gNSUgZGUgcHJvYmFiaWxpZGFkIGRlIHF1ZSBlbCB2ZXJkYWRlcm8gdmFsb3IgcG9ibGFjaW9uYWwgdSBxdWVkZSBmdWVyYSBkZWwgaW50ZXJ2YWxvIGNhbGN1bGFkby4KCioqUGFzbyAyOiBPYnRlbmVyIGVsIHZhbG9yIGNyw610aWNvIHRhLzIqKgoKRWwgdmFsb3IgY3LDrXRpY28gdGEvMiBzZSBvYnRpZW5lIGRlIGxhIGRpc3RyaWJ1Y2nDs24gdCBkZSBTdHVkZW50LiBFc3RlIHZhbG9yIGRlcGVuZGUgZGU6CgotICAg77u/77u/YS8gMjogTWl0YWQgZGVsIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEsIHlhIHF1ZSBlbCBJQyB0aWVuZSBkb3MgY29sYXMgKGEvIDIgZW4gY2FkYSBsYWRvKS4KCi0gICDvu7/vu79HcmFkb3MgZGUgbGliZXJ0YWQgKGRmKTogUGFyYSB1bmEgbXVlc3RyYSwgZGYgPSBuIC0gMS4KCkVuIFIsIGNhbGN1bGFtb3MgZXN0byB1c2FuZG8gbGEgZnVuY2nDs24gcXQgOgoKYGBge3J9CnRfY3JpdGljbyA8LSBxdCgxLWFscGhhIC8gMiwgZGYgPSBuIC0gMSkKYGBgCgoqKiFbXShpbWFnZXMvY2xpcGJvYXJkLTk0MDQ3NzA3Ny5wbmcpIFBhc28gMzogQ2FsY3VsYXIgZWwgZXJyb3IgZXN0w6FuZGFyIChTRSkqKgoKRWwgZXJyb3IgZXN0w6FuZGFyIGRlIGxhIG1lZGlhIGVzdGltYSBjdcOhbnRvIHZhcsOtYSBsYSBtZWRpYSBtdWVzdHJhbCBjb24gcmVzcGVjdG8gYSBsYSBtZWRpYSBwb2JsYWNpb25hbC4KCioqUGFzbyA0OiBDYWxjdWxhciBlbCBtYXJnZW4gZGUgZXJyb3IqKgoKRWwgbWFyZ2VuIGRlIGVycm9yIG1pZGUgY3XDoW50byBwb2RlbW9zIGRlc3ZpYXIgbGEgZXN0aW1hY2nDs24gcHVudHVhbCAobWVkaWEgbXVlc3RyYWwpIHBhcmEgY29uc3RydWlyIGVsIGludGVydmFsby4KCioqUGFzbyA1OiBDb25zdHJ1aXIgZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSoqCgpGaW5hbG1lbnRlLCBjb25zdHJ1aW1vcyBlbCBJQyBzdW1hbmRvIHkgcmVzdGFuZG8gZWwgbWFyZ2VuIGRlIGVycm9yIGRlIGxhIG1lZGlhIG11ZXN0cmFsIChcJCkuCgoqKkNhbGN1bG8gZW4gUioqCgpgYGB7cn0KIyBkYXRvcyBzaW11bGFkb3MKc2V0LnNlZWQoMTIzKQpkYXRvcyA8LSBybm9ybSgzMCwgbWVhbiA9IDEwMCwgc2QgPSAxNSkKCiMgY2FsY3VsYXIgZXN0YWTDrXN0aWNhcwptZWRpYSA8LSBtZWFuKGRhdG9zKSAKc2QgPC0gc2QoZGF0b3MpICMgZGVzdmlhY2nDs24gZXN0w6FuZGFyIG11ZXN0cmFsCm4gPC0gbGVuZ3RoKGRhdG9zKSAjdGFtYcOxbyBkZSBsYSBtdWVzdHJhCnNlIDwtIHNkIC8gc3FydChuKSAjIGVycm9yIGVzdGFuZGFyCgojIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEgCmFscGhhIDwtIDAuMDUKCiMgdmFsb3IgY3LDrXRpY28gdAp0X2NyaXRpY28gPC0gcXQoMSAtIGFscGhhIC8gMiwgZGYgPSBuIC0gMSkKCiNtYXJnZW4gZGUgZXJvciAKbWFyZ2VuX2Vycm9yIDwtIHRfY3JpdGljbyAqIHNlCgojIGludGVydmFsbyBkZSBjb25maWFuemEKaWNfaW5mIDwtIG1lZGlhIC0gbWFyZ2VuX2Vycm9yCmljX3N1cCA8LSBtZWRpYSArIG1hcmdlbl9lcnJvcgoKY2F0KCJNZWRpYToiLCByb3VuZChtZWRpYSwgMiksICJcbiIpCmBgYAoKYGBge3J9CmNhdCgiSW50ZXJ2YWxvIGRlIENvbmZpYW56YSBkZWwgOTUlOiBbIiwgcm91bmQoaWNfaW5mLCAyKSwgIiwiLCByb3VuZChpY19zdXAsIDIpLCAiXVxuIikKYGBgCgojIyMgKipEaWZlcmVuY2lhcyBlbnRyZSBJbnRlcnZhbG9zIGRlIENvbmZpYW56YSB5IGVsIFZhbG9yIHAqKgoKMS4gICoqSW50ZXJ2YWxvcyBkZSBDb25maWFuemEgKElDKToqKgoKICAgIC0gICBMb3MgSUMgbm9zIGRhbiB1biByYW5nbyBwbGF1c2libGUgcGFyYSBlbCB2YWxvciB2ZXJkYWRlcm8gZGUgdW4gcGFyw6FtZXRybyAoY29tbyBsYSBtZWRpYSBvIHVuYSBkaWZlcmVuY2lhIGVudHJlIG1lZGlhcykuCgogICAgLSAgIEludGVycHJldGFjacOzbjogVW4gSUMgZGVsIDk1JSBpbmRpY2EgcXVlLCBzaSByZXBpdGnDqXJhbW9zIGVsIGVzdHVkaW8gbcO6bHRpcGxlcyB2ZWNlcywgZWwgOTUlIGRlIGVzb3MgaW50ZXJ2YWxvcyBpbmNsdWlyw61hIGVsIHZhbG9yIHZlcmRhZGVybyBkZWwgcGFyw6FtZXRyby4KCjIuICAqKlZhbG9yIHA6KioKCiAgICAtICAgRWwgdmFsb3IgcCBpbmRpY2EgbGEgcHJvYmFiaWxpZGFkIGRlIG9ic2VydmFyIHVuIGVmZWN0byB0YW4gZXh0cmVtbyAobyBtw6FzKSBxdWUgZWwgZW5jb250cmFkbywgYmFqbyBsYSBoaXDDs3Rlc2lzIG51bGEgKEgw4oCLKS4KCiAgICAtICAgRXMgdW5hIGhlcnJhbWllbnRhIHBhcmEgdG9tYXIgZGVjaXNpb25lcyBzb2JyZSByZWNoYXphciBvIG5vIEgwLgoKMy4gICoqRGlmZXJlbmNpYSBwcsOhY3RpY2E6KioKCiAgICAtICAgRWwgSUMgcHJvcG9yY2lvbmEgaW5mb3JtYWNpw7NuIHNvYnJlIGxhIG1hZ25pdHVkIHkgcHJlY2lzacOzbiBkZWwgZWZlY3RvIGVzdGltYWRvLgoKICAgIC0gICBFbCB2YWxvciBwIHNvbG8gaW5kaWNhIHNpIHVuIGVmZWN0byBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZvLCBzaW4gcHJvcG9yY2lvbmFyIGluZm9ybWFjacOzbiBkaXJlY3RhIHNvYnJlIHN1IG1hZ25pdHVkLgoKIyMjICoqVXNvIGRlIFI6IENvbXBhcmFjacOzbiBlbnRyZSBJQyB5IHZhbG9yIHAqKgoKIyMjIyAqKlBhc28gMTogRGF0b3MgZGVsIEVqZW1wbG8qKgoKU2ltdWxhbW9zIGRhdG9zIGRlIG5pdmVsZXMgZGUgZ2x1Y29zYToKCmBgYHtyfQpzZXQuc2VlZCgxMjMpCm5pdmVsZXNfZ2x1Y29zYSA8LSBybm9ybSgyMDAsIG1lYW4gPSAxMDAsIHNkID0gMTUpICAjIE1lZGlhID0gMTAwLCBTRCA9IDE1CmBgYAoKKipQYXNvIDI6IEPDoWxjdWxvIGRlbCBJQyA5NSUqKgoKYGBge3J9CiMgQ2FsY3VsYXIgZXN0YWTDrXN0aWNvcwptZWRpYSA8LSBtZWFuKG5pdmVsZXNfZ2x1Y29zYSkgICMgTWVkaWEgbXVlc3RyYWwKc2QgPC0gc2Qobml2ZWxlc19nbHVjb3NhKSAgICAgICAjIERlc3ZpYWNpw7NuIGVzdMOhbmRhciBtdWVzdHJhbApuIDwtIGxlbmd0aChuaXZlbGVzX2dsdWNvc2EpICAgICMgVGFtYcOxbyBkZSBsYSBtdWVzdHJhCnNlIDwtIHNkIC8gc3FydChuKSAgICAgICAgICAgICAgIyBFcnJvciBlc3TDoW5kYXIKCiMgSUMgOTUlCmFscGhhIDwtIDAuMDUKdF9jcml0aWNvIDwtIHF0KDEgLSBhbHBoYSAvIDIsIGRmID0gbiAtIDEpICAjIFZhbG9yIGNyw610aWNvIGRlIHQKbWFyZ2VuX2Vycm9yIDwtIHRfY3JpdGljbyAqIHNlICAgICAgICAgICAgICAjIE1hcmdlbiBkZSBlcnJvcgppY19pbmYgPC0gbWVkaWEgLSBtYXJnZW5fZXJyb3IKaWNfc3VwIDwtIG1lZGlhICsgbWFyZ2VuX2Vycm9yCgpjYXQoIkludGVydmFsbyBkZSBDb25maWFuemEgZGVsIDk1JTogWyIsIHJvdW5kKGljX2luZiwgMiksICIsIiwgcm91bmQoaWNfc3VwLCAyKSwgIl1cbiIpCmBgYAoKIyMjIyAqKlBhc28gMzogQ8OhbGN1bG8gZGVsIFZhbG9yIHAqKgoKU3Vwb25nYW1vcyBxdWUgcXVlcmVtb3MgcHJvYmFyIHNpIGxhIG1lZGlhIHBvYmxhY2lvbmFsIGVzIGlndWFsIGEgOTUgKCBIMOKAizrOvD05NSk6CgpgYGB7cn0KIyBwcnVlYmEgdCBwYXJhIG1lZGlhIHBvYmxhY2lvbmFsIGRlIDk1CnRfdGVzdCA8LSB0LnRlc3Qobml2ZWxlc19nbHVjb3NhLCBtdSA9IDk1KSAjaGlww7N0ZXNpcyBudWxhOiBtZWRpYSA9IDk1CgojcmVzdWx0YWRvIGRlbCB2YWxvciBwCmNhdCgiVmFsb3IgcDoiLCB0X3Rlc3QkcC52YWx1ZSwgIlxuIikKYGBgCgojIyMgKipSZXN1bHRhZG9zOioqCgoxLiAgKipJQyA5NSU6KirCoE11ZXN0cmEgZWwgcmFuZ28gZW4gZWwgcXVlIGNyZWVtb3MgcXVlIGVzdMOhIGxhIHZlcmRhZGVyYSBtZWRpYSBkZSBsb3Mgbml2ZWxlcyBkZSBnbHVjb3NhLgoKICAgIC0gICBFamVtcGxvOiBTaSBlbCBJQyBlc8KgCgogICAgICAgIDkzLjgsMTAzLjIKCiAgICAgICAgLCBzYWJlbW9zIHF1ZSBjb24gdW4gOTUlIGRlIGNvbmZpYW56YSwgbGEgdmVyZGFkZXJhIG1lZGlhIGRlIGxhIHBvYmxhY2nDs24gZXN0w6EgZGVudHJvIGRlIGVzdGUgcmFuZ28uCgoyLiAgKipWYWxvciBwOioqwqBNaWRlIHNpIGxvcyBkYXRvcyByZXNwYWxkYW4gbyByZWNoYXphbiBsYSBIMOKAiy4KCiAgICAtICAgRWplbXBsbzogU2kgZWwgdmFsb3IgcCBlcyBcPCAwLjA1LCByZWNoYXphbW9zIEgw4oCLIChlcyBkZWNpciwgY3JlZW1vcyBxdWUgbGEgbWVkaWEgbm8gZXMgOTUpLgoKIyMjICoqVmlzdWFsaXphY2nDs246IElDIHZzIFZhbG9yIHAqKgoKUG9kZW1vcyB1c2FyIHVuIGdyw6FmaWNvIHBhcmEgZXhwbGljYXIgY8OzbW8gZWwgSUMgeSBlbCB2YWxvciBwIHNlIHJlbGFjaW9uYW4gdmlzdWFsbWVudGUuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKIyBDcmVhciB1biBkYXRhIGZyYW1lIHBhcmEgZWwgZ3LDoWZpY28KZGYgPC0gZGF0YS5mcmFtZSgKICBtZWRpYSA9IG1lZGlhLAogIGljX2luZiA9IGljX2luZiwKICBpY19zdXAgPSBpY19zdXAKKQoKIyBHcmFmaWNhcgpnZ3Bsb3QoZGYsIGFlcyh4ID0gMSkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gaWNfaW5mLCB5bWF4ID0gaWNfc3VwKSwgd2lkdGggPSAwLjIsIGNvbG9yID0gImJsdWUiKSArIHlsaW0oMCwyMDApKwogIGdlb21fcG9pbnQoYWVzKHkgPSBtZWRpYSksIHNpemUgPSA0LCBjb2xvciA9ICJyZWQiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gOTUsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb21wYXJhY2nDs24gZW50cmUgSW50ZXJ2YWxvcyBkZSBDb25maWFuemEgZSBIaXDDs3Rlc2lzIE51bGEiLAogICAgeCA9ICJNdWVzdHJhIChuaXZlbGVzIGRlIGdsdWNvc2EpIiwKICAgIHkgPSAiTml2ZWxlcyBkZSBHbHVjb3NhIChtZy9kTCkiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMjICoqSW50ZXJwcmV0YWNpw7NuIGRlbCBHcsOhZmljbyoqCgoxLiAgKipJbnRlcnZhbG8gZGUgQ29uZmlhbnphOioqCgogICAgLSAgIExhIGzDrW5lYSBwdW50ZWFkYSBtdWVzdHJhIGVsIHJhbmdvIHBsYXVzaWJsZSBwYXJhIGxhIHZlcmRhZGVyYSBtZWRpYSBkZSBsYSBwb2JsYWNpw7NuLgoKICAgIC0gICBTaSBIMD05NSBjYWUgZnVlcmEgZGVsIGludGVydmFsbyAobMOtbmVhIG5lZ3JhIGRpc2NvbnRpbnVhKSwgcG9kZW1vcyBjb25jbHVpciBxdWUgZXMgaW1wcm9iYWJsZSBxdWUgzrw9OTUKCjIuICAqKlZhbG9yIHA6KioKCiAgICAtICAgU2kgZWwgdmFsb3IgcCBlcyBtZW5vciBxdWUgzrE9MC4wNSwgcmVjaGF6YW1vcyBIMOKAiywgcXVlIGVzIGNvbnNpc3RlbnRlIGNvbiBlbCBoZWNobyBkZSBxdWUgZWwgSUMgbm8gaW5jbHV5ZSA5NS4KCiMjIyAqKlZlbnRhamEgZGUgY29tYmluYXIgSUMgeSB2YWxvciBwKioKCjEuICAqKklDOioqwqBQcm9wb3JjaW9uYSB1bmEgdmlzacOzbiBtw6FzIGludGVncmF0aXZhLCBtb3N0cmFuZG8gbGEgbWFnbml0dWQgZGVsIGVmZWN0byB5IHN1IHByZWNpc2nDs24uCgoyLiAgKipWYWxvciBwOioqwqBQZXJtaXRlIHRvbWFyIGRlY2lzaW9uZXMgcsOhcGlkYXMgc29icmUgbGEgaGlww7N0ZXNpcyBudWxhLCBwZXJvIG5vIGluZGljYSBsYSBtYWduaXR1ZCBkZWwgZWZlY3RvLgoKIyMjICoqQ29uY2x1c2nDs24qKgoKLSAgIEVuIGludmVzdGlnYWNpb25lcyBlcGlkZW1pb2zDs2dpY2FzLCBjbMOtbmljYXMgbyBiaW9sb2dpY2FzLiBMb3MgSUMgc29uIHByZWZlcmlibGVzIHBvcnF1ZSBubyBzb2xvIGluZGljYW4gc2kgdW4gZWZlY3RvIGVzIHNpZ25pZmljYXRpdm8sIHNpbm8gdGFtYmnDqW7CoCoqcXXDqSB0YW4gZ3JhbmRlIG8gcHJlY2lzbyBlcyBlbCBlZmVjdG8gZXN0aW1hZG8qKi4KCi0gICBFbMKgKip2YWxvciBwKirCoGNvbXBsZW1lbnRhIGVzdGUgYW7DoWxpc2lzLCBheXVkw6FuZG9ub3MgYSBkZXRlcm1pbmFyIHNpIGRlYmVtb3MgcmVjaGF6YXIgdW5hIGhpcMOzdGVzaXMgbnVsYSBlc3BlY8OtZmljYS4KCkN1YW5kbyBjb21wYXJhbW9zIGRvcyBncnVwb3MsIGxvc8KgKipJbnRlcnZhbG9zIGRlIENvbmZpYW56YSAoSUMpKirCoHkgZWzCoCoqdmFsb3IgcCoqwqBzb24gaGVycmFtaWVudGFzIGNvbXBsZW1lbnRhcmlhcyBwYXJhIGludGVycHJldGFyIGxhcyBkaWZlcmVuY2lhcy4gQSBjb250aW51YWNpw7NuLCB0ZSBwcmVzZW50byB1biBlamVtcGxvIGRldGFsbGFkbyBlbsKgKipSKirCoHBhcmEgY29tcGFyYXIgZG9zIGdydXBvcyBjb24gdW4gZW5mb3F1ZSBlbiBsYSBlc3RpbWFjacOzbiBkZSBJQyB5IGVsIHZhbG9yIHAuCgojIyMgKipDb21wYXJhY2nDs24gZGUgRG9zIEdydXBvcyoqCgpTdXBvbmdhbW9zIHF1ZSBxdWVyZW1vcyBjb21wYXJhciBsb3Mgbml2ZWxlcyBkZSBnbHVjb3NhIGVudHJlIGRvcyBncnVwb3M6wqAqKmdydXBvIGNvbnRyb2wqKsKgecKgKipncnVwbyBleHBlcmltZW50YWwqKi4KCiMjIyMgKiooRGF0b3MgU2ltdWxhZG9zKSoqCgpgYGB7cn0Kc2V0LnNlZWQoMTIzKSAgIyBSZXByb2R1Y2liaWxpZGFkCgojIFNpbXVsYXIgZGF0b3MKZ3J1cG9fY29udHJvbCA8LSBybm9ybSgzMCwgbWVhbiA9IDEwMCwgc2QgPSAxNSkgICMgTWVkaWEgPSAxMDAsIFNEID0gMTUKZ3J1cG9fZXhwZXJpbWVudGFsIDwtIHJub3JtKDMwLCBtZWFuID0gMTEwLCBzZCA9IDE1KSAgIyBNZWRpYSA9IDExMCwgU0QgPSAxNQpgYGAKCiMjIyAqKlBhc28gMTogQ8OhbGN1bG8gZGVsIEludGVydmFsbyBkZSBDb25maWFuemEgcGFyYSBsYSBEaWZlcmVuY2lhIGRlIE1lZGlhcyoqCgojIyMjICoqRsOzcm11bGE6KioKCiFbXShpbWFnZXMvY2xpcGJvYXJkLTc1OTM3MjYxNS5wbmcpCgoqKkPDs2RpZ28gcGFyYSBJQyoqCgpgYGB7cn0KIyBFc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcwptZWRpYV9jb250cm9sIDwtIG1lYW4oZ3J1cG9fY29udHJvbCkKbWVkaWFfZXhwZXJpbWVudGFsIDwtIG1lYW4oZ3J1cG9fZXhwZXJpbWVudGFsKQpzZF9jb250cm9sIDwtIHNkKGdydXBvX2NvbnRyb2wpCnNkX2V4cGVyaW1lbnRhbCA8LSBzZChncnVwb19leHBlcmltZW50YWwpCm5fY29udHJvbCA8LSBsZW5ndGgoZ3J1cG9fY29udHJvbCkKbl9leHBlcmltZW50YWwgPC0gbGVuZ3RoKGdydXBvX2V4cGVyaW1lbnRhbCkKCiMgRGlmZXJlbmNpYSBkZSBtZWRpYXMKZGlmZXJlbmNpYSA8LSBtZWRpYV9leHBlcmltZW50YWwgLSBtZWRpYV9jb250cm9sCgojIEVycm9yIGVzdMOhbmRhciBjb21iaW5hZG8Kc2UgPC0gc3FydCgoc2RfY29udHJvbF4yIC8gbl9jb250cm9sKSArIChzZF9leHBlcmltZW50YWxeMiAvIG5fZXhwZXJpbWVudGFsKSkKCiMgVmFsb3IgY3LDrXRpY28gdCBwYXJhIElDIGRlbCA5NSUKYWxwaGEgPC0gMC4wNQp0X2NyaXRpY28gPC0gcXQoMSAtIGFscGhhIC8gMiwgZGYgPSBuX2NvbnRyb2wgKyBuX2V4cGVyaW1lbnRhbCAtIDIpCgojIE1hcmdlbiBkZSBlcnJvcgptYXJnZW5fZXJyb3IgPC0gdF9jcml0aWNvICogc2UKCiMgTMOtbWl0ZXMgZGVsIElDCmljX2luZiA8LSBkaWZlcmVuY2lhIC0gbWFyZ2VuX2Vycm9yCmljX3N1cCA8LSBkaWZlcmVuY2lhICsgbWFyZ2VuX2Vycm9yCgpjYXQoIkRpZmVyZW5jaWEgZGUgbWVkaWFzOiIsIHJvdW5kKGRpZmVyZW5jaWEsIDIpLCAiXG4iKQpgYGAKCmBgYHtyfQpjYXQoIkludGVydmFsbyBkZSBDb25maWFuemEgZGVsIDk1JTogWyIsIHJvdW5kKGljX2luZiwgMiksICIsIiwgcm91bmQoaWNfc3VwLCAyKSwgIl1cbiIpCmBgYAoKIyMjICoqUGFzbyAyOiBQcnVlYmEgZGUgSGlww7N0ZXNpcyB5IFZhbG9yIHAqKgoKVXNhbW9zIHVuYSBwcnVlYmEgdCBwYXJhIGRvcyBtdWVzdHJhcyBpbmRlcGVuZGllbnRlcyBwYXJhIGRldGVybWluYXIgc2kgbGEgZGlmZXJlbmNpYSBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhLgoKIyMjIyAqKkPDs2RpZ28gcGFyYSBQcnVlYmEgdCoqCgpgYGB7cn0KIyBQcnVlYmEgdCBwYXJhIGRvcyBtdWVzdHJhcyBpbmRlcGVuZGllbnRlcwp0X3Rlc3QgPC0gdC50ZXN0KGdydXBvX2NvbnRyb2wsIGdydXBvX2V4cGVyaW1lbnRhbCwgdmFyLmVxdWFsID0gVFJVRSkKCiMgUmVzdWx0YWRvcwpjYXQoIlZhbG9yIHA6IiwgdF90ZXN0JHAudmFsdWUsICJcbiIpCmBgYAoKYGBge3J9CmNhdCgiRGlmZXJlbmNpYSBlc3RpbWFkYSAodC10ZXN0KToiLCB0X3Rlc3QkZXN0aW1hdGUsICJcbiIpCmBgYAoKIyMjICoqUGFzbyAzOiBWaXN1YWxpemFjacOzbiBkZSBsb3MgUmVzdWx0YWRvcyoqCgpQb2RlbW9zIGdyYWZpY2FyIGxhcyBkaXN0cmlidWNpb25lcyBkZSBhbWJvcyBncnVwb3MgeSBzdXBlcnBvbmVyIGxvcyBJQyBwYXJhIGxhIGRpZmVyZW5jaWEgZGUgbWVkaWFzLgoKIyMjIyAqKkPDs2RpZ28gcGFyYSBWaXN1YWxpemFjacOzbioqCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKIyBDcmVhciB1biBkYXRhIGZyYW1lIGNvbiBsb3MgZGF0b3MKZGYgPC0gZGF0YS5mcmFtZSgKICBncnVwbyA9IHJlcChjKCJDb250cm9sIiwgIkV4cGVyaW1lbnRhbCIpLCBlYWNoID0gMzApLAogIG5pdmVsZXNfZ2x1Y29zYSA9IGMoZ3J1cG9fY29udHJvbCwgZ3J1cG9fZXhwZXJpbWVudGFsKQopCgojIEdyYWZpY2FyIGxvcyBkYXRvcwpnZ3Bsb3QoZGYsIGFlcyh4ID0gZ3J1cG8sIHkgPSBuaXZlbGVzX2dsdWNvc2EsIGZpbGwgPSBncnVwbykpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIG91dGxpZXIuY29sb3VyID0gInJlZCIpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4xKSwgYWxwaGEgPSAwLjUpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQ29tcGFyYWNpw7NuIGRlIE5pdmVsZXMgZGUgR2x1Y29zYSBlbnRyZSBHcnVwb3MiLAogICAgeCA9ICJHcnVwbyIsCiAgICB5ID0gIk5pdmVsZXMgZGUgR2x1Y29zYSAobWcvZEwpIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzAwQkZDNCIsICIjRjg3NjZEIikpCmBgYAoKQUdSRUdBUiBTSUdOSUZJQ0FOQ0lBIEFMIEdSw4FGSUNPCgpgYGB7cn0KIyBJbnN0YWxhciBnZ3B1YnIgc2kgbm8gbG8gdGllbmVzCiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dwdWJyIikKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3B1YnIpCgojIENyZWFyIHVuIGRhdGEgZnJhbWUgY29uIGxvcyBkYXRvcwpkZiA8LSBkYXRhLmZyYW1lKAogIGdydXBvID0gcmVwKGMoIkNvbnRyb2wiLCAiRXhwZXJpbWVudGFsIiksIGVhY2ggPSAzMCksCiAgbml2ZWxlc19nbHVjb3NhID0gYyhncnVwb19jb250cm9sLCBncnVwb19leHBlcmltZW50YWwpCikKCiMgR3JhZmljYXIgbG9zIGRhdG9zIGNvbiBzaWduaWZpY2FuY2lhCmdncGxvdChkZiwgYWVzKHggPSBncnVwbywgeSA9IG5pdmVsZXNfZ2x1Y29zYSwgZmlsbCA9IGdydXBvKSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNywgb3V0bGllci5jb2xvdXIgPSAicmVkIikgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjEpLCBhbHBoYSA9IDAuNSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb21wYXJhY2nDs24gZGUgTml2ZWxlcyBkZSBHbHVjb3NhIGVudHJlIEdydXBvcyIsCiAgICB4ID0gIkdydXBvIiwKICAgIHkgPSAiTml2ZWxlcyBkZSBHbHVjb3NhIChtZy9kTCkiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDBCRkM0IiwgIiNGODc2NkQiKSkgKwogIHN0YXRfY29tcGFyZV9tZWFucygKICAgIG1ldGhvZCA9ICJ0LnRlc3QiLCAjIFJlYWxpemFyIHBydWViYSB0CiAgICBsYWJlbCA9ICJwLmZvcm1hdCIsICMgTW9zdHJhciBlbCB2YWxvciBwIGVuIGZvcm1hdG8gZXN0w6FuZGFyIG8gbG8gcHVlZGVzIGNhbWJpYXIgcG9yICJwLnNpZ25pZiIgcGFyYSBhc3RlcmlzY29zCiAgICBsYWJlbC55ID0gbWF4KGRmJG5pdmVsZXNfZ2x1Y29zYSkgKyA1ICMgQWp1c3RhciBsYSBwb3NpY2nDs24gZGUgbGEgZXRpcXVldGEKICAsbGFiZWwueD0xLjUpCmBgYAoKMS4gICoqYHN0YXRfY29tcGFyZV9tZWFucygpYCoqOgoKICAgIC0gICBBZ3JlZ2EgbGEgc2lnbmlmaWNhbmNpYSBlc3RhZMOtc3RpY2EgYWwgZ3LDoWZpY28uCgogICAgLSAgIEVsIGFyZ3VtZW50b8KgYG1ldGhvZGDCoGVzcGVjaWZpY2EgZWwgdGlwbyBkZSBwcnVlYmEgZXN0YWTDrXN0aWNhIChlbiBlc3RlIGNhc28swqBgdC50ZXN0YMKgcGFyYSBjb21wYXJhciBkb3MgbWVkaWFzKS4KCjIuICAqKmBsYWJlbCA9ICJwLmZvcm1hdCJgKio6CgogICAgLSAgIEZvcm1hdGVhIGVsIHZhbG9yIHAgcXVlIHNlIG1vc3RyYXLDoSBlbiBlbCBncsOhZmljby4KCjMuICAqKmBsYWJlbC55YCoqOgoKICAgIC0gICBBanVzdGEgbGEgcG9zaWNpw7NuIHZlcnRpY2FsIGRlIGxhIGV0aXF1ZXRhIHBhcmEgcXVlIG5vIGludGVyZmllcmEgY29uIGxvcyBkYXRvcy4KCiMjIyAqKkludGVycHJldGFjacOzbiBkZWwgR3LDoWZpY28qKgoKLSAgIEFob3JhLCBlbCBncsOhZmljbyBpbmNsdXllIHVuIGluZGljYWRvciB2aXN1YWwgZGVsIHZhbG9yIHAsIG1vc3RyYW5kbyBzaSBsYSBkaWZlcmVuY2lhIGVudHJlIGxvcyBncnVwb3MgZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YS4KCi0gICBTaSBlbCB2YWxvciBwIGVzIG1lbm9yIGEgMC4wNSwgbG9zIHJlc3VsdGFkb3Mgc29uIGNvbnNpZGVyYWRvcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZvcy4KCiAgICBFbnRvbmNlczoKCi0gICAqKkludGVydmFsbyBkZSBDb25maWFuemEgKElDKToqKgoKICAgIC0gICBQcm9wb3JjaW9uYSB1biByYW5nbyBwYXJhIGxhIGRpZmVyZW5jaWEgZW50cmUgbWVkaWFzLgoKICAgIC0gICBFamVtcGxvOiBTaSBlbCBJQyBlc8KgCgogICAgICAgIDguNSwxMy4yCgogICAgICAgICwgcG9kZW1vcyBkZWNpciBjb24gdW4gOTUlIGRlIGNvbmZpYW56YSBxdWUgbGEgdmVyZGFkZXJhIGRpZmVyZW5jaWEgZGUgbWVkaWFzIGVzdMOhIGVuIGVzdGUgcmFuZ28uCgotICAgKipWYWxvciBwOioqCgogICAgLSAgIERldGVybWluYSBzaSBsYSBkaWZlcmVuY2lhIGVudHJlIGxhcyBtZWRpYXMgZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YS4KCiAgICAtICAgRWplbXBsbzogU2kgcFw8MC4wNSwgcmVjaGF6YW1vcyBsYSBoaXDDs3Rlc2lzIG51bGEgZGUgcXVlIGxhcyBtZWRpYXMgc29uIGlndWFsZXMuCgojIyMgKipJbnRlcnByZXRhY2nDs246IElDIHZzIFZhbG9yIHAqKgoKMS4gICoqRWwgSUM6KioKCiAgICAtICAgTm9zIGRpY2Ugbm8gc29sbyBzaSBsYSBkaWZlcmVuY2lhIGVzIHNpZ25pZmljYXRpdmEsIHNpbm8gdGFtYmnDqW4gY3XDoW4gZ3JhbmRlIGVzIGxhIGRpZmVyZW5jaWEgeSBxdcOpIHRhbiBwcmVjaXNhIGVzIGxhIGVzdGltYWNpw7NuLgoKMi4gICoqRWwgVmFsb3IgcDoqKgoKICAgIC0gICBTb2xvIG5vcyBkaWNlIHNpIGxhIGRpZmVyZW5jaWEgZXMgc2lnbmlmaWNhdGl2YSBhIHVuIG5pdmVsIGVzcGVjw61maWNvICjOsT0wLjA1KS4KCkVuIGVzdGUgZWplbXBsbzoKCi0gICBFbCBJQyBtdWVzdHJhIGxhIG1hZ25pdHVkIHkgcHJlY2lzacOzbiBkZSBsYSBkaWZlcmVuY2lhIGRlIG1lZGlhcy4KCi0gICBFbCB2YWxvciBwIGNvbXBsZW1lbnRhIGVzdGUgYW7DoWxpc2lzIGFsIGluZGljYXIgc2kgbGEgZGlmZXJlbmNpYSBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhLgoKRXN0ZSBlbmZvcXVlIGludGVncmFkbyBlcyBlc2VuY2lhbCBwYXJhIHJlcG9ydGFyIHJlc3VsdGFkb3Mgc2lnbmlmaWNhdGl2b3MgZW4gbnVlc3RyYXMgaW52ZXN0aWdhY2lvbmVzLgo=