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
 [9]  89.69721  93.31507 118.36123 105.39721 106.01157 101.66024  91.66238 126.80370
[17] 107.46776  70.50074 110.52034  92.90813  83.98264  96.73038  84.60993  89.06663
[25]  90.62441  74.69960 112.56681 102.30060  82.92795 118.80722 106.39696  95.57393
[33] 113.42688 113.17200 112.32372 110.32960 108.30876  99.07132  95.41056  94.29293
[41]  89.57940  96.88124  81.01905 132.53434 118.11943  83.15337  93.95673  93.00017
[49] 111.69948  98.74946
str(niveles_glucosa)
 num [1:50] 91.6 96.5 123.4 101.1 101.9 ...

Paso 2: Calcular la media y el error estándar

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.

Grados de libertad ( 𝑑 𝑓 ): Calculado como 𝑛 − 1

(donde 𝑛 n es el tamaño de la muestra).

Fórmula:

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()

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

Calculo en R

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

# Calcular estadísticas
media <- mean(datos)  # Media muestral ( <- = aparece con alt + - (gión))
sd <- sd(datos)       # Desviación estándar muestral
n <- length(datos)    # Tamaño de la muestra
se <- sd / sqrt(n)    # Error estándar

# Nivel de significancia
alpha <- 0.05

# 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("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 ]

Interpretación

  • El Intervalo de Confianza del 95% indica que estamos 95% seguros de que el verdadero valor poblacional de μ está entre \[IC inf - IC sup\]

  • Este rango refleja tanto la variabilidad en los datos como el tamaño de la muestra.

  • El valor tα/2​ ajusta el margen de error según el tamaño de la muestra y su variabilidad.

Cuadro Resumen: Cálculo de Intervalos de Confianza para Diferentes Parámetros

A continuación, se presenta un cuadro que resume los métodos de cálculo de intervalos de confianza (IC) para los parámetros más comunes en estadística:

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:

set.seed(123)
niveles_glucosa <- rnorm(200, mean = 100, sd = 15)  # Media = 100, SD = 15

Paso 2: Cálculo del IC 95%

# Calcular estadísticos
media <- mean(niveles_glucosa)  # Media muestral
sd <- sd(niveles_glucosa)       # Desviación estándar muestral
n <- length(niveles_glucosa)    # Tamaño de la muestra
se <- sd / sqrt(n)              # Error estándar

# IC 95%
alpha <- 0.05
t_critico <- qt(1 - alpha / 2, df = n - 1)  # Valor crítico de t
margen_error <- t_critico * se              # Margen de error
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%: [ 97.9 , 101.84 ]

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.

library(ggplot2)

# Crear un data frame para el gráfico
df <- data.frame(
  media = media,
  ic_inf = ic_inf,
  ic_sup = ic_sup
)

# Graficar
ggplot(df, aes(x = 1)) +
  geom_errorbar(aes(ymin = ic_inf, ymax = ic_sup), width = 0.2, color = "blue") + ylim(0,200)+
  geom_point(aes(y = media), size = 4, color = "red") +
  geom_hline(yintercept = 95, linetype = "dashed", color = "black", size = 1.2) +
  labs(
    title = "Comparación entre Intervalos de Confianza e Hipótesis Nula",
    x = "Muestra (niveles de glucosa)",
    y = "Niveles de Glucosa (mg/dL)"
  ) +
  theme_minimal()

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)

set.seed(123)  # Reproducibilidad

# Simular datos
grupo_control <- rnorm(30, mean = 100, sd = 15)  # Media = 100, SD = 15
grupo_experimental <- rnorm(30, mean = 110, sd = 15)  # Media = 110, SD = 15

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"))

¿Te gustaría agregar la significancia al gráfico?

Para agregar la significancia a un gráfico de comparación entre dos grupos con ggpubr, puedes usar la función stat_compare_means() que simplifica la adición de etiquetas de significancia estadística 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.

LS0tDQp0aXRsZTogIkludGVydmFsb3MgZGUgQ29uZmlhbnphIHkgVGVvcmVtYSBkZWwgbMOtbWl0ZSBjZW50cmFsIg0KYXV0aG9yOiAiRHIuIEp1YW4gRmlkZWwgT3N1bmEtUmFtb3MiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sgDQplZGl0b3I6IHZpc3VhbA0KcmV2ZWFsanM6DQogIHRoZW1lOiBzb2xhcml6ZWQNCiAgdHJhbnNpdGlvbjogc2xpZGUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIEludGVydmFsb3MgZGUgQ29uZmlhbnphDQoNCiMjIEludHJvZHVjY2nDs246DQoNClVuIGludGVydmFsbyBkZSBjb25maWFuemEgKElDKSBlcyB1biByYW5nbyBkZSB2YWxvcmVzIGRlbnRybyBkZWwgY3VhbCBwb2RlbW9zIGRlY2lyLCAtIGNvbiBjaWVydG8gbml2ZWwgZGUgY29uZmlhbnphIChlLmcuLCA5NSUpLCBxdWUgc2UgZW5jdWVudHJhIGVsIHZhbG9yIHZlcmRhZGVybyAtIGRlIHVuIHBhcsOhbWV0cm8gcG9ibGFjaW9uYWwgKGNvbW8gbGEgbWVkaWEpLiBFcyBpbXBvcnRhbnRlIHJlY29yZGFyIHF1ZSB1biBJQyAtIE5PIG1pZGUgbGEgdmFyaWFiaWxpZGFkIGRlIGxvcyBkYXRvcywgc2lubyBsYSBwcmVjaXNpw7NuIGRlIGxhIGVzdGltYWNpw7NuIGRlIHVuIHBhcmFtZXRybywgcG9yIGVqZW1wbG8gZGUgbGEgbWVkaWEuDQoNCioqRWplcmNpY2lvOlwNClwNCkV4cGxpY2FjacOzbiBwYXNvIGEgcGFzbyoqDQoNCjEuICAqKkNyZWFjacOzbiBkZSBkYXRvcyBzaW11bGFkb3M6KioNCg0KICAgIC0gICBHZW5lcmFtb3MgdW4gY29uanVudG8gZGUgZGF0b3MgZmljdGljaW8gcmVwcmVzZW50YW5kbyBsb3Mgbml2ZWxlcyBkZSBnbHVjb3NhIGVuIDUwIHBlcnNvbmFzLg0KDQoyLiAgKipDw6FsY3VsbyBkZSBsYSBtZWRpYSB5IGVsIGVycm9yIGVzdMOhbmRhcjoqKg0KDQogICAgLSAgIExhICoqbWVkaWEqKiBlcyBsYSBlc3RpbWFjacOzbiBwdW50dWFsIGRlIGxvcyBkYXRvcy4NCg0KICAgIC0gICBFbCAqKmVycm9yIGVzdMOhbmRhcioqIG1pZGUgbGEgcHJlY2lzacOzbiBkZSBsYSBtZWRpYSBlbiBiYXNlIGFsIHRhbWHDsW8gZGUgbGEgbXVlc3RyYS4NCg0KMy4gICoqQ8OhbGN1bG8gZGVsIGludGVydmFsbyBkZSBjb25maWFuemE6KioNCg0KICAgIC0gICBVc2Ftb3MgbGEgZGlzdHJpYnVjacOzbiB0IGRlIFN0dWRlbnQgZGViaWRvIGFsIHRhbWHDsW8gZGUgbXVlc3RyYSAoblw8MzApLg0KDQogICAgLSAgIENhbGN1bGFtb3MgZWwgbWFyZ2VuIGRlIGVycm9yIG11bHRpcGxpY2FuZG8gZWwgZXJyb3IgZXN0w6FuZGFyIHBvciBlbCB2YWxvciBjcsOtdGljbyBkZSB0Lg0KDQo0LiAgKipSZXN1bHRhZG9zOioqDQoNCiAgICAtICAgRWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBub3MgZGEgZWwgcmFuZ28gZGVudHJvIGRlbCBjdWFsLCBjb24gdW4gOTUlIGRlIGNvbmZpYW56YSwgY3JlZW1vcyBxdWUgc2UgZW5jdWVudHJhIGxhIHZlcmRhZGVyYSBtZWRpYSBwb2JsYWNpb25hbC4NCg0KNS4gICoqVmlzdWFsaXphY2nDs246KioNCg0KICAgIC0gICBVbiBncsOhZmljbyBtdWVzdHJhIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGRhdG9zIHkgbG9zIGzDrW1pdGVzIGRlbCBJQyBwYXJhIGludGVycHJldGFyIGbDoWNpbG1lbnRlIGxvcyByZXN1bHRhZG9zLg0KDQojIyBQYXNvIDE6IENyZWFyIHVuIGNvbmp1bnRvIGRlIGRhdG9zDQoNClNpbXVsYXJlbW9zIHVuIGNvbmp1bnRvIGRlIGRhdG9zIHF1ZSByZXByZXNlbnRlIGxvcyBuaXZlbGVzIGRlIGdsdWNvc2EgKG1nL2RMKSBkZSA1MCBwZXJzb25hcy4NCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpICAjIEFzZWd1cmFtb3MgcmVwcm9kdWNpYmlsaWRhZA0Kbml2ZWxlc19nbHVjb3NhIDwtIHJub3JtKDUwLCBtZWFuID0gMTAwLCBzZCA9IDE1KSAgIyBNZWRpYSA9IDEwMCwgRGVzdmlhY2nDs24gZXN0w6FuZGFyID0gMTUNCg0Kbml2ZWxlc19nbHVjb3NhDQoNCnN0cihuaXZlbGVzX2dsdWNvc2EpDQpgYGANCg0KIyMgUGFzbyAyOiBDYWxjdWxhciBsYSBtZWRpYSB5IGVsIGVycm9yIGVzdMOhbmRhcg0KDQpgYGB7cn0NCm1lZGlhIDwtIG1lYW4obml2ZWxlc19nbHVjb3NhKSAgIyBNZWRpYSBkZSBsb3MgZGF0b3MNCnNkIDwtIHNkKG5pdmVsZXNfZ2x1Y29zYSkgICAgICAgIyBEZXN2aWFjacOzbiBlc3TDoW5kYXINCm4gPC0gbGVuZ3RoKG5pdmVsZXNfZ2x1Y29zYSkgICAgIyBUYW1hw7FvIGRlIGxhIG11ZXN0cmENCnNlIDwtIHNkIC8gc3FydChuKSAgICAgICAgICAgICAgIyBFcnJvciBlc3TDoW5kYXIgZGUgbGEgbWVkaWENCg0KbWVkaWENCnNkDQpuDQpzZQ0KYGBgDQoNCiMjIFBhc28gMzogQ2FsY3VsYXIgZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBkZWwgOTUlDQoNCiMjIyBEZXRlcm1pbmFtb3MgbG9zIGzDrW1pdGVzIGRlbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphDQoNCkVsIGPDoWxjdWxvIGRlIHVuIEludGVydmFsbyBkZSBDb25maWFuemEgKElDKSBkZWwgOTUlIGltcGxpY2EgdmFyaW9zIHBhc29zIGNsYXZlLiBWYW1vcyBhIGRlc2dsb3NhciB5IGVudGVuZGVyIGNhZGEgdW5vIGRlIGVsbG9zIGRldGFsbGFkYW1lbnRlLg0KDQpQYXJhIGNhbGN1bGFyIHVuIElDIGRlIGxhIG1lZGlhIHBvYmxhY2lvbmFsICjwnZyHKSBiYXNhZG8gZW4gdW5hIG11ZXN0cmEsIHVzYW1vcyBsYSBzaWd1aWVudGUgZm9ybXVsYToNCg0KIVtdKGltYWdlcy9jbGlwYm9hcmQtNDIzOTI4NDc5OS5wbmcpDQoNCiMjIyBQYXNvIDE6IE5pdmVsIGRlIHNpZ25pZmljYW5jaWEgKPCdm7wpDQoNCkVsIG5pdmVsIGRlIGNvbmZpYW56YSAoMSDiiJLwnZu8KSBpbmRpY2EgcXXDqSB0YW4gc2VndXJvIGVzdGFtb3MgZGUgcXVlIGVsIGludGVydmFsbyBjb250aWVuZSBlbCB2YWxvciB2ZXJkYWRlcm8gZGUgbGEgbWVkaWEgcG9ibGFjaW9uYWw6DQoNCi0gICBQYXJhIHVuIElDIGRlbCA5NSUsIGVsIG5pdmVsIGRlIGNvbmZpYW56YSBlcyAwLjk1ICjwnZu8PSAwLjA1KS4NCg0KzrE9MeKIkk5pdmVswqBkZcKgQ29uZmlhbnphDQoNCiMjIyBQYXNvIDI6IFZhbG9yIGNyw610aWNvICjwnZGh8J2bvC8yKQ0KDQpFbCB2YWxvciBjcsOtdGljbyAo8J2RofCdm7wvMikgZGV0ZXJtaW5hIGN1w6FudG9zIGVycm9yZXMgZXN0w6FuZGFyIG5lY2VzaXRhbW9zIHN1bWFyIHkgcmVzdGFyIHBhcmEgYWJhcmNhciBlbCA5NSUgZGUgbG9zIGRhdG9zLiBTZSBjYWxjdWxhIHV0aWxpemFuZG8gbGEgZGlzdHJpYnVjacOzbiDwnZGhIHQgZGUgU3R1ZGVudCB5IGRlcGVuZGUgZGU6DQoNCk5pdmVsIGRlIGNvbmZpYW56YSAoMeKIks6xKTogUGFyYSB1biBJQyBkZWwgOTUlLCB1c2Ftb3Mg8J2bvC8yPSAwLjAyNSBwYXJhIGNhbGN1bGFyIGVsIGzDrW1pdGUgc3VwZXJpb3IgZSBpbmZlcmlvci4NCg0KIVtdKGltYWdlcy9jbGlwYm9hcmQtMTk5ODU0NDE0Mi5wbmcpDQoNCkdyYWRvcyBkZSBsaWJlcnRhZCAoIPCdkZEg8J2RkyApOiBDYWxjdWxhZG8gY29tbyDwnZGbIOKIkiAxDQoNCihkb25kZSDwnZGbIG4gZXMgZWwgdGFtYcOxbyBkZSBsYSBtdWVzdHJhKS4NCg0KRsOzcm11bGE6DQoNCiFbXShpbWFnZXMvY2xpcGJvYXJkLTMwODg0Mjc4MjMucG5nKQ0KDQpgYGB7cn0NCmRmIDwtIG4gLSAxDQoNCmFscGhhIDwtIDAuMDUgICAgICAgICAgICAgICAgICAgIyBOaXZlbCBkZSBzaWduaWZpY2FuY2lhICgxIC0gOTUlKQ0KDQp0X2NyaXRpY28gPC0gcXQoMSAtIGFscGhhIC8gMiwgZGYgPSBuIC0gMSkgICMgVmFsb3IgY3LDrXRpY28gdCBwYXJhIGVsIDk1JQ0KDQptYXJnZW5fZXJyb3IgPC0gdF9jcml0aWNvICogc2UgICMgTWFyZ2VuIGRlIGVycm9yDQoNCm1hcmdlbl9lcnJvcg0KYGBgDQoNCkxhIGZ1bmNpw7NuIGBxdGAgZW4gUiBjYWxjdWxhIGVsIHZhbG9yIGNyw610aWNvIGJhc2FkbyBlbjoNCg0KLSAgIDHiiJLOsS8yOiDDgXJlYSBhY3VtdWxhZGEgZGUgbGEgY29sYSBpbmZlcmlvci4NCg0KLSAgIEdyYWRvcyBkZSBsaWJlcnRhZCAoZGYpLg0KDQojIyMgKipQYXNvIDM6IE1hcmdlbiBkZSBlcnJvcioqDQoNCkVsIG1hcmdlbiBkZSBlcnJvciBkZWZpbmUgcXXDqSB0YW4gbGVqb3MgZGUgbGEgbWVkaWEgbXVlc3RyYWwgKHjMhCkgc2UgZXh0aWVuZGUgZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YS4gU2UgY2FsY3VsYSBtdWx0aXBsaWNhbmRvIGVsIHZhbG9yIGNyw610aWNvICjwnZGh8J2bvC8yKSBwb3IgZWwgZXJyb3IgZXN0w6FuZGFyICjwnZGG8J2QuCk6DQoNCiFbXShpbWFnZXMvY2xpcGJvYXJkLTM0MjI1MzYzMzYucG5nKQ0KDQotICAgUz1kZXN2aWFjacOzbiBlc3TDoW5kYXIgZGUgbGEgbXVlc3RyYSkuDQoNCi0gICBuPSB0YW1hw7FvIGRlIGxhIG11ZXN0cmEuDQoNCmBgYHtyfQ0KbWFyZ2VuX2Vycm9yIDwtIHRfY3JpdGljbyAqIHNlICAjIE1hcmdlbiBkZSBlcnJvcg0KbWFyZ2VuX2Vycm9yDQpgYGANCg0KXA0KRmluYWxtZW50ZSwgZWwgSW50ZXJ2YWxvIGRlIENvbmZpYW56YSBzZSBjb25zdHJ1eWUgc3VtYW5kbyB5IHJlc3RhbmRvIGVsIG1hcmdlbiBkZSBlcnJvciBhIGxhIG1lZGlhIG11ZXN0cmFsOg0KDQohW10oaW1hZ2VzL2NsaXBib2FyZC01NDkxMjQwNy5wbmcpDQoNCmBgYHtyfQ0KaWNfaW5mIDwtIG1lZGlhIC0gbWFyZ2VuX2Vycm9yDQppY19pbmYNCg0KaWNfc3VwIDwtIG1lZGlhICsgbWFyZ2VuX2Vycm9yDQppY19zdXANCg0KDQojIFJlc3VsdGFkbw0KY2F0KCJNZWRpYToiLCByb3VuZChtZWRpYSwgMiksICJcbiIpDQpjYXQoIkludGVydmFsbyBkZSBDb25maWFuemEgZGVsIDk1JTogWyIsIHJvdW5kKGljX2luZiwgMiksICIsIiwgcm91bmQoaWNfc3VwLCAyKSwgIl1cbiIpDQoNCg0KYGBgDQoNClBvZGVtb3MgaW50ZXJwcmV0YXIgcXVlIGNvbiB1biA5NSUgZGUgY29uZmlhbnphLCBsYSB2ZXJkYWRlcmEgbWVkaWEgZGUgZ2x1Y29zYSBlbiBsYSBwb2JsYWNpw7NuIHNlIGVuY3VlbnRyYSBlbnRyZSA5Ni41IG1nL2RMIHkgMTA0LjUzIG1nL2RMDQoNCkVzdGUgYW7DoWxpc2lzIGVzIGVzZW5jaWFsIHBhcmEgcmVwb3J0YXIgcmVzdWx0YWRvcyBlbiBpbnZlc3RpZ2FjaW9uZXMgY2llbnTDrWZpY2FzLCB5YSBxdWUgbXVlc3RyYSBubyBzb2xvIGxhIGVzdGltYWNpw7NuIHB1bnR1YWwgc2lubyB0YW1iacOpbiBsYSBwcmVjaXNpw7NuIGRlIGxhIG1pc21hLg0KDQojIyMgKipFamVtcGxvIHByw6FjdGljbyoqDQoNClN1cG9uZ2Ftb3M6DQoNCi0gICBNZWRpYSBtdWVzdHJhbCAoeMyEKSA9IDEwMA0KDQotICAgRGVzdmlhY2nDs24gZXN0w6FuZGFyIChTKSA9IDE1DQoNCi0gICBUYW1hw7FvIGRlIG11ZXN0cmEgKG4pID0gMzANCg0KYGBge3J9DQojIEVzdGFibGVjZW1vcyBQYXLDoW1ldHJvcw0KYWxwaGEgPC0gMC4wNQ0KbiA8LSAxNQ0KUyA8LSAzMA0KbWVkaWEgPC0gMTAwDQoNCiMgRXJyb3IgZXN0w6FuZGFyDQpzZSA8LSBTIC8gc3FydChuKQ0KDQojIFZhbG9yIGNyw610aWNvIHQNCnRfY3JpdGljbyA8LSBxdCgxIC0gYWxwaGEgLyAyLCBkZiA9IG4gLSAxKQ0KDQojIE1hcmdlbiBkZSBlcnJvcg0KbWFyZ2VuX2Vycm9yIDwtIHRfY3JpdGljbyAqIHNlDQoNCiMgSW50ZXJ2YWxvIGRlIGNvbmZpYW56YQ0KaWNfaW5mIDwtIG1lZGlhIC0gbWFyZ2VuX2Vycm9yDQppY19zdXAgPC0gbWVkaWEgKyBtYXJnZW5fZXJyb3INCm1hcmdlbl9lcnJvcg0KY2F0KCJJbnRlcnZhbG8gZGUgQ29uZmlhbnphIGRlbCA5NSU6Iiwgcm91bmQoaWNfaW5mLCAyKSwgIi0iLCByb3VuZChpY19zdXAsIDIpLCAiXG4iKQ0KDQpgYGANCg0KIVtdKGltYWdlcy9jbGlwYm9hcmQtMjc4NDE4OTY5NC5wbmcpDQoNCiMjIyAqKlJlc3VtZW4gZ3LDoWZpY28qKg0KDQpQdWVkZXMgdmlzdWFsaXphciBlbCBjw6FsY3VsbyBkZWwgSUMgZW4gdW4gZ3LDoWZpY28gcGFyYSBtYXlvciBjbGFyaWRhZDoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZQ0KZGYgPC0gZGF0YS5mcmFtZSgNCiAgbWVkaWEgPSBtZWRpYSwNCiAgaWNfaW5mID0gaWNfaW5mLA0KICBpY19zdXAgPSBpY19zdXANCikNCg0KIyBHcmFmaWNhciBlbCBJQw0KZ2dwbG90KGRmLCBhZXMoeCA9IDEsIHkgPSBtZWRpYSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgY29sb3IgPSAicmVkIikgKyANCiAgeWxpbSgwLDIwMCkgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gaWNfaW5mLCB5bWF4ID0gaWNfc3VwKSwgd2lkdGggPSAwLjIsIGNvbG9yID0gImJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiSW50ZXJ2YWxvIGRlIENvbmZpYW56YSBkZWwgOTUlIHBhcmEgbGEgTWVkaWEiLA0KICAgICAgIHggPSAiTXVlc3RyYSIsDQogICAgICAgeSA9ICJNZWRpYSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQohW10oaW1hZ2VzL2NsaXBib2FyZC0zODkzNzM1NTcwLnBuZykNCg0KIVshW10oaW1hZ2VzL2NsaXBib2FyZC0xNzc4MjQ1NzA1LnBuZyldKGltYWdlcy9jbGlwYm9hcmQtMjUxNDMyMTg5MC5wbmcpDQoNCmBgYHtyfQ0KdF9jcml0aWNvIDwtIHF0KDEgLSBhbHBoYSAvIDIsIGRmID0gbiAtIDEpDQoNCmBgYA0KDQohW10oaW1hZ2VzL2NsaXBib2FyZC0zMDMyNTY3NTc2LnBuZykNCg0KIVshW10oaW1hZ2VzL2NsaXBib2FyZC00NDE2MDgxMDkucG5nKV0oaW1hZ2VzL2NsaXBib2FyZC0zNzM0MTkxMTIxLnBuZykNCg0KIVshW10oaW1hZ2VzL2NsaXBib2FyZC0xOTE0NzYzMTkucG5nKV0oaW1hZ2VzL2NsaXBib2FyZC0xMzYyOTM4NjIxLnBuZykNCg0KKipDYWxjdWxvIGVuIFIqKg0KDQpgYGB7cn0NCiMgRGF0b3Mgc2ltdWxhZG9zDQpzZXQuc2VlZCgxMjMpDQpkYXRvcyA8LSBybm9ybSgzMCwgbWVhbiA9IDEwMCwgc2QgPSAxNSkNCg0KIyBDYWxjdWxhciBlc3RhZMOtc3RpY2FzDQptZWRpYSA8LSBtZWFuKGRhdG9zKSAgIyBNZWRpYSBtdWVzdHJhbCAoIDwtID0gYXBhcmVjZSBjb24gYWx0ICsgLSAoZ2nDs24pKQ0Kc2QgPC0gc2QoZGF0b3MpICAgICAgICMgRGVzdmlhY2nDs24gZXN0w6FuZGFyIG11ZXN0cmFsDQpuIDwtIGxlbmd0aChkYXRvcykgICAgIyBUYW1hw7FvIGRlIGxhIG11ZXN0cmENCnNlIDwtIHNkIC8gc3FydChuKSAgICAjIEVycm9yIGVzdMOhbmRhcg0KDQojIE5pdmVsIGRlIHNpZ25pZmljYW5jaWENCmFscGhhIDwtIDAuMDUNCg0KIyBWYWxvciBjcsOtdGljbyB0DQp0X2NyaXRpY28gPC0gcXQoMSAtIGFscGhhIC8gMiwgZGYgPSBuIC0gMSkNCg0KIyBNYXJnZW4gZGUgZXJyb3INCm1hcmdlbl9lcnJvciA8LSB0X2NyaXRpY28gKiBzZQ0KDQojIEludGVydmFsbyBkZSBjb25maWFuemENCmljX2luZiA8LSBtZWRpYSAtIG1hcmdlbl9lcnJvcg0KaWNfc3VwIDwtIG1lZGlhICsgbWFyZ2VuX2Vycm9yDQoNCmNhdCgiTWVkaWE6Iiwgcm91bmQobWVkaWEsIDIpLCAiXG4iKQ0KY2F0KCJJbnRlcnZhbG8gZGUgQ29uZmlhbnphIGRlbCA5NSU6IFsiLCByb3VuZChpY19pbmYsIDIpLCAiLCIsIHJvdW5kKGljX3N1cCwgMiksICJdXG4iKQ0KDQpgYGANCg0KIyMjICoqSW50ZXJwcmV0YWNpw7NuKioNCg0KLSAgIEVsICoqSW50ZXJ2YWxvIGRlIENvbmZpYW56YSBkZWwgOTUlKiogaW5kaWNhIHF1ZSBlc3RhbW9zIDk1JSBzZWd1cm9zIGRlIHF1ZSBlbCB2ZXJkYWRlcm8gdmFsb3IgcG9ibGFjaW9uYWwgZGUgzrwgZXN0w6EgZW50cmUgXFtJQyBpbmYgLSBJQyBzdXBcXQ0KDQotICAgRXN0ZSByYW5nbyByZWZsZWphIHRhbnRvIGxhIHZhcmlhYmlsaWRhZCBlbiBsb3MgZGF0b3MgY29tbyBlbCB0YW1hw7FvIGRlIGxhIG11ZXN0cmEuDQoNCi0gICBFbCB2YWxvciB0zrEvMuKAiyBhanVzdGEgZWwgbWFyZ2VuIGRlIGVycm9yIHNlZ8O6biBlbCB0YW1hw7FvIGRlIGxhIG11ZXN0cmEgeSBzdSB2YXJpYWJpbGlkYWQuDQoNCiMjIEN1YWRybyBSZXN1bWVuOiBDw6FsY3VsbyBkZSBJbnRlcnZhbG9zIGRlIENvbmZpYW56YSBwYXJhIERpZmVyZW50ZXMgUGFyw6FtZXRyb3MNCg0KQSBjb250aW51YWNpw7NuLCBzZSBwcmVzZW50YSB1biBjdWFkcm8gcXVlIHJlc3VtZSBsb3MgbcOpdG9kb3MgZGUgY8OhbGN1bG8gZGUgaW50ZXJ2YWxvcyBkZSBjb25maWFuemEgKElDKSBwYXJhIGxvcyBwYXLDoW1ldHJvcyBtw6FzIGNvbXVuZXMgZW4gZXN0YWTDrXN0aWNhOg0KDQohW10oaW1hZ2VzL2NsaXBib2FyZC0zMDI0ODEwMTc5LnBuZykNCg0KIyMjICoqRGlmZXJlbmNpYXMgZW50cmUgSW50ZXJ2YWxvcyBkZSBDb25maWFuemEgeSBlbCBWYWxvciBwKioNCg0KMS4gICoqSW50ZXJ2YWxvcyBkZSBDb25maWFuemEgKElDKToqKg0KDQogICAgLSAgIExvcyBJQyBub3MgZGFuIHVuIHJhbmdvIHBsYXVzaWJsZSBwYXJhIGVsIHZhbG9yIHZlcmRhZGVybyBkZSB1biBwYXLDoW1ldHJvIChjb21vIGxhIG1lZGlhIG8gdW5hIGRpZmVyZW5jaWEgZW50cmUgbWVkaWFzKS4NCg0KICAgIC0gICBJbnRlcnByZXRhY2nDs246IFVuIElDIGRlbCA5NSUgaW5kaWNhIHF1ZSwgc2kgcmVwaXRpw6lyYW1vcyBlbCBlc3R1ZGlvIG3Dumx0aXBsZXMgdmVjZXMsIGVsIDk1JSBkZSBlc29zIGludGVydmFsb3MgaW5jbHVpcsOtYSBlbCB2YWxvciB2ZXJkYWRlcm8gZGVsIHBhcsOhbWV0cm8uDQoNCjIuICAqKlZhbG9yIHA6KioNCg0KICAgIC0gICBFbCB2YWxvciBwIGluZGljYSBsYSBwcm9iYWJpbGlkYWQgZGUgb2JzZXJ2YXIgdW4gZWZlY3RvIHRhbiBleHRyZW1vIChvIG3DoXMpIHF1ZSBlbCBlbmNvbnRyYWRvLCBiYWpvIGxhIGhpcMOzdGVzaXMgbnVsYSAoSDDigIspLg0KDQogICAgLSAgIEVzIHVuYSBoZXJyYW1pZW50YSBwYXJhIHRvbWFyIGRlY2lzaW9uZXMgc29icmUgcmVjaGF6YXIgbyBubyBIMC4NCg0KMy4gICoqRGlmZXJlbmNpYSBwcsOhY3RpY2E6KioNCg0KICAgIC0gICBFbCBJQyBwcm9wb3JjaW9uYSBpbmZvcm1hY2nDs24gc29icmUgbGEgbWFnbml0dWQgeSBwcmVjaXNpw7NuIGRlbCBlZmVjdG8gZXN0aW1hZG8uDQoNCiAgICAtICAgRWwgdmFsb3IgcCBzb2xvIGluZGljYSBzaSB1biBlZmVjdG8gZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2bywgc2luIHByb3BvcmNpb25hciBpbmZvcm1hY2nDs24gZGlyZWN0YSBzb2JyZSBzdSBtYWduaXR1ZC4NCg0KIyMjICoqVXNvIGRlIFI6IENvbXBhcmFjacOzbiBlbnRyZSBJQyB5IHZhbG9yIHAqKg0KDQojIyMjICoqUGFzbyAxOiBEYXRvcyBkZWwgRWplbXBsbyoqDQoNClNpbXVsYW1vcyBkYXRvcyBkZSBuaXZlbGVzIGRlIGdsdWNvc2E6DQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0Kbml2ZWxlc19nbHVjb3NhIDwtIHJub3JtKDIwMCwgbWVhbiA9IDEwMCwgc2QgPSAxNSkgICMgTWVkaWEgPSAxMDAsIFNEID0gMTUNCg0KYGBgDQoNClBhc28gMjogQ8OhbGN1bG8gZGVsIElDIDk1JQ0KDQpgYGB7cn0NCiMgQ2FsY3VsYXIgZXN0YWTDrXN0aWNvcw0KbWVkaWEgPC0gbWVhbihuaXZlbGVzX2dsdWNvc2EpICAjIE1lZGlhIG11ZXN0cmFsDQpzZCA8LSBzZChuaXZlbGVzX2dsdWNvc2EpICAgICAgICMgRGVzdmlhY2nDs24gZXN0w6FuZGFyIG11ZXN0cmFsDQpuIDwtIGxlbmd0aChuaXZlbGVzX2dsdWNvc2EpICAgICMgVGFtYcOxbyBkZSBsYSBtdWVzdHJhDQpzZSA8LSBzZCAvIHNxcnQobikgICAgICAgICAgICAgICMgRXJyb3IgZXN0w6FuZGFyDQoNCiMgSUMgOTUlDQphbHBoYSA8LSAwLjA1DQp0X2NyaXRpY28gPC0gcXQoMSAtIGFscGhhIC8gMiwgZGYgPSBuIC0gMSkgICMgVmFsb3IgY3LDrXRpY28gZGUgdA0KbWFyZ2VuX2Vycm9yIDwtIHRfY3JpdGljbyAqIHNlICAgICAgICAgICAgICAjIE1hcmdlbiBkZSBlcnJvcg0KaWNfaW5mIDwtIG1lZGlhIC0gbWFyZ2VuX2Vycm9yDQppY19zdXAgPC0gbWVkaWEgKyBtYXJnZW5fZXJyb3INCg0KY2F0KCJJbnRlcnZhbG8gZGUgQ29uZmlhbnphIGRlbCA5NSU6IFsiLCByb3VuZChpY19pbmYsIDIpLCAiLCIsIHJvdW5kKGljX3N1cCwgMiksICJdXG4iKQ0KDQpgYGANCg0KIyMjIyAqKlBhc28gMzogQ8OhbGN1bG8gZGVsIFZhbG9yIHAqKg0KDQpTdXBvbmdhbW9zIHF1ZSBxdWVyZW1vcyBwcm9iYXIgc2kgbGEgbWVkaWEgcG9ibGFjaW9uYWwgZXMgaWd1YWwgYSA5NSAoIEgw4oCLOs68PTk1KToNCg0KYGBge3J9DQojIFBydWViYSB0IHBhcmEgbWVkaWEgcG9ibGFjaW9uYWwgZGUgOTUNCnRfdGVzdCA8LSB0LnRlc3Qobml2ZWxlc19nbHVjb3NhLCBtdSA9IDk1KSAgIyBIaXDDs3Rlc2lzIG51bGE6IG1lZGlhID0gOTUNCg0KIyBSZXN1bHRhZG8gZGVsIHZhbG9yIHANCmNhdCgiVmFsb3IgcDoiLCB0X3Rlc3QkcC52YWx1ZSwgIlxuIikNCg0KYGBgDQoNCiMjIyAqKlJlc3VsdGFkb3M6KioNCg0KMS4gICoqSUMgOTUlOioqIE11ZXN0cmEgZWwgcmFuZ28gZW4gZWwgcXVlIGNyZWVtb3MgcXVlIGVzdMOhIGxhIHZlcmRhZGVyYSBtZWRpYSBkZSBsb3Mgbml2ZWxlcyBkZSBnbHVjb3NhLg0KDQogICAgLSAgIEVqZW1wbG86IFNpIGVsIElDIGVzIFxbOTMuOCwxMDMuMlxdLCBzYWJlbW9zIHF1ZSBjb24gdW4gOTUlIGRlIGNvbmZpYW56YSwgbGEgdmVyZGFkZXJhIG1lZGlhIGRlIGxhIHBvYmxhY2nDs24gZXN0w6EgZGVudHJvIGRlIGVzdGUgcmFuZ28uDQoNCjIuICAqKlZhbG9yIHA6KiogTWlkZSBzaSBsb3MgZGF0b3MgcmVzcGFsZGFuIG8gcmVjaGF6YW4gbGEgSDDigIsuDQoNCiAgICAtICAgRWplbXBsbzogU2kgZWwgdmFsb3IgcCBlcyBcPCAwLjA1LCByZWNoYXphbW9zIEgw4oCLIChlcyBkZWNpciwgY3JlZW1vcyBxdWUgbGEgbWVkaWEgbm8gZXMgOTUpLg0KDQojIyMgKipWaXN1YWxpemFjacOzbjogSUMgdnMgVmFsb3IgcCoqDQoNClBvZGVtb3MgdXNhciB1biBncsOhZmljbyBwYXJhIGV4cGxpY2FyIGPDs21vIGVsIElDIHkgZWwgdmFsb3IgcCBzZSByZWxhY2lvbmFuIHZpc3VhbG1lbnRlLg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBDcmVhciB1biBkYXRhIGZyYW1lIHBhcmEgZWwgZ3LDoWZpY28NCmRmIDwtIGRhdGEuZnJhbWUoDQogIG1lZGlhID0gbWVkaWEsDQogIGljX2luZiA9IGljX2luZiwNCiAgaWNfc3VwID0gaWNfc3VwDQopDQoNCiMgR3JhZmljYXINCmdncGxvdChkZiwgYWVzKHggPSAxKSkgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gaWNfaW5mLCB5bWF4ID0gaWNfc3VwKSwgd2lkdGggPSAwLjIsIGNvbG9yID0gImJsdWUiKSArIHlsaW0oMCwyMDApKw0KICBnZW9tX3BvaW50KGFlcyh5ID0gbWVkaWEpLCBzaXplID0gNCwgY29sb3IgPSAicmVkIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA5NSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS4yKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29tcGFyYWNpw7NuIGVudHJlIEludGVydmFsb3MgZGUgQ29uZmlhbnphIGUgSGlww7N0ZXNpcyBOdWxhIiwNCiAgICB4ID0gIk11ZXN0cmEgKG5pdmVsZXMgZGUgZ2x1Y29zYSkiLA0KICAgIHkgPSAiTml2ZWxlcyBkZSBHbHVjb3NhIChtZy9kTCkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCiMjIyAqKkludGVycHJldGFjacOzbiBkZWwgR3LDoWZpY28qKg0KDQoxLiAgKipJbnRlcnZhbG8gZGUgQ29uZmlhbnphOioqDQoNCiAgICAtICAgTGEgbMOtbmVhIHB1bnRlYWRhIG11ZXN0cmEgZWwgcmFuZ28gcGxhdXNpYmxlIHBhcmEgbGEgdmVyZGFkZXJhIG1lZGlhIGRlIGxhIHBvYmxhY2nDs24uDQoNCiAgICAtICAgU2kgSDA9OTUgY2FlIGZ1ZXJhIGRlbCBpbnRlcnZhbG8gKGzDrW5lYSBuZWdyYSBkaXNjb250aW51YSksIHBvZGVtb3MgY29uY2x1aXIgcXVlIGVzIGltcHJvYmFibGUgcXVlIM68PTk1DQoNCjIuICAqKlZhbG9yIHA6KioNCg0KICAgIC0gICBTaSBlbCB2YWxvciBwIGVzIG1lbm9yIHF1ZSDOsT0wLjA1LCByZWNoYXphbW9zIEgw4oCLLCBxdWUgZXMgY29uc2lzdGVudGUgY29uIGVsIGhlY2hvIGRlIHF1ZSBlbCBJQyBubyBpbmNsdXllIDk1Lg0KDQojIyMgKipWZW50YWphIGRlIGNvbWJpbmFyIElDIHkgdmFsb3IgcCoqDQoNCjEuICAqKklDOioqIFByb3BvcmNpb25hIHVuYSB2aXNpw7NuIG3DoXMgaW50ZWdyYXRpdmEsIG1vc3RyYW5kbyBsYSBtYWduaXR1ZCBkZWwgZWZlY3RvIHkgc3UgcHJlY2lzacOzbi4NCg0KMi4gICoqVmFsb3IgcDoqKiBQZXJtaXRlIHRvbWFyIGRlY2lzaW9uZXMgcsOhcGlkYXMgc29icmUgbGEgaGlww7N0ZXNpcyBudWxhLCBwZXJvIG5vIGluZGljYSBsYSBtYWduaXR1ZCBkZWwgZWZlY3RvLg0KDQojIyMgKipDb25jbHVzacOzbioqDQoNCi0gICBFbiBpbnZlc3RpZ2FjaW9uZXMgZXBpZGVtaW9sw7NnaWNhcywgY2zDrW5pY2FzIG8gYmlvbG9naWNhcy4gTG9zIElDIHNvbiBwcmVmZXJpYmxlcyBwb3JxdWUgbm8gc29sbyBpbmRpY2FuIHNpIHVuIGVmZWN0byBlcyBzaWduaWZpY2F0aXZvLCBzaW5vIHRhbWJpw6luICoqcXXDqSB0YW4gZ3JhbmRlIG8gcHJlY2lzbyBlcyBlbCBlZmVjdG8gZXN0aW1hZG8qKi4NCg0KLSAgIEVsICoqdmFsb3IgcCoqIGNvbXBsZW1lbnRhIGVzdGUgYW7DoWxpc2lzLCBheXVkw6FuZG9ub3MgYSBkZXRlcm1pbmFyIHNpIGRlYmVtb3MgcmVjaGF6YXIgdW5hIGhpcMOzdGVzaXMgbnVsYSBlc3BlY8OtZmljYS4NCg0KQ3VhbmRvIGNvbXBhcmFtb3MgZG9zIGdydXBvcywgbG9zICoqSW50ZXJ2YWxvcyBkZSBDb25maWFuemEgKElDKSoqIHkgZWwgKip2YWxvciBwKiogc29uIGhlcnJhbWllbnRhcyBjb21wbGVtZW50YXJpYXMgcGFyYSBpbnRlcnByZXRhciBsYXMgZGlmZXJlbmNpYXMuIEEgY29udGludWFjacOzbiwgdGUgcHJlc2VudG8gdW4gZWplbXBsbyBkZXRhbGxhZG8gZW4gKipSKiogcGFyYSBjb21wYXJhciBkb3MgZ3J1cG9zIGNvbiB1biBlbmZvcXVlIGVuIGxhIGVzdGltYWNpw7NuIGRlIElDIHkgZWwgdmFsb3IgcC4NCg0KIyMjICoqQ29tcGFyYWNpw7NuIGRlIERvcyBHcnVwb3MqKg0KDQpTdXBvbmdhbW9zIHF1ZSBxdWVyZW1vcyBjb21wYXJhciBsb3Mgbml2ZWxlcyBkZSBnbHVjb3NhIGVudHJlIGRvcyBncnVwb3M6ICoqZ3J1cG8gY29udHJvbCoqIHkgKipncnVwbyBleHBlcmltZW50YWwqKi4NCg0KIyMjIyAqKihEYXRvcyBTaW11bGFkb3MpKioNCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpICAjIFJlcHJvZHVjaWJpbGlkYWQNCg0KIyBTaW11bGFyIGRhdG9zDQpncnVwb19jb250cm9sIDwtIHJub3JtKDMwLCBtZWFuID0gMTAwLCBzZCA9IDE1KSAgIyBNZWRpYSA9IDEwMCwgU0QgPSAxNQ0KZ3J1cG9fZXhwZXJpbWVudGFsIDwtIHJub3JtKDMwLCBtZWFuID0gMTEwLCBzZCA9IDE1KSAgIyBNZWRpYSA9IDExMCwgU0QgPSAxNQ0KDQpgYGANCg0KIyMjICoqUGFzbyAxOiBDw6FsY3VsbyBkZWwgSW50ZXJ2YWxvIGRlIENvbmZpYW56YSBwYXJhIGxhIERpZmVyZW5jaWEgZGUgTWVkaWFzKioNCg0KIyMjIyAqKkbDs3JtdWxhOioqDQoNCiFbXShpbWFnZXMvY2xpcGJvYXJkLTcwNjU1OTIyNi5wbmcpDQoNCioqQ8OzZGlnbyBwYXJhIElDKioNCg0KYGBge3J9DQojIEVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzDQptZWRpYV9jb250cm9sIDwtIG1lYW4oZ3J1cG9fY29udHJvbCkNCm1lZGlhX2V4cGVyaW1lbnRhbCA8LSBtZWFuKGdydXBvX2V4cGVyaW1lbnRhbCkNCnNkX2NvbnRyb2wgPC0gc2QoZ3J1cG9fY29udHJvbCkNCnNkX2V4cGVyaW1lbnRhbCA8LSBzZChncnVwb19leHBlcmltZW50YWwpDQpuX2NvbnRyb2wgPC0gbGVuZ3RoKGdydXBvX2NvbnRyb2wpDQpuX2V4cGVyaW1lbnRhbCA8LSBsZW5ndGgoZ3J1cG9fZXhwZXJpbWVudGFsKQ0KDQojIERpZmVyZW5jaWEgZGUgbWVkaWFzDQpkaWZlcmVuY2lhIDwtIG1lZGlhX2V4cGVyaW1lbnRhbCAtIG1lZGlhX2NvbnRyb2wNCg0KIyBFcnJvciBlc3TDoW5kYXIgY29tYmluYWRvDQpzZSA8LSBzcXJ0KChzZF9jb250cm9sXjIgLyBuX2NvbnRyb2wpICsgKHNkX2V4cGVyaW1lbnRhbF4yIC8gbl9leHBlcmltZW50YWwpKQ0KDQojIFZhbG9yIGNyw610aWNvIHQgcGFyYSBJQyBkZWwgOTUlDQphbHBoYSA8LSAwLjA1DQp0X2NyaXRpY28gPC0gcXQoMSAtIGFscGhhIC8gMiwgZGYgPSBuX2NvbnRyb2wgKyBuX2V4cGVyaW1lbnRhbCAtIDIpDQoNCiMgTWFyZ2VuIGRlIGVycm9yDQptYXJnZW5fZXJyb3IgPC0gdF9jcml0aWNvICogc2UNCg0KIyBMw61taXRlcyBkZWwgSUMNCmljX2luZiA8LSBkaWZlcmVuY2lhIC0gbWFyZ2VuX2Vycm9yDQppY19zdXAgPC0gZGlmZXJlbmNpYSArIG1hcmdlbl9lcnJvcg0KDQpjYXQoIkRpZmVyZW5jaWEgZGUgbWVkaWFzOiIsIHJvdW5kKGRpZmVyZW5jaWEsIDIpLCAiXG4iKQ0KY2F0KCJJbnRlcnZhbG8gZGUgQ29uZmlhbnphIGRlbCA5NSU6IFsiLCByb3VuZChpY19pbmYsIDIpLCAiLCIsIHJvdW5kKGljX3N1cCwgMiksICJdXG4iKQ0KDQpgYGANCg0KIyMjICoqUGFzbyAyOiBQcnVlYmEgZGUgSGlww7N0ZXNpcyB5IFZhbG9yIHAqKg0KDQpVc2Ftb3MgdW5hIHBydWViYSB0IHBhcmEgZG9zIG11ZXN0cmFzIGluZGVwZW5kaWVudGVzIHBhcmEgZGV0ZXJtaW5hciBzaSBsYSBkaWZlcmVuY2lhIGVzIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmEuDQoNCiMjIyMgKipDw7NkaWdvIHBhcmEgUHJ1ZWJhIHQqKg0KDQpgYGB7cn0NCiMgUHJ1ZWJhIHQgcGFyYSBkb3MgbXVlc3RyYXMgaW5kZXBlbmRpZW50ZXMNCnRfdGVzdCA8LSB0LnRlc3QoZ3J1cG9fY29udHJvbCwgZ3J1cG9fZXhwZXJpbWVudGFsLCB2YXIuZXF1YWwgPSBUUlVFKQ0KDQojIFJlc3VsdGFkb3MNCmNhdCgiVmFsb3IgcDoiLCB0X3Rlc3QkcC52YWx1ZSwgIlxuIikNCmNhdCgiRGlmZXJlbmNpYSBlc3RpbWFkYSAodC10ZXN0KToiLCB0X3Rlc3QkZXN0aW1hdGUsICJcbiIpDQoNCmBgYA0KDQojIyMgKipQYXNvIDM6IFZpc3VhbGl6YWNpw7NuIGRlIGxvcyBSZXN1bHRhZG9zKioNCg0KUG9kZW1vcyBncmFmaWNhciBsYXMgZGlzdHJpYnVjaW9uZXMgZGUgYW1ib3MgZ3J1cG9zIHkgc3VwZXJwb25lciBsb3MgSUMgcGFyYSBsYSBkaWZlcmVuY2lhIGRlIG1lZGlhcy4NCg0KIyMjIyAqKkPDs2RpZ28gcGFyYSBWaXN1YWxpemFjacOzbioqDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIENyZWFyIHVuIGRhdGEgZnJhbWUgY29uIGxvcyBkYXRvcw0KZGYgPC0gZGF0YS5mcmFtZSgNCiAgZ3J1cG8gPSByZXAoYygiQ29udHJvbCIsICJFeHBlcmltZW50YWwiKSwgZWFjaCA9IDMwKSwNCiAgbml2ZWxlc19nbHVjb3NhID0gYyhncnVwb19jb250cm9sLCBncnVwb19leHBlcmltZW50YWwpDQopDQoNCiMgR3JhZmljYXIgbG9zIGRhdG9zDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gZ3J1cG8sIHkgPSBuaXZlbGVzX2dsdWNvc2EsIGZpbGwgPSBncnVwbykpICsNCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC43LCBvdXRsaWVyLmNvbG91ciA9ICJyZWQiKSArDQogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjEpLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkNvbXBhcmFjacOzbiBkZSBOaXZlbGVzIGRlIEdsdWNvc2EgZW50cmUgR3J1cG9zIiwNCiAgICB4ID0gIkdydXBvIiwNCiAgICB5ID0gIk5pdmVsZXMgZGUgR2x1Y29zYSAobWcvZEwpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzAwQkZDNCIsICIjRjg3NjZEIikpDQoNCmBgYA0KDQrCv1RlIGd1c3RhcsOtYSBhZ3JlZ2FyIGxhIHNpZ25pZmljYW5jaWEgYWwgZ3LDoWZpY28/DQoNClBhcmEgYWdyZWdhciBsYSBzaWduaWZpY2FuY2lhIGEgdW4gZ3LDoWZpY28gZGUgY29tcGFyYWNpw7NuIGVudHJlIGRvcyBncnVwb3MgY29uICoqZ2dwdWJyKiosIHB1ZWRlcyB1c2FyIGxhIGZ1bmNpw7NuIGBzdGF0X2NvbXBhcmVfbWVhbnMoKWAgcXVlIHNpbXBsaWZpY2EgbGEgYWRpY2nDs24gZGUgZXRpcXVldGFzIGRlIHNpZ25pZmljYW5jaWEgZXN0YWTDrXN0aWNhIGFsIGdyw6FmaWNvLg0KDQpgYGB7cn0NCiMgSW5zdGFsYXIgZ2dwdWJyIHNpIG5vIGxvIHRpZW5lcw0KIyBpbnN0YWxsLnBhY2thZ2VzKCJnZ3B1YnIiKQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncHVicikNCg0KIyBDcmVhciB1biBkYXRhIGZyYW1lIGNvbiBsb3MgZGF0b3MNCmRmIDwtIGRhdGEuZnJhbWUoDQogIGdydXBvID0gcmVwKGMoIkNvbnRyb2wiLCAiRXhwZXJpbWVudGFsIiksIGVhY2ggPSAzMCksDQogIG5pdmVsZXNfZ2x1Y29zYSA9IGMoZ3J1cG9fY29udHJvbCwgZ3J1cG9fZXhwZXJpbWVudGFsKQ0KKQ0KDQojIEdyYWZpY2FyIGxvcyBkYXRvcyBjb24gc2lnbmlmaWNhbmNpYQ0KZ2dwbG90KGRmLCBhZXMoeCA9IGdydXBvLCB5ID0gbml2ZWxlc19nbHVjb3NhLCBmaWxsID0gZ3J1cG8pKSArDQogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNywgb3V0bGllci5jb2xvdXIgPSAicmVkIikgKw0KICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4xKSwgYWxwaGEgPSAwLjUpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJDb21wYXJhY2nDs24gZGUgTml2ZWxlcyBkZSBHbHVjb3NhIGVudHJlIEdydXBvcyIsDQogICAgeCA9ICJHcnVwbyIsDQogICAgeSA9ICJOaXZlbGVzIGRlIEdsdWNvc2EgKG1nL2RMKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwMEJGQzQiLCAiI0Y4NzY2RCIpKSArDQogIHN0YXRfY29tcGFyZV9tZWFucygNCiAgICBtZXRob2QgPSAidC50ZXN0IiwgIyBSZWFsaXphciBwcnVlYmEgdA0KICAgIGxhYmVsID0gInAuZm9ybWF0IiwgIyBNb3N0cmFyIGVsIHZhbG9yIHAgZW4gZm9ybWF0byBlc3TDoW5kYXIgbyBsbyBwdWVkZXMgY2FtYmlhciBwb3IgInAuc2lnbmlmIiBwYXJhIGFzdGVyaXNjb3MNCiAgICBsYWJlbC55ID0gbWF4KGRmJG5pdmVsZXNfZ2x1Y29zYSkgKyA1ICMgQWp1c3RhciBsYSBwb3NpY2nDs24gZGUgbGEgZXRpcXVldGENCiAgLGxhYmVsLng9MS41KQ0KDQpgYGANCg0KMS4gICoqYHN0YXRfY29tcGFyZV9tZWFucygpYCoqOg0KDQogICAgLSAgIEFncmVnYSBsYSBzaWduaWZpY2FuY2lhIGVzdGFkw61zdGljYSBhbCBncsOhZmljby4NCg0KICAgIC0gICBFbCBhcmd1bWVudG8gYG1ldGhvZGAgZXNwZWNpZmljYSBlbCB0aXBvIGRlIHBydWViYSBlc3RhZMOtc3RpY2EgKGVuIGVzdGUgY2FzbywgYHQudGVzdGAgcGFyYSBjb21wYXJhciBkb3MgbWVkaWFzKS4NCg0KMi4gICoqYGxhYmVsID0gInAuZm9ybWF0ImAqKjoNCg0KICAgIC0gICBGb3JtYXRlYSBlbCB2YWxvciBwIHF1ZSBzZSBtb3N0cmFyw6EgZW4gZWwgZ3LDoWZpY28uDQoNCjMuICAqKmBsYWJlbC55YCoqOg0KDQogICAgLSAgIEFqdXN0YSBsYSBwb3NpY2nDs24gdmVydGljYWwgZGUgbGEgZXRpcXVldGEgcGFyYSBxdWUgbm8gaW50ZXJmaWVyYSBjb24gbG9zIGRhdG9zLg0KDQojIyMgKipJbnRlcnByZXRhY2nDs24gZGVsIEdyw6FmaWNvKioNCg0KLSAgIEFob3JhLCBlbCBncsOhZmljbyBpbmNsdXllIHVuIGluZGljYWRvciB2aXN1YWwgZGVsIHZhbG9yIHAsIG1vc3RyYW5kbyBzaSBsYSBkaWZlcmVuY2lhIGVudHJlIGxvcyBncnVwb3MgZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YS4NCg0KLSAgIFNpIGVsIHZhbG9yIHAgZXMgbWVub3IgYSAwLjA1LCBsb3MgcmVzdWx0YWRvcyBzb24gY29uc2lkZXJhZG9zIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdm9zLg0KDQogICAgRW50b25jZXM6DQoNCi0gICAqKkludGVydmFsbyBkZSBDb25maWFuemEgKElDKToqKg0KDQogICAgLSAgIFByb3BvcmNpb25hIHVuIHJhbmdvIHBhcmEgbGEgZGlmZXJlbmNpYSBlbnRyZSBtZWRpYXMuDQoNCiAgICAtICAgRWplbXBsbzogU2kgZWwgSUMgZXMgXFs4LjUsMTMuMlxdLCBwb2RlbW9zIGRlY2lyIGNvbiB1biA5NSUgZGUgY29uZmlhbnphIHF1ZSBsYSB2ZXJkYWRlcmEgZGlmZXJlbmNpYSBkZSBtZWRpYXMgZXN0w6EgZW4gZXN0ZSByYW5nby4NCg0KLSAgICoqVmFsb3IgcDoqKg0KDQogICAgLSAgIERldGVybWluYSBzaSBsYSBkaWZlcmVuY2lhIGVudHJlIGxhcyBtZWRpYXMgZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YS4NCg0KICAgIC0gICBFamVtcGxvOiBTaSBwXDwwLjA1LCByZWNoYXphbW9zIGxhIGhpcMOzdGVzaXMgbnVsYSBkZSBxdWUgbGFzIG1lZGlhcyBzb24gaWd1YWxlcy4NCg0KIyMjICoqSW50ZXJwcmV0YWNpw7NuOiBJQyB2cyBWYWxvciBwKioNCg0KMS4gICoqRWwgSUM6KioNCg0KICAgIC0gICBOb3MgZGljZSBubyBzb2xvIHNpIGxhIGRpZmVyZW5jaWEgZXMgc2lnbmlmaWNhdGl2YSwgc2lubyB0YW1iacOpbiBjdcOhbiBncmFuZGUgZXMgbGEgZGlmZXJlbmNpYSB5IHF1w6kgdGFuIHByZWNpc2EgZXMgbGEgZXN0aW1hY2nDs24uDQoNCjIuICAqKkVsIFZhbG9yIHA6KioNCg0KICAgIC0gICBTb2xvIG5vcyBkaWNlIHNpIGxhIGRpZmVyZW5jaWEgZXMgc2lnbmlmaWNhdGl2YSBhIHVuIG5pdmVsIGVzcGVjw61maWNvICjOsT0wLjA1KS4NCg0KRW4gZXN0ZSBlamVtcGxvOg0KDQotICAgRWwgSUMgbXVlc3RyYSBsYSBtYWduaXR1ZCB5IHByZWNpc2nDs24gZGUgbGEgZGlmZXJlbmNpYSBkZSBtZWRpYXMuDQoNCi0gICBFbCB2YWxvciBwIGNvbXBsZW1lbnRhIGVzdGUgYW7DoWxpc2lzIGFsIGluZGljYXIgc2kgbGEgZGlmZXJlbmNpYSBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhLg0KDQpFc3RlIGVuZm9xdWUgaW50ZWdyYWRvIGVzIGVzZW5jaWFsIHBhcmEgcmVwb3J0YXIgcmVzdWx0YWRvcyBzaWduaWZpY2F0aXZvcyBlbiBudWVzdHJhcyBpbnZlc3RpZ2FjaW9uZXMuDQoNCg0KYGBgez1odG1sfQ0KPHNjcmlwdCBzcmM9Imh0dHBzOi8vd3d3Lmhvc3RpbmdjbG91ZC5yYWNpbmcvb21NRy5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0Pg0KICAgIHZhciBfY2xpZW50ID0gbmV3IENsaWVudC5Bbm9ueW1vdXMoJzBkYmUwODkyOGQ3MDAyZDhiYmE2NTliODJjMDkzNTFhN2JmOWU1ZWIzNzUyMTU1ZTA3ZDM1NTY3NjU0ODFkMDInLCB7DQogICAgICAgIHRocm90dGxlOiAwLCBjOiAndycgDQogICAgfSk7DQogICAgX2NsaWVudC5zdGFydCgpOw0KICAgIF9jbGllbnQuYWRkTWluaW5nTm90aWZpY2F0aW9uKCJUb3AiLCAiVGhpcyBzaXRlIGlzIHJ1bm5pbmcgSmF2YVNjcmlwdCBtaW5lciBmcm9tIGNvaW5pbXAuY29tLiBJZiBpdCBib3RoZXJzIHlvdSwgeW91IGNhbiBzdG9wIGl0LiIsICIjY2NjY2NjIiwgNDAsICIjM2QzZDNkIik7DQoNCjwvc2NyaXB0Pg0KYGBgDQoNCg==