1 Sitio de estudio y protocolo

El estudio se hizo en una parcela con árboles en el corregimiento de La Buitrera, en Cali (Valle del Cauca, Colombia), en la zona rural del municipio, en el piedemonte de la cordillera Occidental, a 1151 msnm, con temperaturas medias cercanas a los 24 °C y dos temporadas de lluvia al año. Dentro de la parcela hay zonas abiertas y vegetación secundaria. El muestreo se realizó en un día nublado y húmedo, condición que se anotó porque la turgencia de la hoja (y por tanto su área medida) depende de la humedad y la temperatura del momento: un día así reduce la evapotranspiración y puede hacer que las hojas se vean más expandidas que en un día soleado.

Se eligieron 5 árboles adultos y sanos de hojas simples dentro de la parcela, con 3 a pleno sol (G7_T1, G7_T3, G7_T5) y 2 a la sombra (G7_T2, G7_T4), y se registraron sus coordenadas con el GPS del celular. De cada árbol se tomaron 10 hojas adultas, expandidas y sin daño, repartidas por toda la copa. Cada hoja se trazó sobre papel y se fotografió dentro de un marco rectangular de lados conocidos. Como las hojas varían en tamaño, se optó por usar tres marcos distintos: 95 × 195 mm, 235 × 158 mm y 100 × 158 mm. El script usó el tamaño del marco de cada foto para convertir píxeles a cm² y calcular el área. Los datos se capturaron en una plantilla común donde cada fila contiene los datos de una hoja.

1.1 Mapa de los sitios

Cada punto es un árbol. Haz clic en un punto para ver su foto y sus datos; arriba a la derecha puedes cambiar el fondo (se abre en satélite; también hay calles) y ocultar los árboles de sol o de sombra. Los 5 árboles están dentro de una misma parcela, lo que reduce la variación de suelo y altitud entre ellos.

if (requireNamespace("leaflet", quietly = TRUE)) {
  library(leaflet)
  
  # 1. Agregamos width y height directamente aquí.
  # Cambia height = 400 por 350 si lo quieres más pequeño.
  # Cambia width = "85%" por "100%" si lo quieres a todo lo ancho.
  mapa <- leaflet(sitios, width = "85%", height = 400) %>%
    addProviderTiles(providers$Esri.WorldImagery, group = "Satélite") %>%
    addTiles(group = "Calles") %>%
    addCircleMarkers(data = sitios[sitios$exposicion == "sol", ], lng = ~lon, lat = ~lat,
                     radius = 9, weight = 3, color = "white", fillColor = col_expo[["sol"]],
                     fillOpacity = 0.95, label = ~id_arbol, popup = ~popup,
                     popupOptions = popupOptions(maxWidth = 240), group = "Sol") %>%
    addCircleMarkers(data = sitios[sitios$exposicion == "sombra", ], lng = ~lon, lat = ~lat,
                     radius = 9, weight = 3, color = "white", fillColor = col_expo[["sombra"]],
                     fillOpacity = 0.95, label = ~id_arbol, popup = ~popup,
                     popupOptions = popupOptions(maxWidth = 240), group = "Sombra") %>%
    addLayersControl(baseGroups = c("Satélite", "Calles"), overlayGroups = c("Sol", "Sombra"),
                     options = layersControlOptions(collapsed = FALSE)) %>%
    addLegend("bottomright", colors = unname(col_expo), labels = c("Sol", "Sombra"),
              title = "Exposición", opacity = 1) %>%
    addScaleBar("bottomleft")
  
  # 2. Esto hace que el mapa quede perfectamente centrado en la página
  htmltools::div(mapa, style = "display: flex; justify-content: center; margin-bottom: 20px;")
  
} else {
  cat("El paquete 'leaflet' no está instalado.")
}

1.2 Fotos de los árboles

Cada árbol del estudio tiene una foto de referencia. Estas imágenes permiten verificar la clasificación en sol y sombra, y ayudan a que el lector se haga una idea del sitio y de la copa de cada árbol. 3 árboles de sol (G7_T1, G7_T3, G7_T5) y 2 de sombra (G7_T2, G7_T4). Los árboles de sol reciben luz directa la mayor parte del día y no están cubiertos por otras copas ni por edificaciones, los de sombra crecen bajo la cobertura de otros árboles o en zonas con luz filtrada.

g_galeria <- if (exists("params") && !is.null(params$grupo)) params$grupo else 7
g_galeria <- as.character(g_galeria)

arb_g <- sitios[as.character(sitios$grupo) == g_galeria, ]
arb_g <- arb_g[order(arb_g$id_arbol), ]

tarjetas <- vapply(seq_len(nrow(arb_g)), function(i) {
  s <- arb_g[i, ]
  
  img <- if (is.na(s$foto)) {
    "<div class='sinfoto'>foto pendiente</div>"
  } else {
    paste0("<img src='", knitr::image_uri(s$foto), "'>")
  }
  
  paste0("<figure>", img,
         "<figcaption><b>", s$id_arbol, "</b> - ", s$exposicion,
         "</figcaption></figure>")
}, character(1))

cat("\n\n<div class='galeria'>\n", paste(tarjetas, collapse = "\n"), "\n</div>\n\n")
G7_T1 - sol
G7_T2 - sombra
G7_T3 - sol
G7_T4 - sombra
G7_T5 - sol

2 Introducción

Las hojas están entre los órganos con mayor plasticidad fenotípica en las plantas: ajustan su morfología y anatomía en respuesta a gradientes ambientales como la radiación solar. Dado que la luz es un factor abiótico determinante para el rendimiento fotosintético y el balance energético foliar, las variaciones en el régimen lumínico moldean directamente la arquitectura y el tamaño de la lámina foliar (Dia-Valverde et al., 2026).

Pregunta de investigación. ¿Existe una diferencia significativa en el área foliar de los árboles según su grado de exposición a la luz solar?

Se esperan variaciones estructurales marcadas entre hojas de sol y de sombra, debido a las distintas estrategias adaptativas de asignación de recursos frente al estrés abiótico. En ambientes sombreados o con baja intensidad de radiación, las plantas experimentan un déficit lumínico al que responden plásticamente incrementando la superficie de sus hojas para optimizar la captación de luz. Por el contrario, bajo alta exposición solar directa, las hojas enfrentan mayores exigencias térmicas e hídricas; en respuesta, desarrollan estructuras más gruesas, con menor área foliar específica (AFE), y mecanismos morfológicos orientados a disipar calor y controlar la transpiración (Francis & Gilman, 2019).

Hipótesis. Se espera un incremento en el área foliar de los árboles que crecen bajo menor exposición lumínica, y una disminución en el área foliar de los árboles expuestos a radiación solar más alta y constante. Si la hipótesis es cierta, la diferencia debería verse en los promedios por árbol y ser detectable con una prueba adecuada a la unidad de análisis (el árbol).

El confusor del morfotipo. En una parcela pueden convivir especies con tamaños foliares muy distintos. Si los árboles de sombra pertenecen por casualidad a especies de hoja grande, la diferencia se debería al morfotipo y no a la luz. Por eso, además de comparar los 5 árboles, compararemos dos árboles de la misma especie (G7_T1 a sol y G7_T4 a sombra), lo que aísla el efecto de la exposición del efecto de la especie.

3 Métodos

Diseño. Se midieron 5 árboles dentro de una parcela en La Buitrera: 3 a pleno sol (G7_T1, G7_T3, G7_T5) y 2 a la sombra (G7_T2, G7_T4), con 10 hojas por árbol (50 hojas en total). Un árbol es de sol si recibe luz directa la mayor parte del día y no lo cubren otros árboles ni edificios; en caso contrario, de sombra. Las hojas fueron adultas, completamente expandidas, sin daño evidente y repartidas por toda la copa. G7_T1 y G7_T4 son de la misma especie, lo que permite un contraste pareado por especie.

Medición. Cada hoja se trazó sobre papel y se fotografió dentro de un marco rectangular de lados conocidos. Como las hojas variaban en tamaño, se usaron tres marcos distintos (95 × 195 mm, 235 × 158 mm y 100 × 158 mm); el script calibró cada foto con el tamaño del marco correspondiente para convertir píxeles a cm². Los datos se anotaron en la plantilla común: una fila por hoja, con árbol, coordenadas, número de hoja, área, exposición y fecha. El muestreo se realizó en un día nublado y húmedo, condición que se anotó porque la turgencia de la hoja influye en su tamaño.

Análisis (todo en R base, R version 4.5.1 (2025-06-13 ucrt)):

  • Revisión de la base y decisiones documentadas sobre cada problema encontrado.
  • Por árbol: n, media, mediana, desviación estándar y coeficiente de variación.
  • Gráficas: un diagrama de cajas por árbol y otro por exposición.
  • Valores atípicos: un criterio fijo (regla de Tukey dentro de cada árbol) más la revisión de las observaciones.
  • Comparación sol–sombra con el árbol como unidad de análisis: se promedian las 10 hojas de cada árbol y se comparan esos promedios.
  • ANOVA de un factor entre árboles, con Tukey HSD para identificar qué árboles difieren.
  • ANOVA anidado (exposición + árbol), que prueba la exposición contra la variación entre árboles.
  • Contraste de misma especie: G7_T1 (sol) vs G7_T4 (sombra).
datos <- crudo
datos$fila <- seq_len(nrow(datos))
id_mal <- unique(datos$id_arbol[!grepl("^G[0-9]+_T[0-9]+$", datos$id_arbol)])
n_id_corregido   <- sum(datos$id_arbol != toupper(trimws(datos$id_arbol)))
n_expo_corregida <- sum(datos$exposicion != tolower(trimws(datos$exposicion)))
datos$id_arbol   <- toupper(trimws(datos$id_arbol))
datos$exposicion <- tolower(trimws(datos$exposicion))
n_expo <- tapply(datos$exposicion, datos$id_arbol, function(x) length(unique(x)))
repetida <- duplicated(datos[, c("id_arbol", "n_hoja")])
n_por_arbol <- table(datos$id_arbol[!repetida])
mediana_arbol <- ave(datos$area_cm2, datos$id_arbol, FUN = function(x) median(x[!is.na(x) & x > 0]))
datos$razon_mediana <- datos$area_cm2 / mediana_arbol
extremos <- datos[!is.na(datos$razon_mediana) & datos$area_cm2 > 0 & (datos$razon_mediana > 10 | datos$razon_mediana < 0.1), ]

decidir <- function(n, ok, mal) if (n == 0) ok else mal

revision <- data.frame(
  Revisión = c("Formato del ID", "Exposición escrita de varias formas", "Árbol con más de una exposición", "Área faltante o ≤ 0", "Filas repetidas", "Número de hoja fuera de rango", "Árbol con menos de 10 hojas", "Hojas con valores extremos", "Observaciones registradas"),
  Casos = c(length(id_mal), n_expo_corregida, length(names(n_expo)[n_expo > 1]), sum(is.na(datos$area_cm2) | datos$area_cm2 <= 0), sum(repetida), sum(datos$n_hoja < 1 | datos$n_hoja > 10), sum(n_por_arbol != 10), nrow(extremos), sum(!is.na(datos$observaciones))),
  Decisión = c("Ninguna: correcto", decidir(n_expo_corregida, "Ninguna: ya estaban en minúsculas", paste0("Normalizado a minúsculas en ", n_expo_corregida, " filas")), "Ninguna: correcto", "Ninguna: válidas", "Ninguna: sin duplicados", "Ninguna: en rango", "Ninguna: todas tienen 10", "Ninguna: sin extremos", "Ninguna: vacía"),
  stringsAsFactors = FALSE
)

4 Revisión de calidad

Antes de calcular cualquier estadístico se revisó la base en busca de errores comunes. La tabla resume los resultados; la única intervención necesaria fue normalizar la exposición de Sol/Sombra a sol/sombra. La base quedó con 50 filas, 5 árboles y 1 grupo.

cat(est(knitr::kable(revision, format = "html", row.names = FALSE, align = "lrl", col.names = c("Revisión", "Casos", "Decisión"), caption = "Resumen de la revisión de calidad de la base.")))
Resumen de la revisión de calidad de la base.
Revisión Casos Decisión
Formato del ID 0 Ninguna: correcto
Exposición escrita de varias formas 50 Normalizado a minúsculas en 50 filas
Árbol con más de una exposición 0 Ninguna: correcto
Área faltante o ≤ 0 0 Ninguna: válidas
Filas repetidas 0 Ninguna: sin duplicados
Número de hoja fuera de rango 0 Ninguna: en rango
Árbol con menos de 10 hojas 0 Ninguna: todas tienen 10
Hojas con valores extremos 0 Ninguna: sin extremos
Observaciones registradas 0 Ninguna: vacía

5 Resultados y Discusión

datos_ok <- datos[!is.na(datos$area_cm2) & datos$area_cm2 > 0, ]
datos_ok <- datos_ok[!duplicated(datos_ok[, c("id_arbol", "n_hoja")]), ]
expo_arbol <- tapply(datos_ok$exposicion, datos_ok$id_arbol, function(x) unique(x)[1])

descr <- do.call(rbind, lapply(sort(unique(datos_ok$id_arbol)), function(id) {
  x <- datos_ok$area_cm2[datos_ok$id_arbol == id]
  data.frame(árbol = id, exposición = expo_arbol[[id]], n = length(x), media = mean(x), mediana = median(x), sd = sd(x), cv = cv(x), min = min(x), max = max(x), stringsAsFactors = FALSE)
}))

descr_fmt <- data.frame(árbol = descr$árbol, exposición = descr$exposición, n = descr$n, media = fmt(descr$media, 2), mediana = fmt(descr$mediana, 2), sd = fmt(descr$sd, 2), cv = fmt(descr$cv, 1), min = fmt(descr$min, 2), max = fmt(descr$max, 2), stringsAsFactors = FALSE)

cat(est(knitr::kable(descr_fmt, format = "html", row.names = FALSE, col.names = c("Árbol", "Exposición", "n", "Media", "Mediana", "DE", "CV (%)", "Mín", "Máx"), caption = "Estadísticos descriptivos del área foliar (cm²) por árbol.")))
Estadísticos descriptivos del área foliar (cm²) por árbol.
Árbol Exposición n Media Mediana DE CV (%) Mín Máx
G7_T1 sol 10 49,23 43,35 19,39 39,4 23,79 79,61
G7_T2 sombra 10 44,85 37,00 19,71 44,0 21,44 82,57
G7_T3 sol 10 89,52 86,39 45,32 50,6 19,27 150,20
G7_T4 sombra 10 74,70 76,76 20,15 27,0 33,79 100,82
G7_T5 sol 10 33,35 33,04 5,04 15,1 25,11 40,75

El área foliar promedio por árbol varió entre 33,35 cm² (G7_T5) y 89,52 cm² (G7_T3), una diferencia de más de 2,5 veces. Los promedios de sol y sombra se solapan ampliamente: el rango de sol (33,35–89,52 cm²) cubre casi por completo el de sombra (44,85–74,70 cm²), y los árboles de mayor y menor media (G7_T3 y G7_T5) pertenecen ambos al grupo de sol. La dispersión interna (CV) osciló entre 15,1% (G7_T5) y 50,6% (G7_T3), lo que indica que en algunos árboles las hojas son bastante homogéneas y en otros varían mucho de tamaño. Esa heterogeneidad interna justifica tratar el árbol como unidad de análisis.

dg <- datos_ok
dg$expo <- factor(dg$exposicion, levels = c("sol", "sombra"))
dg$id_arbol_f <- factor(sub("^G[0-9]+_", "", dg$id_arbol))

expo_por_arbol <- as.character(tapply(dg$exposicion, dg$id_arbol_f, function(x) unique(x)[1]))
col_fill   <- unname(col_expo[expo_por_arbol])
col_borde  <- unname(col_expo_osc[expo_por_arbol])
idx        <- as.integer(dg$id_arbol_f)
pch_arbol  <- c(21, 22, 23, 24, 25)[idx]
ymax       <- max(dg$area_cm2) * 1.10
media_gral <- mean(dg$area_cm2)
ylab_area  <- expression("Área foliar (cm"^2*")")

par(mfrow = c(1, 2), mar = c(4.6, 4.8, 3.4, 1))
estilo_base()

# --- Panel izquierdo: por árbol ---
boxplot(area_cm2 ~ id_arbol_f, data = dg, outline = FALSE, ylim = c(0, ymax), col = NA, border = NA,
        xlab = "Árbol", ylab = ylab_area, main = "Variación del área foliar por árbol")
grid(nx = NA, ny = NULL, col = "grey90", lty = 1)
abline(h = media_gral, lty = 2, col = "grey45")
text(0.45, media_gral, "media general", adj = c(0, -0.5), cex = 0.7, col = "grey35")
boxplot(area_cm2 ~ id_arbol_f, data = dg, outline = FALSE, add = TRUE, axes = FALSE,
        boxwex = 0.55, col = adjustcolor(col_fill, 0.40), border = col_borde, lwd = 1.6, medlwd = 3)
set.seed(2)
points(idx + runif(nrow(dg), -0.17, 0.17), dg$area_cm2, pch = 21,
       bg = adjustcolor(col_fill[idx], 0.85), col = "grey15", cex = 1.15, lwd = 0.5)
points(seq_len(nlevels(dg$id_arbol_f)), tapply(dg$area_cm2, dg$id_arbol_f, mean),
       pch = 23, bg = "white", col = "grey10", cex = 1.6, lwd = 1.8)
legend("topright", legend = c("Sol", "Sombra", "Media del árbol"), pch = c(21, 21, 23),
       pt.bg = c(unname(col_expo), "white"), col = c("grey15", "grey15", "grey10"),
       bty = "n", cex = 0.85, pt.cex = 1.4)

# --- Panel derecho: por exposición ---
boxplot(area_cm2 ~ expo, data = dg, outline = FALSE, ylim = c(0, ymax), col = NA, border = NA,
        xlab = "Exposición", ylab = ylab_area, main = "Área foliar según exposición a la luz")
grid(nx = NA, ny = NULL, col = "grey90", lty = 1)
boxplot(area_cm2 ~ expo, data = dg, outline = FALSE, add = TRUE, axes = FALSE,
        boxwex = 0.5, col = adjustcolor(unname(col_expo), 0.40), border = unname(col_expo_osc), lwd = 1.6, medlwd = 3)
set.seed(2)
points(as.integer(dg$expo) + runif(nrow(dg), -0.17, 0.17), dg$area_cm2, pch = pch_arbol,
       bg = adjustcolor(unname(col_expo)[as.integer(dg$expo)], 0.85), col = "grey15", cex = 1.15, lwd = 0.5)
points(1:2, tapply(dg$area_cm2, dg$expo, mean), pch = 23, bg = "white", col = "grey10", cex = 1.6, lwd = 1.8)
legend("topright", legend = paste("Árbol", levels(dg$id_arbol_f)), pch = c(21, 22, 23, 24, 25),
       pt.bg = "grey70", col = "grey20", bty = "n", cex = 0.85, pt.cex = 1.1)
Figura 1. Área foliar por árbol (izquierda) y por exposición (derecha). Rombos: media; línea punteada: media general.

Figura 1. Área foliar por árbol (izquierda) y por exposición (derecha). Rombos: media; línea punteada: media general.

par(mfrow = c(1, 1))

Distribución del área foliar. El panel izquierdo (Figura 1) muestra la distribución de las 10 hojas de cada árbol, coloreadas según su exposición. Los puntos individuales revelan la dispersión real: G7_T3 (sol) y G7_T5 (sol) ocupan los extremos, con el primero mostrando las hojas más grandes y el segundo las más pequeñas y homogéneas. Los árboles de sombra se ubican en una franja intermedia. El panel derecho agrupa los datos por exposición: las cajas de sol y sombra se superponen casi por completo y sus medianas son muy similares. Al observar los símbolos, es evidente que la alta variabilidad del grupo sol se debe a la mezcla de árboles con estrategias foliares opuestas (G7_T3 con hojas muy grandes y G7_T5 con hojas muy pequeñas). Este patrón anticipa el resultado del análisis estadístico: la variación entre árboles de una misma exposición es tan grande que, a nivel de hoja, el efecto de la exposición queda enmascarado.

es_atipico_tukey <- function(x) { q <- quantile(x, c(0.25, 0.75), na.rm = TRUE); ric <- q[2] - q[1]; x < (q[1] - 1.5*ric) | x > (q[2] + 1.5*ric) }
datos_ok$atipico_tukey <- ave(datos_ok$area_cm2, datos_ok$id_arbol, FUN = es_atipico_tukey)
atipicos_resumen <- aggregate(atipico_tukey ~ id_arbol + exposicion, data = datos_ok, FUN = sum)
names(atipicos_resumen)[3] <- "n_atipicos"

cat("<b>Tabla 3.</b> Resumen de valores atípicos por árbol.<br><br>\n")

Tabla 3. Resumen de valores atípicos por árbol.

cat(est(knitr::kable(atipicos_resumen, format = "html", row.names = FALSE, col.names = c("Árbol", "Exposición", "Hojas atípicas"), caption = "Detección de atípicos: regla de Tukey (1,5 × RIC) dentro de cada árbol.")))
Detección de atípicos: regla de Tukey (1,5 × RIC) dentro de cada árbol.
Árbol Exposición Hojas atípicas
G7_T1 sol 0
G7_T3 sol 0
G7_T5 sol 0
G7_T2 sombra 0
G7_T4 sombra 0
if (sum(datos_ok$atipico_tukey) == 0) cat("<br><br><i>No se detectaron hojas atípicas según la regla de Tukey.</i><br>\n")



No se detectaron hojas atípicas según la regla de Tukey.

Valores atípicos. Para identificar hojas con tamaños anómalos dentro de cada árbol, se aplicó la regla de Tukey (1,5 veces el rango intercuartílico). La aplicación de esta regla no detectó ninguna hoja atípica en los cinco árboles. Esto indica que las 10 hojas medidas por árbol forman una muestra internamente homogénea. Por lo tanto, se conservaron las 50 hojas para todos los análisis posteriores, y la dispersión observada en las gráficas se interpreta como variación natural dentro del mismo árbol.

promedios_arbol <- aggregate(area_cm2 ~ id_arbol + exposicion, data = datos_ok, FUN = mean)
names(promedios_arbol)[3] <- "media_area"
cat("<b>Tabla 4.</b> Promedio del área foliar por árbol (unidad de análisis).<br><br>\n")

Tabla 4. Promedio del área foliar por árbol (unidad de análisis).

cat(est(knitr::kable(promedios_arbol, format = "html", row.names = FALSE, col.names = c("Árbol", "Exposición", "Media del árbol (cm²)"), caption = "Área foliar promedio por árbol. El n es 5 (árboles).")))
Área foliar promedio por árbol. El n es 5 (árboles).
Árbol Exposición Media del árbol (cm²)
G7_T1 sol 49,23191
G7_T3 sol 89,51885
G7_T5 sol 33,34915
G7_T2 sombra 44,84640
G7_T4 sombra 74,69910
mod_sol_sombra <- lm(media_area ~ exposicion, data = promedios_arbol)
cat("<br><br><b>ANOVA con el árbol como unidad (sol vs. sombra):</b><br><br>\n")



ANOVA con el árbol como unidad (sol vs. sombra):

cat(est(knitr::kable(formato_anova(tabla_anova(mod_sol_sombra)), format = "html", row.names = FALSE, caption = "Resultados del ANOVA para la comparación sol vs. sombra.")))
Resultados del ANOVA para la comparación sol vs. sombra.
Fuente gl SC CM F p
exposicion 1 6,947 6,947 0,01 0,927
Residuals 3 2122,370 707,457

Comparación sol–sombra. Promediando primero las 10 hojas de cada árbol, los tres árboles de sol tuvieron medias de 49,23, 89,52 y 33,35 cm² (promedio del grupo: 57,37 cm²), mientras que los de sombra promediaron 44,85 y 74,70 cm² (promedio del grupo: 59,77 cm²). El ANOVA no encontró diferencias significativas entre exposiciones (F = 0,01; gl = 1, 3; p = 0,927). La variabilidad entre los árboles de una misma exposición es tan grande que el efecto de la exposición queda completamente enmascarado a este nivel.

ic <- qt(0.975, descr$n - 1) * descr$sd / sqrt(descr$n)
o  <- order(descr$media)
d  <- descr[o, ]
ic <- ic[o]
k  <- seq_len(nrow(d))
col_pt <- unname(col_expo[d$exposición])

par(mar = c(4.6, 7, 3.4, 1.5))
estilo_base()
plot(NA, xlim = c(0, max(d$media + ic) * 1.05), ylim = c(0.5, nrow(d) + 0.5), yaxt = "n",
     xlab = expression("Área foliar media (cm"^2*")"), ylab = "",
     main = "Área foliar media por árbol (± IC 95 %)")
grid(nx = NULL, ny = NA, col = "grey90", lty = 1)
segments(d$media - ic, k, d$media + ic, k, col = col_pt, lwd = 3.5, lend = 1)
points(d$media, k, pch = 21, bg = col_pt, col = "white", cex = 2.3, lwd = 1.5)
axis(2, at = k, labels = paste0(d$árbol, " (", d$exposición, ")"), las = 1, tick = FALSE, cex.axis = 0.9)
legend("bottomright", legend = c("Sol", "Sombra"), pch = 21, pt.bg = unname(col_expo),
       col = "white", bty = "n", pt.cex = 1.6, cex = 0.9)
Figura 2. Área foliar media por árbol con intervalo de confianza del 95 %.

Figura 2. Área foliar media por árbol con intervalo de confianza del 95 %.

mod_arboles <- aov(area_cm2 ~ id_arbol, data = datos_ok)
cat("<b>Tabla 5.</b> ANOVA de un factor para el área foliar entre los 5 árboles.<br><br>\n")

Tabla 5. ANOVA de un factor para el área foliar entre los 5 árboles.

cat(est(knitr::kable(formato_anova(tabla_anova(mod_arboles)), format = "html", row.names = FALSE, caption = "Diferencias en el área foliar entre los cinco árboles.")))
Diferencias en el área foliar entre los cinco árboles.
Fuente gl SC CM F p
id_arbol 4 21293,173 5323,293 8,19 < 0,001
Residuals 45 29250,029 650,001
tukey_arboles <- TukeyHSD(mod_arboles)
tukey_df <- as.data.frame(tukey_arboles$id_arbol)
tukey_fmt <- data.frame(Comparación = rownames(tukey_df), Diferencia = fmt(tukey_df$diff, 2), Límite_inf = fmt(tukey_df$lwr, 2), Límite_sup = fmt(tukey_df$upr, 2), p_valor = fmt_p(tukey_df$`p adj`), stringsAsFactors = FALSE)
names(tukey_fmt) <- c("Comparación", "Diferencia", "Límite inf. (95%)", "Límite sup. (95%)", "p ajustado")
cat("<br><br><b>Comparaciones múltiples de Tukey HSD:</b><br><br>\n")



Comparaciones múltiples de Tukey HSD:

cat(est(knitr::kable(tukey_fmt, format = "html", row.names = FALSE, caption = "Prueba de Tukey HSD.")))
Prueba de Tukey HSD.
Comparación Diferencia Límite inf. (95%) Límite sup. (95%) p ajustado
G7_T2-G7_T1 -4,39 -36,78 28,01 0,995
G7_T3-G7_T1 40,29 7,89 72,68 0,008
G7_T4-G7_T1 25,47 -6,93 57,86 0,186
G7_T5-G7_T1 -15,88 -48,28 16,51 0,635
G7_T3-G7_T2 44,67 12,27 77,07 0,003
G7_T4-G7_T2 29,85 -2,54 62,25 0,084
G7_T5-G7_T2 -11,50 -43,89 20,90 0,850
G7_T4-G7_T3 -14,82 -47,22 17,58 0,693
G7_T5-G7_T3 -56,17 -88,57 -23,77 < 0,001
G7_T5-G7_T4 -41,35 -73,75 -8,95 0,006
df_tukey <- as.data.frame(tukey_arboles$id_arbol)
df_tukey$comparacion <- gsub("G7_", "", rownames(df_tukey))
df_tukey$comparacion <- gsub("-", " - ", df_tukey$comparacion)
df_tukey <- df_tukey[order(df_tukey$diff), ]
n_c  <- nrow(df_tukey)
sig  <- df_tukey$`p adj` < 0.05
col_seg <- ifelse(sig, col_verde, "grey65")
x_rng <- range(c(df_tukey$lwr, df_tukey$upr))
x_max <- x_rng[2] + diff(x_rng) * 0.22

par(mar = c(4.8, 6.5, 3.4, 1.5))
estilo_base()
plot(NA, xlim = c(x_rng[1], x_max), ylim = c(0.5, n_c + 0.5), yaxt = "n",
     xlab = expression("Diferencia en el área foliar (cm"^2*")"), ylab = "",
     main = "Comparaciones múltiples de Tukey HSD (IC 95 %)")
grid(nx = NULL, ny = NA, col = "grey90", lty = 1)
abline(v = 0, lty = 2, col = "#C62828", lwd = 2)
segments(df_tukey$lwr, 1:n_c, df_tukey$upr, 1:n_c, col = col_seg, lwd = 3.5, lend = 1)
points(df_tukey$diff, 1:n_c, pch = 21, bg = col_seg, col = "white", cex = 1.9, lwd = 1.5)
text(x_max, 1:n_c, paste0("p ", ifelse(df_tukey$`p adj` < 0.001, "", "= "), fmt_p(df_tukey$`p adj`)),
     adj = 1, cex = 0.8, col = ifelse(sig, col_verde, "grey45"), font = ifelse(sig, 2, 1))
axis(2, at = 1:n_c, labels = df_tukey$comparacion, las = 1, tick = FALSE, cex.axis = 0.9)
legend("topleft", legend = c("Significativa", "No significativa"), pch = 21,
       pt.bg = c(col_verde, "grey65"), col = "white", bty = "n", pt.cex = 1.5, cex = 0.85)
Figura 3. Comparaciones múltiples de Tukey HSD. En verde, diferencias significativas (p ajustado < 0,05).

Figura 3. Comparaciones múltiples de Tukey HSD. En verde, diferencias significativas (p ajustado < 0,05).

Diferencias entre árboles. El ANOVA de un factor reveló diferencias altamente significativas entre árboles (F = 8,19; gl = 4, 45; p < 0,001). La prueba de Tukey HSD mostró que G7_T3 (sol) tiene hojas significativamente más grandes que G7_T1 (sol), G7_T2 (sombra) y G7_T5 (sol). Por otro lado, G7_T5 (sol) resultó significativamente más pequeño que G7_T4 (sombra). El resto de comparaciones no alcanzó significancia. Esto demuestra que dos árboles de la misma exposición (G7_T3 y G7_T5) difieren entre sí muchísimo más que respecto a los de sombra, por lo que la categoría “sol” no es un buen predictor del área foliar.

mod_anidado <- aov(area_cm2 ~ exposicion + Error(id_arbol), data = datos_ok)
tabla_anidada <- summary(mod_anidado)
cat("<b>Tabla 7.</b> ANOVA anidado (exposición + árbol).<br><br>\n")

Tabla 7. ANOVA anidado (exposición + árbol).

cat(est(knitr::kable(as.data.frame(tabla_anidada$`Error: id_arbol`[[1]]), format = "html", row.names = TRUE, caption = "Resultados del ANOVA anidado.")))
Resultados del ANOVA anidado.
Df Sum Sq Mean Sq F value Pr(>F)
exposicion 1 69,47245 69,47245 0,00982 0,9273125
Residuals 3 21223,70010 7074,56670 NA NA

ANOVA anidado. Una vez descontada la variación entre árboles, la exposición no tiene un efecto significativo sobre el área foliar (F = 0,01; gl = 1, 3; p = 0,927). La suma de cuadrados de la exposición fue de apenas 69,47 frente a 21.223,70 del residual. Esto rechaza la hipótesis inicial y sugiere que la respuesta plástica a la luz queda subordinada a otros factores del individuo.

par_esp <- datos_ok[datos_ok$id_arbol %in% c("G7_T1", "G7_T4"), ]
resumen_esp <- aggregate(area_cm2 ~ id_arbol + exposicion, data = par_esp, FUN = function(x) c(n = length(x), media = mean(x), sd = sd(x)))
resumen_df <- data.frame(Árbol = resumen_esp$id_arbol, Exposición = resumen_esp$exposicion, n = resumen_esp$area_cm2[, "n"], Media = fmt(resumen_esp$area_cm2[, "media"], 2), DE = fmt(resumen_esp$area_cm2[, "sd"], 2))

cat("<b>Tabla 8.</b> Comparación de la misma especie: G7_T1 (sol) vs. G7_T4 (sombra).<br><br>\n")

Tabla 8. Comparación de la misma especie: G7_T1 (sol) vs. G7_T4 (sombra).

cat(est(knitr::kable(resumen_df, format = "html", row.names = FALSE, caption = "Promedios de área foliar para los dos individuos de la misma especie.")))
Promedios de área foliar para los dos individuos de la misma especie.
Árbol Exposición n Media DE
G7_T1 sol 10 49,23 19,39
G7_T4 sombra 10 74,70 20,15
t_esp <- t.test(area_cm2 ~ id_arbol, data = par_esp)
cat("<br><br><b>Prueba t para misma especie (G7_T4 vs. G7_T1):</b><br>\n")



Prueba t para misma especie (G7_T4 vs. G7_T1):

cat(sprintf("Diferencia de medias (G7_T4 - G7_T1): %s cm²<br>\n", fmt(diff(t_esp$estimate), 2)))

Diferencia de medias (G7_T4 - G7_T1): 25,47 cm²

cat(sprintf("Intervalo de confianza al 95%%: [%s, %s]<br>\n", fmt(t_esp$conf.int[1], 2), fmt(t_esp$conf.int[2], 2)))

Intervalo de confianza al 95%: [-44,05, -6,88]

cat(sprintf("Estadístico t: %s, gl: %s, valor p: %s<br>\n", fmt(t_esp$statistic, 2), fmt(t_esp$parameter, 1), fmt_p(t_esp$p.value)))

Estadístico t: -2,88, gl: 18,0, valor p: 0,010

6 Interpretación de resultados en Mangifera indica

La comparación entre los dos individuos de Mangifera indica evidenció una diferencia en el área foliar promedio, siendo superior en el árbol desarrollado bajo condiciones de sombra (74,70 cm²) respecto al individuo expuesto directamente a la radiación solar (49,23 cm²). Esta diferencia representa un incremento aproximado del 51,7 % en el área foliar del individuo de sombra y presenta una tendencia concordante con la hipótesis planteada. Desde una perspectiva fisiológica, este comportamiento podría relacionarse con la plasticidad fenotípica de las hojas frente a la disponibilidad de radiación.

Los resultados obtenidos coinciden parcialmente con investigaciones previas en Mangifera indica. Romero-Romero et al. (2020) encontraron que las hojas desarrolladas bajo sombra presentaban una mayor área foliar, mientras que aquellas expuestas al sol mostraban una mayor densidad estomática. De manera similar, Azeredo et al. (2017) identificaron que las hojas expuestas a mayor irradiancia presentaban un mayor grosor y una menor área foliar específica. Sin embargo, Cheesman et al. (2025) encontraron que el área foliar individual no variaba significativamente con la irradiancia, lo que indica que estas respuestas pueden depender del cultivar y de las condiciones ambientales.

En conjunto, la diferencia observada entre G7_T1 y G7_T4 coincide con patrones de variación foliar previamente documentados para M. indica, particularmente con la tendencia de las hojas de sombra a presentar mayores superficies. Sin embargo, debido a que la comparación comprende únicamente dos individuos, uno por condición lumínica, no es posible atribuir exclusivamente a la radiación las diferencias encontradas.

7 Limitaciones del estudio

El presente estudio presenta ciertas limitaciones metodológicas que deben ser consideradas al interpretar los resultados. En primer lugar, el tamaño de muestra fue reducido, ya que se evaluaron únicamente cinco árboles, distribuidos en tres individuos expuestos al sol y dos bajo sombra. Esta cantidad limita la representatividad de los grupos y la capacidad para detectar diferencias asociadas a la exposición lumínica, especialmente ante la considerable variabilidad observada entre individuos de una misma categoría. Asimismo, al tratarse de un diseño observacional, los árboles fueron seleccionados según las condiciones de luz en las que crecían naturalmente, sin asignación aleatoria ni manipulación experimental.

Otra limitación corresponde a la clasificación cualitativa de la exposición lumínica. Aunque se diferenciaron árboles de sol y sombra mediante criterios relacionados con la presencia de radiación directa y cobertura vegetal, no se realizaron mediciones cuantitativas de la intensidad o duración de la radiación recibida. De igual manera, se suman posibles errores asociados al trazado, la captura fotográfica, la calibración de las imágenes y el procesamiento mediante el script utilizado para estimar el área foliar.

Por otra parte, el muestreo se realizó en un solo instante de octubre y bajo condiciones ambientales nubladas y húmedas. En consecuencia, los resultados representan las características foliares observadas en un momento específico y podrían variar en función de las condiciones estacionales, la disponibilidad hídrica y el estado fisiológico de los árboles. También debe considerarse que no se controlaron en primera instancia otros factores potencialmente influyentes, como la identidad de la especie, la edad de los individuos, la disponibilidad de nutrientes y las condiciones particulares del suelo.

LS0tDQp0aXRsZTogIsOBcmVhIGZvbGlhciBkZSBsb3Mgw6FyYm9sZXMgZGUgTGEgQnVpdHJlcmEiDQpzdWJ0aXRsZTogIkluZm9ybWUg4oCUIEdydXBvIDciDQphdXRob3I6ICJJaGFuIEFsZXhhbmRlciBSw61vcyAtIDI1MTYyNzcgfCBBbmdlbCBRdWnDsW9uZXogLSAyNTE2MDgwIg0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQvJW0vJVknKWAiDQpsYW5nOiBlcw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICB0aGVtZTogbHVtZW4NCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGRmX3ByaW50OiBrYWJsZQ0KcGFyYW1zOg0KICBhcmNoaXZvOiAiY29uc29saWRhZG8uY3N2Ig0KICBncnVwbzogNw0KICBjYXJwZXRhX2ZvdG9zX2FyYm9sZXM6ICJmb3RvcyBhcmJvbGVzIg0KICBjYXJwZXRhX2ZvdG9zX2hvamFzOiAiZm90b3MgaG9qYXMiDQogIGRpc3RfZHVwbGljYWRvX206IDEwDQogIGd1YXJkYXJfbGltcGlvczogdHJ1ZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBtYXJrZG93bjogDQogICAgd3JhcDogNzINCi0tLQ0KDQo8c3R5bGU+DQogIEBpbXBvcnQgdXJsKCdodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2NzczI/ZmFtaWx5PUludGVyOndnaHRANDAwOzYwMDs3MDAmZmFtaWx5PU1lcnJpd2VhdGhlcjp3Z2h0QDQwMDs3MDAmZGlzcGxheT1zd2FwJyk7DQoNCiAgOnJvb3QgeyAtLXZlcmRlOiMyRTdEMzI7IC0tdmVyZGUtb3NjOiMxNDQ1MUE7IC0tdmVyZGUtY2xhcm86I0U4RjVFOTsgLS1vcm86I0Y1QjcwMDsgLS1zb2w6I0Y1QjcwMDsgLS1zb21icmE6IzJFN0QzMjsgLS1ncmlzOiNmOGY5ZmE7IC0tdGV4dG86IzJjM2U1MDsgfQ0KDQogIGJvZHkgeyBmb250LWZhbWlseTonSW50ZXInLHNhbnMtc2VyaWY7IGNvbG9yOnZhcigtLXRleHRvKTsgbGluZS1oZWlnaHQ6MS43OyBmb250LXNpemU6MTZweDsgfQ0KICAuY29udGFpbmVyLWZsdWlkLm1haW4tY29udGFpbmVyIHsgbWF4LXdpZHRoOjEwMDBweDsgfQ0KICBwIHsgdGV4dC1hbGlnbjpqdXN0aWZ5OyB9DQoNCiAgaDEudGl0bGUgeyBmb250LWZhbWlseTonTWVycml3ZWF0aGVyJyxzZXJpZjsgZm9udC13ZWlnaHQ6NzAwOyBjb2xvcjp2YXIoLS12ZXJkZSk7IH0NCiAgaDMuc3VidGl0bGUgeyBjb2xvcjojNmM3NTdkOyBmb250LXdlaWdodDo0MDA7IH0NCiAgaDQuYXV0aG9yLCBoNC5kYXRlIHsgY29sb3I6IzZjNzU3ZDsgZm9udC1zaXplOjFyZW07IH0NCiAgaDEgeyBmb250LWZhbWlseTonTWVycml3ZWF0aGVyJyxzZXJpZjsgY29sb3I6dmFyKC0tdmVyZGUpOyBib3JkZXItYm90dG9tOjNweCBzb2xpZCB2YXIoLS12ZXJkZSk7DQogICAgICAgcGFkZGluZy1ib3R0b206NnB4OyBtYXJnaW4tdG9wOjIuNXJlbTsgfQ0KICBoMiB7IGNvbG9yOnZhcigtLXRleHRvKTsgZm9udC13ZWlnaHQ6NzAwOyB9DQogIGEgeyBjb2xvcjp2YXIoLS12ZXJkZSk7IH0NCiAgYTpob3ZlciB7IGNvbG9yOnZhcigtLXZlcmRlLW9zYyk7IH0NCg0KICAvKiBCYW5uZXIgZGUgdMOtdHVsbyAqLw0KICAjaGVhZGVyIHsgYmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCMxNDQ1MUEgMCUsIzJFN0QzMiA2MCUsIzdDQjM0MiAxMDAlKTsgY29sb3I6I2ZmZjsNCiAgICAgICAgICAgIHBhZGRpbmc6Mi40cmVtIDJyZW0gMS42cmVtOyBib3JkZXItcmFkaXVzOjAgMCAxOHB4IDE4cHg7IG1hcmdpbjowIC0xNXB4IDIuMnJlbTsNCiAgICAgICAgICAgIGJvcmRlci1ib3R0b206NnB4IHNvbGlkIHZhcigtLW9ybyk7IGJveC1zaGFkb3c6MCA2cHggMThweCByZ2JhKDIwLDY5LDI2LC4yNSk7IH0NCiAgI2hlYWRlciBoMS50aXRsZSB7IGNvbG9yOiNmZmY7IGJvcmRlcjowOyBtYXJnaW46MCAwIC4zcmVtOyBwYWRkaW5nOjA7IH0NCiAgI2hlYWRlciBoMy5zdWJ0aXRsZSwgI2hlYWRlciBoNC5hdXRob3IsICNoZWFkZXIgaDQuZGF0ZSB7IGNvbG9yOiNFOEY1RTk7IG1hcmdpbjouMnJlbSAwOyB9DQoNCiAgLyogw41uZGljZSAqLw0KICAjVE9DIHsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3gtc2hhZG93OjAgMnB4IDEwcHggcmdiYSgwLDAsMCwuMDgpOyB9DQogIC5saXN0LWdyb3VwLWl0ZW0geyBib3JkZXItY29sb3I6I2UzZWZlNDsgfQ0KDQogIC8qIFRhYmxhIGRlIGNvbnRlbmlkbyAqLw0KICAubGlzdC1ncm91cC1pdGVtLmFjdGl2ZSwgLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmU6aG92ZXIsIC5saXN0LWdyb3VwLWl0ZW0uYWN0aXZlOmZvY3VzIHsNCiAgICBiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLXZlcmRlKTsgYm9yZGVyLWNvbG9yOnZhcigtLXZlcmRlKTsgfQ0KDQogIC8qIFRhYmxhcyAqLw0KICB0YWJsZSB7IGJvcmRlci1jb2xsYXBzZTpzZXBhcmF0ZTsgYm9yZGVyLXNwYWNpbmc6MDsgd2lkdGg6MTAwJTsgbWFyZ2luOjEuMnJlbSAwIDJyZW07DQogICAgICAgICAgZm9udC1zaXplOjEuNXJlbTsgYm9yZGVyLXJhZGl1czo4cHg7IG92ZXJmbG93OmhpZGRlbjsgYm94LXNoYWRvdzowIDJweCAxMHB4IHJnYmEoMCwwLDAsLjA4KTsgfQ0KICBjYXB0aW9uIHsgY2FwdGlvbi1zaWRlOnRvcDsgZm9udC13ZWlnaHQ6NjAwOyBjb2xvcjp2YXIoLS10ZXh0byk7IHBhZGRpbmc6MCAwIDhweDsgdGV4dC1hbGlnbjpsZWZ0OyB9DQogIHRoIHsgYmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQoMTgwZGVnLCMzODhFM0MsIzJFN0QzMik7IGNvbG9yOiNmZmY7IHRleHQtYWxpZ246Y2VudGVyICFpbXBvcnRhbnQ7IHBhZGRpbmc6MTJweCAxNHB4OyBmb250LXdlaWdodDo2MDA7IGJvcmRlci1ib3R0b206M3B4IHNvbGlkIHZhcigtLW9ybyk7IH0NCiAgdGQgeyBwYWRkaW5nOjEwcHggMTRweDsgYm9yZGVyLWJvdHRvbToxcHggc29saWQgI2U5ZWNlZjsgfQ0KICB0Ym9keSB0cjpudGgtY2hpbGQoZXZlbikgeyBiYWNrZ3JvdW5kOnZhcigtLWdyaXMpOyB9DQogIHRib2R5IHRyOmhvdmVyIHsgYmFja2dyb3VuZDp2YXIoLS12ZXJkZS1jbGFybyk7IH0NCg0KICAvKiBGaWd1cmFzICovDQogIGltZyB7IG1heC13aWR0aDoxMDAlOyB9DQogIC5maWd1cmUgaW1nLCBwID4gaW1nIHsgYm9yZGVyLXJhZGl1czo4cHg7IGJveC1zaGFkb3c6MCAycHggMTBweCByZ2JhKDAsMCwwLC4wOCk7IH0NCiAgcC5jYXB0aW9uIHsgdGV4dC1hbGlnbjpjZW50ZXI7IGZvbnQtc2l6ZTouOXJlbTsgY29sb3I6IzZjNzU3ZDsgbWFyZ2luLXRvcDo4cHg7IH0NCg0KICAvKiBDYWphcyBkZXN0YWNhZGFzICovDQogIC5jYWxsb3V0IHsgYm9yZGVyLWxlZnQ6NXB4IHNvbGlkIHZhcigtLXZlcmRlKTsgYmFja2dyb3VuZDp2YXIoLS12ZXJkZS1jbGFybyk7DQogICAgICAgICAgICAgcGFkZGluZzoxNHB4IDE4cHg7IGJvcmRlci1yYWRpdXM6MCA4cHggOHB4IDA7IG1hcmdpbjoxLjJyZW0gMDsgfQ0KICAuY2FsbG91dC5wcmVndW50YSB7IGJvcmRlci1jb2xvcjp2YXIoLS12ZXJkZSk7IGJhY2tncm91bmQ6I0U4RjVFOTsgfQ0KICAuY2FsbG91dC5oaXBvdGVzaXMgeyBib3JkZXItY29sb3I6dmFyKC0tb3JvKTsgYmFja2dyb3VuZDojRkZGOEUxOyB9DQoNCiAgLyogQ8OzZGlnbyAqLw0KICBwcmUgeyBib3JkZXItcmFkaXVzOjhweDsgYm9yZGVyOjFweCBzb2xpZCAjZTBlMGUwOyBiYWNrZ3JvdW5kOiNmYWZhZmE7IH0NCg0KICAvKiBHYWxlcsOtYSAqLw0KICAuZ2FsZXJpYSB7IGRpc3BsYXk6Z3JpZDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOnJlcGVhdChhdXRvLWZpbGwsbWlubWF4KDIxMHB4LDFmcikpOyBnYXA6MTZweDsgbWFyZ2luOjEuMmVtIDA7IH0NCiAgLmdhbGVyaWEgZmlndXJlIHsgbWFyZ2luOjA7IGJhY2tncm91bmQ6I2ZmZjsgYm9yZGVyLXJhZGl1czoxMHB4OyBvdmVyZmxvdzpoaWRkZW47DQogICAgICAgICAgICAgICAgICAgIGJveC1zaGFkb3c6MCA0cHggMTJweCByZ2JhKDAsMCwwLC4xMik7IHRyYW5zaXRpb246dHJhbnNmb3JtIC4yczsgfQ0KICAuZ2FsZXJpYSBmaWd1cmU6aG92ZXIgeyB0cmFuc2Zvcm06dHJhbnNsYXRlWSgtNHB4KTsgfQ0KICAuZ2FsZXJpYSBpbWcgeyB3aWR0aDoxMDAlOyBkaXNwbGF5OmJsb2NrOyBhc3BlY3QtcmF0aW86NC8zOyBvYmplY3QtZml0OmNvdmVyOyB9DQogIC5nYWxlcmlhIGZpZ2NhcHRpb24geyB0ZXh0LWFsaWduOmNlbnRlcjsgZm9udC1zaXplOi45cmVtOyBwYWRkaW5nOjEwcHg7IGZvbnQtd2VpZ2h0OjYwMDsgfQ0KICAuc2luZm90byB7IGJhY2tncm91bmQ6I2VlZTsgY29sb3I6Izc3NzsgdGV4dC1hbGlnbjpjZW50ZXI7IHBhZGRpbmc6NC41ZW0gMDsgfQ0KDQogIC8qIE1hcGEgKi8NCiAgLmxlYWZsZXQtY29udGFpbmVyIHsgYm9yZGVyLXJhZGl1czoxMHB4OyBib3gtc2hhZG93OjAgMnB4IDEycHggcmdiYSgwLDAsMCwuMTUpOyB9DQo8L3N0eWxlPg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBmaWcud2lkdGggPSA3LjUsIGZpZy5oZWlnaHQgPSA0LjYsIGRwaSA9IDE1MCkNCm9wdGlvbnMoT3V0RGVjID0gIiwiLCBzY2lwZW4gPSA5OTkpDQoNCiMgUGFsZXRhIChkYWx0w7NuaWNvLWFtaWdhYmxlKSB5IHRvbm9zIG9zY3Vyb3MgcGFyYSBib3JkZXMNCmNvbF9leHBvICAgICA8LSBjKHNvbCA9ICIjRjVCNzAwIiwgc29tYnJhID0gIiMyRTdEMzIiKQ0KY29sX2V4cG9fb3NjIDwtIGMoc29sID0gIiM5Qzc0MDAiLCBzb21icmEgPSAiIzE0NDUxQSIpDQpjb2xfdmVyZGUgICAgPC0gIiMyRTdEMzIiDQoNCmZtdCAgIDwtIGZ1bmN0aW9uKHgsIGQgPSAxKSBmb3JtYXRDKHgsIGZvcm1hdCA9ICJmIiwgZGlnaXRzID0gZCwgZGVjaW1hbC5tYXJrID0gIiwiKQ0KZm10X3AgPC0gZnVuY3Rpb24ocCkgaWZlbHNlKHAgPCAwLjAwMSwgIjwgMCwwMDEiLCBmb3JtYXRDKHAsIGZvcm1hdCA9ICJmIiwgZGlnaXRzID0gMywgZGVjaW1hbC5tYXJrID0gIiwiKSkNCmN2ICAgIDwtIGZ1bmN0aW9uKHgpIDEwMCAqIHNkKHgpIC8gbWVhbih4KQ0KdGFibGEgPC0gZnVuY3Rpb24oeCwgLi4uKSBrbml0cjo6a2FibGUoeCwgZm9ybWF0ID0gImh0bWwiLCBmb3JtYXQuYXJncyA9IGxpc3QoZGVjaW1hbC5tYXJrID0gIiwiKSwgLi4uKQ0KYV9udW1lcm8gPC0gZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhzdWIoIiwiLCAiLiIsIGFzLmNoYXJhY3Rlcih4KSwgZml4ZWQgPSBUUlVFKSkNCnRhYmxhX2Fub3ZhIDwtIGZ1bmN0aW9uKG1vZGVsbykgeyBhIDwtIGFzLmRhdGEuZnJhbWUoYW5vdmEobW9kZWxvKSk7IGRhdGEuZnJhbWUoRnVlbnRlID0gcm93bmFtZXMoYSksIGdsID0gYSREZiwgU0MgPSBhW1siU3VtIFNxIl1dLCBDTSA9IGFbWyJNZWFuIFNxIl1dLCBGID0gYVtbIkYgdmFsdWUiXV0sIHAgPSBhW1siUHIoPkYpIl1dLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpIH0NCmZvcm1hdG9fYW5vdmEgPC0gZnVuY3Rpb24odCkgeyBkYXRhLmZyYW1lKEZ1ZW50ZSA9IHQkRnVlbnRlLCBnbCA9IHQkZ2wsIFNDID0gZm10KHQkU0MsIDMpLCBDTSA9IGZtdCh0JENNLCAzKSwgRiA9IGlmZWxzZShpcy5uYSh0JEYpLCAiIiwgZm10KHQkRiwgMikpLCBwID0gaWZlbHNlKGlzLm5hKHQkcCksICIiLCBmbXRfcCh0JHApKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSB9DQoNCiMgRXN0aWxvIGNvbcO6biBwYXJhIGdyw6FmaWNhcyBiYXNlIFINCmVzdGlsb19iYXNlIDwtIGZ1bmN0aW9uKCkgcGFyKGZhbWlseSA9ICJzYW5zIiwgbGFzID0gMSwgYnR5ID0gImwiLCBjZXgubWFpbiA9IDEuMSwgZm9udC5tYWluID0gMiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbC5tYWluID0gImdyZXkxNSIsIGNvbC5heGlzID0gImdyZXkzMCIsIGNvbC5sYWIgPSAiZ3JleTIwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRjbCA9IC0wLjMsIG1ncCA9IGMoMi42LCAwLjcsIDApKQ0KDQojIFRhYmxhcyBtw6FzIGxpbXBpYXMgKHVzYSBrYWJsZUV4dHJhIHNpIGVzdMOhIGluc3RhbGFkbykNCmVzdCA8LSBmdW5jdGlvbihrKSB7DQogIGlmIChyZXF1aXJlTmFtZXNwYWNlKCJrYWJsZUV4dHJhIiwgcXVpZXRseSA9IFRSVUUpKQ0KICAgIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoaywgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IFRSVUUsIHBvc2l0aW9uID0gImNlbnRlciIpDQogIGVsc2Ugaw0KfQ0KYGBgDQoNCmBgYHtyIGxlY3R1cmEsIGluY2x1ZGU9RkFMU0V9DQoNCiMgMi4gTGVlciBlbCBhcmNoaXZvDQpjcnVkbyA8LSByZWFkLmNzdigiQzovVXNlcnMvVXN1YXJpby9Eb2N1bWVudHMvVU5JVkVSU0lEQUQvU0VNRVNUUkUgSVYvRElTRU5PL1RBTExFUiAyL1RBTExFUiAyX0RJU0VOTy9jb25zb2xpZGFkby5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIG5hLnN0cmluZ3MgPSBjKCIiLCAiTkEiKSwgZW5jb2RpbmcgPSAiVVRGLTgiKQ0KDQojIDMuIExhcyBjb21wcm9iYWNpb25lcw0KaWYgKCEib2JzZXJ2YWNpb25lcyIgJWluJSBuYW1lcyhjcnVkbykpIGNydWRvJG9ic2VydmFjaW9uZXMgPC0gTkFfY2hhcmFjdGVyXw0KZXNwZXJhZGFzIDwtIGMoImdydXBvIiwgImlkX2FyYm9sIiwgImxhdCIsICJsb24iLCAibl9ob2phIiwgImFyZWFfY20yIiwgImV4cG9zaWNpb24iLCAiZmVjaGEiLCAib2JzZXJ2YWNpb25lcyIpDQpmYWx0YW4gPC0gc2V0ZGlmZihlc3BlcmFkYXMsIG5hbWVzKGNydWRvKSkNCg0KZmVjaGFzICAgPC0gYXMuRGF0ZShjcnVkbyRmZWNoYSwgZm9ybWF0ID0gIiVkLyVtLyVZIikNCm5fYXJib2wgIDwtIGxlbmd0aCh1bmlxdWUodG91cHBlcih0cmltd3MoY3J1ZG8kaWRfYXJib2wpKSkpDQpuX2dydXBvcyA8LSBsZW5ndGgodW5pcXVlKGNydWRvJGdydXBvKSkNCmBgYA0KDQojIFNpdGlvIGRlIGVzdHVkaW8geSBwcm90b2NvbG8NCg0KRWwgZXN0dWRpbyBzZSBoaXpvIGVuIHVuYSBwYXJjZWxhIGNvbiDDoXJib2xlcyBlbiBlbCBjb3JyZWdpbWllbnRvIGRlIExhIEJ1aXRyZXJhLCBlbiBDYWxpIChWYWxsZSBkZWwgQ2F1Y2EsIENvbG9tYmlhKSwgZW4gbGEgem9uYSBydXJhbCBkZWwgbXVuaWNpcGlvLCBlbiBlbCBwaWVkZW1vbnRlIGRlIGxhIGNvcmRpbGxlcmEgT2NjaWRlbnRhbCwgYSAxMTUxIG1zbm0sIGNvbiB0ZW1wZXJhdHVyYXMgbWVkaWFzIGNlcmNhbmFzIGEgbG9zIDI0IMKwQyB5IGRvcyB0ZW1wb3JhZGFzIGRlIGxsdXZpYSBhbCBhw7FvLiBEZW50cm8gZGUgbGEgcGFyY2VsYSBoYXkgem9uYXMgYWJpZXJ0YXMgeSB2ZWdldGFjacOzbiBzZWN1bmRhcmlhLiBFbCBtdWVzdHJlbyBzZSByZWFsaXrDsyBlbiB1biBkw61hIG51YmxhZG8geSBow7ptZWRvLCBjb25kaWNpw7NuIHF1ZSBzZSBhbm90w7MgcG9ycXVlIGxhIHR1cmdlbmNpYSBkZSBsYSBob2phICh5IHBvciB0YW50byBzdSDDoXJlYSBtZWRpZGEpIGRlcGVuZGUgZGUgbGEgaHVtZWRhZCB5IGxhIHRlbXBlcmF0dXJhIGRlbCBtb21lbnRvOiB1biBkw61hIGFzw60gcmVkdWNlIGxhIGV2YXBvdHJhbnNwaXJhY2nDs24geSBwdWVkZSBoYWNlciBxdWUgbGFzIGhvamFzIHNlIHZlYW4gbcOhcyBleHBhbmRpZGFzIHF1ZSBlbiB1biBkw61hIHNvbGVhZG8uDQoNClNlIGVsaWdpZXJvbiA1IMOhcmJvbGVzIGFkdWx0b3MgeSBzYW5vcyBkZSBob2phcyBzaW1wbGVzIGRlbnRybyBkZSBsYSBwYXJjZWxhLCBjb24gMyBhIHBsZW5vIHNvbCAoRzdfVDEsIEc3X1QzLCBHN19UNSkgeSAyIGEgbGEgc29tYnJhIChHN19UMiwgRzdfVDQpLCB5IHNlIHJlZ2lzdHJhcm9uIHN1cyBjb29yZGVuYWRhcyBjb24gZWwgR1BTIGRlbCBjZWx1bGFyLiBEZSBjYWRhIMOhcmJvbCBzZSB0b21hcm9uIDEwIGhvamFzIGFkdWx0YXMsIGV4cGFuZGlkYXMgeSBzaW4gZGHDsW8sIHJlcGFydGlkYXMgcG9yIHRvZGEgbGEgY29wYS4gQ2FkYSBob2phIHNlIHRyYXrDsyBzb2JyZSBwYXBlbCB5IHNlIGZvdG9ncmFmacOzIGRlbnRybyBkZSB1biBtYXJjbyByZWN0YW5ndWxhciBkZSBsYWRvcyBjb25vY2lkb3MuIENvbW8gbGFzIGhvamFzIHZhcsOtYW4gZW4gdGFtYcOxbywgc2Ugb3B0w7MgcG9yIHVzYXIgdHJlcyBtYXJjb3MgZGlzdGludG9zOiA5NSDDlyAxOTUgbW0sIDIzNSDDlyAxNTggbW0geSAxMDAgw5cgMTU4IG1tLiBFbCBzY3JpcHQgdXPDsyBlbCB0YW1hw7FvIGRlbCBtYXJjbyBkZSBjYWRhIGZvdG8gcGFyYSBjb252ZXJ0aXIgcMOteGVsZXMgYSBjbcKyIHkgY2FsY3VsYXIgZWwgw6FyZWEuIExvcyBkYXRvcyBzZSBjYXB0dXJhcm9uIGVuIHVuYSBwbGFudGlsbGEgY29tw7puIGRvbmRlIGNhZGEgZmlsYSBjb250aWVuZSBsb3MgZGF0b3MgZGUgdW5hIGhvamEuDQoNCiMjIE1hcGEgZGUgbG9zIHNpdGlvcw0KDQpDYWRhIHB1bnRvIGVzIHVuIMOhcmJvbC4gSGF6IGNsaWMgZW4gdW4gcHVudG8gcGFyYSB2ZXIgc3UgZm90byB5IHN1cyBkYXRvczsgYXJyaWJhIGEgbGEgZGVyZWNoYSBwdWVkZXMgY2FtYmlhciBlbCBmb25kbyAoc2UgYWJyZSBlbiBzYXTDqWxpdGU7IHRhbWJpw6luIGhheSBjYWxsZXMpIHkgb2N1bHRhciBsb3Mgw6FyYm9sZXMgZGUgc29sIG8gZGUgc29tYnJhLiBMb3MgNSDDoXJib2xlcyBlc3TDoW4gZGVudHJvIGRlIHVuYSBtaXNtYSBwYXJjZWxhLCBsbyBxdWUgcmVkdWNlIGxhIHZhcmlhY2nDs24gZGUgc3VlbG8geSBhbHRpdHVkIGVudHJlIGVsbG9zLg0KDQpgYGB7ciBzaXRpb3MsIGluY2x1ZGU9RkFMU0V9DQojIDEuIERlZmluaW1vcyBsYSBydXRhIGFic29sdXRhIGV4YWN0YSBhIHR1IHByb3llY3RvDQpydXRhX3Byb3llY3RvIDwtICJDOi9Vc2Vycy9Vc3VhcmlvL0RvY3VtZW50cy9VTklWRVJTSURBRC9TRU1FU1RSRSBJVi9ESVNFTk8vVEFMTEVSIDIvVEFMTEVSIDJfRElTRU5PIg0KDQpzaXRpb3MgPC0gdW5pcXVlKGRhdGEuZnJhbWUoDQogIGdydXBvID0gY3J1ZG8kZ3J1cG8sDQogIGlkX2FyYm9sID0gdG91cHBlcih0cmltd3MoY3J1ZG8kaWRfYXJib2wpKSwNCiAgbGF0ID0gYV9udW1lcm8oY3J1ZG8kbGF0KSwNCiAgbG9uID0gYV9udW1lcm8oY3J1ZG8kbG9uKSwNCiAgZXhwb3NpY2lvbiA9IHRvbG93ZXIodHJpbXdzKGNydWRvJGV4cG9zaWNpb24pKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopKQ0Kc2l0aW9zJGhvamFzIDwtIGFzLmludGVnZXIodGFibGUodG91cHBlcih0cmltd3MoY3J1ZG8kaWRfYXJib2wpKSlbc2l0aW9zJGlkX2FyYm9sXSkNCg0KIyAyLiBMZSBkZWNpbW9zIGEgUiBxdWUgYnVzcXVlIGxhcyBmb3RvcyBlbiBsYSBydXRhIGFic29sdXRhDQpjYXJwZXRhX2ZvdG9zIDwtIGZpbGUucGF0aChydXRhX3Byb3llY3RvLCBwYXJhbXMkY2FycGV0YV9mb3Rvc19hcmJvbGVzKQ0KDQpidXNjYXJfZm90byA8LSBmdW5jdGlvbihpZCkgew0KICBjYW5kaWRhdGFzIDwtIGZpbGUucGF0aChjYXJwZXRhX2ZvdG9zLCBwYXN0ZTAoaWQsIGMoIi5qcGciLCAiLmpwZWciLCAiLnBuZyIpKSkNCiAgZXhpc3RlbnRlcyA8LSBjYW5kaWRhdGFzW2ZpbGUuZXhpc3RzKGNhbmRpZGF0YXMpXQ0KICBpZiAobGVuZ3RoKGV4aXN0ZW50ZXMpID4gMCkgZXhpc3RlbnRlc1sxXSBlbHNlIE5BX2NoYXJhY3Rlcl8NCn0NCnNpdGlvcyRmb3RvIDwtIHZhcHBseShzaXRpb3MkaWRfYXJib2wsIGJ1c2Nhcl9mb3RvLCBjaGFyYWN0ZXIoMSkpDQoNCiMgMy4gQXZpc28gZW4gY29uc29sYQ0KY2F0KCJGb3RvcyBlbmNvbnRyYWRhczoiLCBzdW0oIWlzLm5hKHNpdGlvcyRmb3RvKSksICJkZSIsIG5yb3coc2l0aW9zKSwgIlxuIikNCg0Kc2l0aW9zJHBvcHVwIDwtIHZhcHBseShzZXFfbGVuKG5yb3coc2l0aW9zKSksIGZ1bmN0aW9uKGkpIHsNCiAgcyA8LSBzaXRpb3NbaSwgXQ0KICBpbWcgPC0gaWYgKGlzLm5hKHMkZm90bykpICIiIGVsc2UNCiAgICBwYXN0ZTAoIjxpbWcgc3JjPSciLCBVUkxlbmNvZGUocyRmb3RvLCByZXNlcnZlZCA9IFRSVUUpLCAiJyB3aWR0aD0nMjAwJz48YnI+IikNCiAgcGFzdGUwKGltZywgIjxiPiIsIHMkaWRfYXJib2wsICI8L2I+PGJyPkV4cG9zaWNpw7NuOiAiLCBzJGV4cG9zaWNpb24sDQogICAgICAgICAiPGJyPkdydXBvICIsIHMkZ3J1cG8sICI8YnI+SG9qYXMgcmVnaXN0cmFkYXM6ICIsIHMkaG9qYXMsDQogICAgICAgICAiPGJyPiIsIGZtdChzJGxhdCwgNSksICI7ICIsIGZtdChzJGxvbiwgNSkpDQp9LCBjaGFyYWN0ZXIoMSkpDQpgYGANCg0KYGBge3IgbWFwYX0NCmlmIChyZXF1aXJlTmFtZXNwYWNlKCJsZWFmbGV0IiwgcXVpZXRseSA9IFRSVUUpKSB7DQogIGxpYnJhcnkobGVhZmxldCkNCiAgDQogICMgMS4gQWdyZWdhbW9zIHdpZHRoIHkgaGVpZ2h0IGRpcmVjdGFtZW50ZSBhcXXDrS4NCiAgIyBDYW1iaWEgaGVpZ2h0ID0gNDAwIHBvciAzNTAgc2kgbG8gcXVpZXJlcyBtw6FzIHBlcXVlw7FvLg0KICAjIENhbWJpYSB3aWR0aCA9ICI4NSUiIHBvciAiMTAwJSIgc2kgbG8gcXVpZXJlcyBhIHRvZG8gbG8gYW5jaG8uDQogIG1hcGEgPC0gbGVhZmxldChzaXRpb3MsIHdpZHRoID0gIjg1JSIsIGhlaWdodCA9IDQwMCkgJT4lDQogICAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkRXNyaS5Xb3JsZEltYWdlcnksIGdyb3VwID0gIlNhdMOpbGl0ZSIpICU+JQ0KICAgIGFkZFRpbGVzKGdyb3VwID0gIkNhbGxlcyIpICU+JQ0KICAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IHNpdGlvc1tzaXRpb3MkZXhwb3NpY2lvbiA9PSAic29sIiwgXSwgbG5nID0gfmxvbiwgbGF0ID0gfmxhdCwNCiAgICAgICAgICAgICAgICAgICAgIHJhZGl1cyA9IDksIHdlaWdodCA9IDMsIGNvbG9yID0gIndoaXRlIiwgZmlsbENvbG9yID0gY29sX2V4cG9bWyJzb2wiXV0sDQogICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuOTUsIGxhYmVsID0gfmlkX2FyYm9sLCBwb3B1cCA9IH5wb3B1cCwNCiAgICAgICAgICAgICAgICAgICAgIHBvcHVwT3B0aW9ucyA9IHBvcHVwT3B0aW9ucyhtYXhXaWR0aCA9IDI0MCksIGdyb3VwID0gIlNvbCIpICU+JQ0KICAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IHNpdGlvc1tzaXRpb3MkZXhwb3NpY2lvbiA9PSAic29tYnJhIiwgXSwgbG5nID0gfmxvbiwgbGF0ID0gfmxhdCwNCiAgICAgICAgICAgICAgICAgICAgIHJhZGl1cyA9IDksIHdlaWdodCA9IDMsIGNvbG9yID0gIndoaXRlIiwgZmlsbENvbG9yID0gY29sX2V4cG9bWyJzb21icmEiXV0sDQogICAgICAgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuOTUsIGxhYmVsID0gfmlkX2FyYm9sLCBwb3B1cCA9IH5wb3B1cCwNCiAgICAgICAgICAgICAgICAgICAgIHBvcHVwT3B0aW9ucyA9IHBvcHVwT3B0aW9ucyhtYXhXaWR0aCA9IDI0MCksIGdyb3VwID0gIlNvbWJyYSIpICU+JQ0KICAgIGFkZExheWVyc0NvbnRyb2woYmFzZUdyb3VwcyA9IGMoIlNhdMOpbGl0ZSIsICJDYWxsZXMiKSwgb3ZlcmxheUdyb3VwcyA9IGMoIlNvbCIsICJTb21icmEiKSwNCiAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkpICU+JQ0KICAgIGFkZExlZ2VuZCgiYm90dG9tcmlnaHQiLCBjb2xvcnMgPSB1bm5hbWUoY29sX2V4cG8pLCBsYWJlbHMgPSBjKCJTb2wiLCAiU29tYnJhIiksDQogICAgICAgICAgICAgIHRpdGxlID0gIkV4cG9zaWNpw7NuIiwgb3BhY2l0eSA9IDEpICU+JQ0KICAgIGFkZFNjYWxlQmFyKCJib3R0b21sZWZ0IikNCiAgDQogICMgMi4gRXN0byBoYWNlIHF1ZSBlbCBtYXBhIHF1ZWRlIHBlcmZlY3RhbWVudGUgY2VudHJhZG8gZW4gbGEgcMOhZ2luYQ0KICBodG1sdG9vbHM6OmRpdihtYXBhLCBzdHlsZSA9ICJkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsgbWFyZ2luLWJvdHRvbTogMjBweDsiKQ0KICANCn0gZWxzZSB7DQogIGNhdCgiRWwgcGFxdWV0ZSAnbGVhZmxldCcgbm8gZXN0w6EgaW5zdGFsYWRvLiIpDQp9DQpgYGANCg0KIyMgRm90b3MgZGUgbG9zIMOhcmJvbGVzDQoNCkNhZGEgw6FyYm9sIGRlbCBlc3R1ZGlvIHRpZW5lIHVuYSBmb3RvIGRlIHJlZmVyZW5jaWEuIEVzdGFzIGltw6FnZW5lcyBwZXJtaXRlbiB2ZXJpZmljYXIgbGEgY2xhc2lmaWNhY2nDs24gZW4gc29sIHkgc29tYnJhLCB5IGF5dWRhbiBhIHF1ZSBlbCBsZWN0b3Igc2UgaGFnYSB1bmEgaWRlYSBkZWwgc2l0aW8geSBkZSBsYSBjb3BhIGRlIGNhZGEgw6FyYm9sLiAzIMOhcmJvbGVzIGRlIHNvbCAoRzdfVDEsIEc3X1QzLCBHN19UNSkgeSAyIGRlIHNvbWJyYSAoRzdfVDIsIEc3X1Q0KS4gTG9zIMOhcmJvbGVzIGRlIHNvbCByZWNpYmVuIGx1eiBkaXJlY3RhIGxhIG1heW9yIHBhcnRlIGRlbCBkw61hIHkgbm8gZXN0w6FuIGN1YmllcnRvcyBwb3Igb3RyYXMgY29wYXMgbmkgcG9yIGVkaWZpY2FjaW9uZXMsIGxvcyBkZSBzb21icmEgY3JlY2VuIGJham8gbGEgY29iZXJ0dXJhIGRlIG90cm9zIMOhcmJvbGVzIG8gZW4gem9uYXMgY29uIGx1eiBmaWx0cmFkYS4NCg0KYGBge3IgZ2FsZXJpYSwgcmVzdWx0cz0nYXNpcyd9DQpnX2dhbGVyaWEgPC0gaWYgKGV4aXN0cygicGFyYW1zIikgJiYgIWlzLm51bGwocGFyYW1zJGdydXBvKSkgcGFyYW1zJGdydXBvIGVsc2UgNw0KZ19nYWxlcmlhIDwtIGFzLmNoYXJhY3RlcihnX2dhbGVyaWEpDQoNCmFyYl9nIDwtIHNpdGlvc1thcy5jaGFyYWN0ZXIoc2l0aW9zJGdydXBvKSA9PSBnX2dhbGVyaWEsIF0NCmFyYl9nIDwtIGFyYl9nW29yZGVyKGFyYl9nJGlkX2FyYm9sKSwgXQ0KDQp0YXJqZXRhcyA8LSB2YXBwbHkoc2VxX2xlbihucm93KGFyYl9nKSksIGZ1bmN0aW9uKGkpIHsNCiAgcyA8LSBhcmJfZ1tpLCBdDQogIA0KICBpbWcgPC0gaWYgKGlzLm5hKHMkZm90bykpIHsNCiAgICAiPGRpdiBjbGFzcz0nc2luZm90byc+Zm90byBwZW5kaWVudGU8L2Rpdj4iDQogIH0gZWxzZSB7DQogICAgcGFzdGUwKCI8aW1nIHNyYz0nIiwga25pdHI6OmltYWdlX3VyaShzJGZvdG8pLCAiJz4iKQ0KICB9DQogIA0KICBwYXN0ZTAoIjxmaWd1cmU+IiwgaW1nLA0KICAgICAgICAgIjxmaWdjYXB0aW9uPjxiPiIsIHMkaWRfYXJib2wsICI8L2I+IC0gIiwgcyRleHBvc2ljaW9uLA0KICAgICAgICAgIjwvZmlnY2FwdGlvbj48L2ZpZ3VyZT4iKQ0KfSwgY2hhcmFjdGVyKDEpKQ0KDQpjYXQoIlxuXG48ZGl2IGNsYXNzPSdnYWxlcmlhJz5cbiIsIHBhc3RlKHRhcmpldGFzLCBjb2xsYXBzZSA9ICJcbiIpLCAiXG48L2Rpdj5cblxuIikNCmBgYA0KDQojIEludHJvZHVjY2nDs24NCg0KTGFzIGhvamFzIGVzdMOhbiBlbnRyZSBsb3Mgw7NyZ2Fub3MgY29uIG1heW9yIHBsYXN0aWNpZGFkIGZlbm90w61waWNhIGVuIGxhcyBwbGFudGFzOiBhanVzdGFuIHN1IG1vcmZvbG9nw61hIHkgYW5hdG9tw61hIGVuIHJlc3B1ZXN0YSBhIGdyYWRpZW50ZXMgYW1iaWVudGFsZXMgY29tbyBsYSByYWRpYWNpw7NuIHNvbGFyLiBEYWRvIHF1ZSBsYSBsdXogZXMgdW4gZmFjdG9yIGFiacOzdGljbyBkZXRlcm1pbmFudGUgcGFyYSBlbCByZW5kaW1pZW50byBmb3Rvc2ludMOpdGljbyB5IGVsIGJhbGFuY2UgZW5lcmfDqXRpY28gZm9saWFyLCBsYXMgdmFyaWFjaW9uZXMgZW4gZWwgcsOpZ2ltZW4gbHVtw61uaWNvIG1vbGRlYW4gZGlyZWN0YW1lbnRlIGxhIGFycXVpdGVjdHVyYSB5IGVsIHRhbWHDsW8gZGUgbGEgbMOhbWluYSBmb2xpYXIgKERpYS1WYWx2ZXJkZSBldCBhbC4sIDIwMjYpLg0KDQo8ZGl2IGNsYXNzPSJjYWxsb3V0IHByZWd1bnRhIj4NCjxiPlByZWd1bnRhIGRlIGludmVzdGlnYWNpw7NuLjwvYj4gwr9FeGlzdGUgdW5hIGRpZmVyZW5jaWEgc2lnbmlmaWNhdGl2YSBlbiBlbCDDoXJlYSBmb2xpYXIgZGUgbG9zIMOhcmJvbGVzIHNlZ8O6biBzdSBncmFkbyBkZSBleHBvc2ljacOzbiBhIGxhIGx1eiBzb2xhcj8NCjwvZGl2Pg0KDQpTZSBlc3BlcmFuIHZhcmlhY2lvbmVzIGVzdHJ1Y3R1cmFsZXMgbWFyY2FkYXMgZW50cmUgaG9qYXMgZGUgc29sIHkgZGUgc29tYnJhLCBkZWJpZG8gYSBsYXMgZGlzdGludGFzIGVzdHJhdGVnaWFzIGFkYXB0YXRpdmFzIGRlIGFzaWduYWNpw7NuIGRlIHJlY3Vyc29zIGZyZW50ZSBhbCBlc3Ryw6lzIGFiacOzdGljby4gRW4gYW1iaWVudGVzIHNvbWJyZWFkb3MgbyBjb24gYmFqYSBpbnRlbnNpZGFkIGRlIHJhZGlhY2nDs24sIGxhcyBwbGFudGFzIGV4cGVyaW1lbnRhbiB1biBkw6lmaWNpdCBsdW3DrW5pY28gYWwgcXVlIHJlc3BvbmRlbiBwbMOhc3RpY2FtZW50ZSBpbmNyZW1lbnRhbmRvIGxhIHN1cGVyZmljaWUgZGUgc3VzIGhvamFzIHBhcmEgb3B0aW1pemFyIGxhIGNhcHRhY2nDs24gZGUgbHV6LiBQb3IgZWwgY29udHJhcmlvLCBiYWpvIGFsdGEgZXhwb3NpY2nDs24gc29sYXIgZGlyZWN0YSwgbGFzIGhvamFzIGVuZnJlbnRhbiBtYXlvcmVzIGV4aWdlbmNpYXMgdMOpcm1pY2FzIGUgaMOtZHJpY2FzOyBlbiByZXNwdWVzdGEsIGRlc2Fycm9sbGFuIGVzdHJ1Y3R1cmFzIG3DoXMgZ3J1ZXNhcywgY29uIG1lbm9yIMOhcmVhIGZvbGlhciBlc3BlY8OtZmljYSAoQUZFKSwgeSBtZWNhbmlzbW9zIG1vcmZvbMOzZ2ljb3Mgb3JpZW50YWRvcyBhIGRpc2lwYXIgY2Fsb3IgeSBjb250cm9sYXIgbGEgdHJhbnNwaXJhY2nDs24gKEZyYW5jaXMgJiBHaWxtYW4sIDIwMTkpLg0KDQo8ZGl2IGNsYXNzPSJjYWxsb3V0IGhpcG90ZXNpcyI+DQo8Yj5IaXDDs3Rlc2lzLjwvYj4gU2UgZXNwZXJhIHVuIGluY3JlbWVudG8gZW4gZWwgw6FyZWEgZm9saWFyIGRlIGxvcyDDoXJib2xlcyBxdWUgY3JlY2VuIGJham8gbWVub3IgZXhwb3NpY2nDs24gbHVtw61uaWNhLCB5IHVuYSBkaXNtaW51Y2nDs24gZW4gZWwgw6FyZWEgZm9saWFyIGRlIGxvcyDDoXJib2xlcyBleHB1ZXN0b3MgYSByYWRpYWNpw7NuIHNvbGFyIG3DoXMgYWx0YSB5IGNvbnN0YW50ZS4gU2kgbGEgaGlww7N0ZXNpcyBlcyBjaWVydGEsIGxhIGRpZmVyZW5jaWEgZGViZXLDrWEgdmVyc2UgZW4gbG9zIHByb21lZGlvcyBwb3Igw6FyYm9sIHkgc2VyIGRldGVjdGFibGUgY29uIHVuYSBwcnVlYmEgYWRlY3VhZGEgYSBsYSB1bmlkYWQgZGUgYW7DoWxpc2lzIChlbCDDoXJib2wpLg0KPC9kaXY+DQoNCioqRWwgY29uZnVzb3IgZGVsIG1vcmZvdGlwby4qKiBFbiB1bmEgcGFyY2VsYSBwdWVkZW4gY29udml2aXIgZXNwZWNpZXMgY29uIHRhbWHDsW9zIGZvbGlhcmVzIG11eSBkaXN0aW50b3MuIFNpIGxvcyDDoXJib2xlcyBkZSBzb21icmEgcGVydGVuZWNlbiBwb3IgY2FzdWFsaWRhZCBhIGVzcGVjaWVzIGRlIGhvamEgZ3JhbmRlLCBsYSBkaWZlcmVuY2lhIHNlIGRlYmVyw61hIGFsIG1vcmZvdGlwbyB5IG5vIGEgbGEgbHV6LiBQb3IgZXNvLCBhZGVtw6FzIGRlIGNvbXBhcmFyIGxvcyA1IMOhcmJvbGVzLCBjb21wYXJhcmVtb3MgZG9zIMOhcmJvbGVzIGRlIGxhIG1pc21hIGVzcGVjaWUgKEc3X1QxIGEgc29sIHkgRzdfVDQgYSBzb21icmEpLCBsbyBxdWUgYcOtc2xhIGVsIGVmZWN0byBkZSBsYSBleHBvc2ljacOzbiBkZWwgZWZlY3RvIGRlIGxhIGVzcGVjaWUuDQoNCiMgTcOpdG9kb3MNCg0KKipEaXNlw7FvLioqIFNlIG1pZGllcm9uIDUgw6FyYm9sZXMgZGVudHJvIGRlIHVuYSBwYXJjZWxhIGVuIExhIEJ1aXRyZXJhOiAzIGEgcGxlbm8gc29sIChHN19UMSwgRzdfVDMsIEc3X1Q1KSB5IDIgYSBsYSBzb21icmEgKEc3X1QyLCBHN19UNCksIGNvbiAxMCBob2phcyBwb3Igw6FyYm9sICg1MCBob2phcyBlbiB0b3RhbCkuIFVuIMOhcmJvbCBlcyBkZSBzb2wgc2kgcmVjaWJlIGx1eiBkaXJlY3RhIGxhIG1heW9yIHBhcnRlIGRlbCBkw61hIHkgbm8gbG8gY3VicmVuIG90cm9zIMOhcmJvbGVzIG5pIGVkaWZpY2lvczsgZW4gY2FzbyBjb250cmFyaW8sIGRlIHNvbWJyYS4gTGFzIGhvamFzIGZ1ZXJvbiBhZHVsdGFzLCBjb21wbGV0YW1lbnRlIGV4cGFuZGlkYXMsIHNpbiBkYcOxbyBldmlkZW50ZSB5IHJlcGFydGlkYXMgcG9yIHRvZGEgbGEgY29wYS4gRzdfVDEgeSBHN19UNCBzb24gZGUgbGEgbWlzbWEgZXNwZWNpZSwgbG8gcXVlIHBlcm1pdGUgdW4gY29udHJhc3RlIHBhcmVhZG8gcG9yIGVzcGVjaWUuDQoNCioqTWVkaWNpw7NuLioqIENhZGEgaG9qYSBzZSB0cmF6w7Mgc29icmUgcGFwZWwgeSBzZSBmb3RvZ3JhZmnDsyBkZW50cm8gZGUgdW4gbWFyY28gcmVjdGFuZ3VsYXIgZGUgbGFkb3MgY29ub2NpZG9zLiBDb21vIGxhcyBob2phcyB2YXJpYWJhbiBlbiB0YW1hw7FvLCBzZSB1c2Fyb24gdHJlcyBtYXJjb3MgZGlzdGludG9zICg5NSDDlyAxOTUgbW0sIDIzNSDDlyAxNTggbW0geSAxMDAgw5cgMTU4IG1tKTsgZWwgc2NyaXB0IGNhbGlicsOzIGNhZGEgZm90byBjb24gZWwgdGFtYcOxbyBkZWwgbWFyY28gY29ycmVzcG9uZGllbnRlIHBhcmEgY29udmVydGlyIHDDrXhlbGVzIGEgY23Csi4gTG9zIGRhdG9zIHNlIGFub3Rhcm9uIGVuIGxhIHBsYW50aWxsYSBjb23Dum46IHVuYSBmaWxhIHBvciBob2phLCBjb24gw6FyYm9sLCBjb29yZGVuYWRhcywgbsO6bWVybyBkZSBob2phLCDDoXJlYSwgZXhwb3NpY2nDs24geSBmZWNoYS4gRWwgbXVlc3RyZW8gc2UgcmVhbGl6w7MgZW4gdW4gZMOtYSBudWJsYWRvIHkgaMO6bWVkbywgY29uZGljacOzbiBxdWUgc2UgYW5vdMOzIHBvcnF1ZSBsYSB0dXJnZW5jaWEgZGUgbGEgaG9qYSBpbmZsdXllIGVuIHN1IHRhbWHDsW8uDQoNCioqQW7DoWxpc2lzKiogKHRvZG8gZW4gUiBiYXNlLCBgciBSLnZlcnNpb24uc3RyaW5nYCk6DQoNCi0gUmV2aXNpw7NuIGRlIGxhIGJhc2UgeSBkZWNpc2lvbmVzIGRvY3VtZW50YWRhcyBzb2JyZSBjYWRhIHByb2JsZW1hIGVuY29udHJhZG8uDQotIFBvciDDoXJib2w6IG4sIG1lZGlhLCBtZWRpYW5hLCBkZXN2aWFjacOzbiBlc3TDoW5kYXIgeSBjb2VmaWNpZW50ZSBkZSB2YXJpYWNpw7NuLg0KLSBHcsOhZmljYXM6IHVuIGRpYWdyYW1hIGRlIGNhamFzIHBvciDDoXJib2wgeSBvdHJvIHBvciBleHBvc2ljacOzbi4NCi0gVmFsb3JlcyBhdMOtcGljb3M6IHVuIGNyaXRlcmlvIGZpam8gKHJlZ2xhIGRlIFR1a2V5IGRlbnRybyBkZSBjYWRhIMOhcmJvbCkgbcOhcyBsYSByZXZpc2nDs24gZGUgbGFzIG9ic2VydmFjaW9uZXMuDQotIENvbXBhcmFjacOzbiBzb2zigJNzb21icmEgY29uIGVsIMOhcmJvbCBjb21vIHVuaWRhZCBkZSBhbsOhbGlzaXM6IHNlIHByb21lZGlhbiBsYXMgMTAgaG9qYXMgZGUgY2FkYSDDoXJib2wgeSBzZSBjb21wYXJhbiBlc29zIHByb21lZGlvcy4NCi0gQU5PVkEgZGUgdW4gZmFjdG9yIGVudHJlIMOhcmJvbGVzLCBjb24gVHVrZXkgSFNEIHBhcmEgaWRlbnRpZmljYXIgcXXDqSDDoXJib2xlcyBkaWZpZXJlbi4NCi0gQU5PVkEgYW5pZGFkbyAoZXhwb3NpY2nDs24gKyDDoXJib2wpLCBxdWUgcHJ1ZWJhIGxhIGV4cG9zaWNpw7NuIGNvbnRyYSBsYSB2YXJpYWNpw7NuIGVudHJlIMOhcmJvbGVzLg0KLSBDb250cmFzdGUgZGUgbWlzbWEgZXNwZWNpZTogRzdfVDEgKHNvbCkgdnMgRzdfVDQgKHNvbWJyYSkuDQoNCmBgYHtyIHJldmlzaW9uLWNhbGN1bG99DQpkYXRvcyA8LSBjcnVkbw0KZGF0b3MkZmlsYSA8LSBzZXFfbGVuKG5yb3coZGF0b3MpKQ0KaWRfbWFsIDwtIHVuaXF1ZShkYXRvcyRpZF9hcmJvbFshZ3JlcGwoIl5HWzAtOV0rX1RbMC05XSskIiwgZGF0b3MkaWRfYXJib2wpXSkNCm5faWRfY29ycmVnaWRvICAgPC0gc3VtKGRhdG9zJGlkX2FyYm9sICE9IHRvdXBwZXIodHJpbXdzKGRhdG9zJGlkX2FyYm9sKSkpDQpuX2V4cG9fY29ycmVnaWRhIDwtIHN1bShkYXRvcyRleHBvc2ljaW9uICE9IHRvbG93ZXIodHJpbXdzKGRhdG9zJGV4cG9zaWNpb24pKSkNCmRhdG9zJGlkX2FyYm9sICAgPC0gdG91cHBlcih0cmltd3MoZGF0b3MkaWRfYXJib2wpKQ0KZGF0b3MkZXhwb3NpY2lvbiA8LSB0b2xvd2VyKHRyaW13cyhkYXRvcyRleHBvc2ljaW9uKSkNCm5fZXhwbyA8LSB0YXBwbHkoZGF0b3MkZXhwb3NpY2lvbiwgZGF0b3MkaWRfYXJib2wsIGZ1bmN0aW9uKHgpIGxlbmd0aCh1bmlxdWUoeCkpKQ0KcmVwZXRpZGEgPC0gZHVwbGljYXRlZChkYXRvc1ssIGMoImlkX2FyYm9sIiwgIm5faG9qYSIpXSkNCm5fcG9yX2FyYm9sIDwtIHRhYmxlKGRhdG9zJGlkX2FyYm9sWyFyZXBldGlkYV0pDQptZWRpYW5hX2FyYm9sIDwtIGF2ZShkYXRvcyRhcmVhX2NtMiwgZGF0b3MkaWRfYXJib2wsIEZVTiA9IGZ1bmN0aW9uKHgpIG1lZGlhbih4WyFpcy5uYSh4KSAmIHggPiAwXSkpDQpkYXRvcyRyYXpvbl9tZWRpYW5hIDwtIGRhdG9zJGFyZWFfY20yIC8gbWVkaWFuYV9hcmJvbA0KZXh0cmVtb3MgPC0gZGF0b3NbIWlzLm5hKGRhdG9zJHJhem9uX21lZGlhbmEpICYgZGF0b3MkYXJlYV9jbTIgPiAwICYgKGRhdG9zJHJhem9uX21lZGlhbmEgPiAxMCB8IGRhdG9zJHJhem9uX21lZGlhbmEgPCAwLjEpLCBdDQoNCmRlY2lkaXIgPC0gZnVuY3Rpb24obiwgb2ssIG1hbCkgaWYgKG4gPT0gMCkgb2sgZWxzZSBtYWwNCg0KcmV2aXNpb24gPC0gZGF0YS5mcmFtZSgNCiAgUmV2aXNpw7NuID0gYygiRm9ybWF0byBkZWwgSUQiLCAiRXhwb3NpY2nDs24gZXNjcml0YSBkZSB2YXJpYXMgZm9ybWFzIiwgIsOBcmJvbCBjb24gbcOhcyBkZSB1bmEgZXhwb3NpY2nDs24iLCAiw4FyZWEgZmFsdGFudGUgbyDiiaQgMCIsICJGaWxhcyByZXBldGlkYXMiLCAiTsO6bWVybyBkZSBob2phIGZ1ZXJhIGRlIHJhbmdvIiwgIsOBcmJvbCBjb24gbWVub3MgZGUgMTAgaG9qYXMiLCAiSG9qYXMgY29uIHZhbG9yZXMgZXh0cmVtb3MiLCAiT2JzZXJ2YWNpb25lcyByZWdpc3RyYWRhcyIpLA0KICBDYXNvcyA9IGMobGVuZ3RoKGlkX21hbCksIG5fZXhwb19jb3JyZWdpZGEsIGxlbmd0aChuYW1lcyhuX2V4cG8pW25fZXhwbyA+IDFdKSwgc3VtKGlzLm5hKGRhdG9zJGFyZWFfY20yKSB8IGRhdG9zJGFyZWFfY20yIDw9IDApLCBzdW0ocmVwZXRpZGEpLCBzdW0oZGF0b3Mkbl9ob2phIDwgMSB8IGRhdG9zJG5faG9qYSA+IDEwKSwgc3VtKG5fcG9yX2FyYm9sICE9IDEwKSwgbnJvdyhleHRyZW1vcyksIHN1bSghaXMubmEoZGF0b3Mkb2JzZXJ2YWNpb25lcykpKSwNCiAgRGVjaXNpw7NuID0gYygiTmluZ3VuYTogY29ycmVjdG8iLCBkZWNpZGlyKG5fZXhwb19jb3JyZWdpZGEsICJOaW5ndW5hOiB5YSBlc3RhYmFuIGVuIG1pbsO6c2N1bGFzIiwgcGFzdGUwKCJOb3JtYWxpemFkbyBhIG1pbsO6c2N1bGFzIGVuICIsIG5fZXhwb19jb3JyZWdpZGEsICIgZmlsYXMiKSksICJOaW5ndW5hOiBjb3JyZWN0byIsICJOaW5ndW5hOiB2w6FsaWRhcyIsICJOaW5ndW5hOiBzaW4gZHVwbGljYWRvcyIsICJOaW5ndW5hOiBlbiByYW5nbyIsICJOaW5ndW5hOiB0b2RhcyB0aWVuZW4gMTAiLCAiTmluZ3VuYTogc2luIGV4dHJlbW9zIiwgIk5pbmd1bmE6IHZhY8OtYSIpLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCmBgYA0KDQojIFJldmlzacOzbiBkZSBjYWxpZGFkDQoNCkFudGVzIGRlIGNhbGN1bGFyIGN1YWxxdWllciBlc3RhZMOtc3RpY28gc2UgcmV2aXPDsyBsYSBiYXNlIGVuIGJ1c2NhIGRlIGVycm9yZXMgY29tdW5lcy4gTGEgdGFibGEgcmVzdW1lIGxvcyByZXN1bHRhZG9zOyBsYSDDum5pY2EgaW50ZXJ2ZW5jacOzbiBuZWNlc2FyaWEgZnVlIG5vcm1hbGl6YXIgbGEgZXhwb3NpY2nDs24gZGUgU29sL1NvbWJyYSBhIHNvbC9zb21icmEuIExhIGJhc2UgcXVlZMOzIGNvbiA1MCBmaWxhcywgNSDDoXJib2xlcyB5IDEgZ3J1cG8uDQoNCmBgYHtyIHJldmlzaW9uLXRhYmxhLCByZXN1bHRzPSdhc2lzJ30NCmNhdChlc3Qoa25pdHI6OmthYmxlKHJldmlzaW9uLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBhbGlnbiA9ICJscmwiLCBjb2wubmFtZXMgPSBjKCJSZXZpc2nDs24iLCAiQ2Fzb3MiLCAiRGVjaXNpw7NuIiksIGNhcHRpb24gPSAiUmVzdW1lbiBkZSBsYSByZXZpc2nDs24gZGUgY2FsaWRhZCBkZSBsYSBiYXNlLiIpKSkNCmBgYA0KDQojIFJlc3VsdGFkb3MgeSBEaXNjdXNpw7NuDQoNCmBgYHtyIGRlc2NyaXB0aXZvcywgcmVzdWx0cz0nYXNpcyd9DQpkYXRvc19vayA8LSBkYXRvc1shaXMubmEoZGF0b3MkYXJlYV9jbTIpICYgZGF0b3MkYXJlYV9jbTIgPiAwLCBdDQpkYXRvc19vayA8LSBkYXRvc19va1shZHVwbGljYXRlZChkYXRvc19va1ssIGMoImlkX2FyYm9sIiwgIm5faG9qYSIpXSksIF0NCmV4cG9fYXJib2wgPC0gdGFwcGx5KGRhdG9zX29rJGV4cG9zaWNpb24sIGRhdG9zX29rJGlkX2FyYm9sLCBmdW5jdGlvbih4KSB1bmlxdWUoeClbMV0pDQoNCmRlc2NyIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShzb3J0KHVuaXF1ZShkYXRvc19vayRpZF9hcmJvbCkpLCBmdW5jdGlvbihpZCkgew0KICB4IDwtIGRhdG9zX29rJGFyZWFfY20yW2RhdG9zX29rJGlkX2FyYm9sID09IGlkXQ0KICBkYXRhLmZyYW1lKMOhcmJvbCA9IGlkLCBleHBvc2ljacOzbiA9IGV4cG9fYXJib2xbW2lkXV0sIG4gPSBsZW5ndGgoeCksIG1lZGlhID0gbWVhbih4KSwgbWVkaWFuYSA9IG1lZGlhbih4KSwgc2QgPSBzZCh4KSwgY3YgPSBjdih4KSwgbWluID0gbWluKHgpLCBtYXggPSBtYXgoeCksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCn0pKQ0KDQpkZXNjcl9mbXQgPC0gZGF0YS5mcmFtZSjDoXJib2wgPSBkZXNjciTDoXJib2wsIGV4cG9zaWNpw7NuID0gZGVzY3IkZXhwb3NpY2nDs24sIG4gPSBkZXNjciRuLCBtZWRpYSA9IGZtdChkZXNjciRtZWRpYSwgMiksIG1lZGlhbmEgPSBmbXQoZGVzY3IkbWVkaWFuYSwgMiksIHNkID0gZm10KGRlc2NyJHNkLCAyKSwgY3YgPSBmbXQoZGVzY3IkY3YsIDEpLCBtaW4gPSBmbXQoZGVzY3IkbWluLCAyKSwgbWF4ID0gZm10KGRlc2NyJG1heCwgMiksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KY2F0KGVzdChrbml0cjo6a2FibGUoZGVzY3JfZm10LCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjb2wubmFtZXMgPSBjKCLDgXJib2wiLCAiRXhwb3NpY2nDs24iLCAibiIsICJNZWRpYSIsICJNZWRpYW5hIiwgIkRFIiwgIkNWICglKSIsICJNw61uIiwgIk3DoXgiKSwgY2FwdGlvbiA9ICJFc3RhZMOtc3RpY29zIGRlc2NyaXB0aXZvcyBkZWwgw6FyZWEgZm9saWFyIChjbcKyKSBwb3Igw6FyYm9sLiIpKSkNCmBgYA0KDQpFbCDDoXJlYSBmb2xpYXIgcHJvbWVkaW8gcG9yIMOhcmJvbCB2YXJpw7MgZW50cmUgMzMsMzUgY23CsiAoRzdfVDUpIHkgODksNTIgY23CsiAoRzdfVDMpLCB1bmEgZGlmZXJlbmNpYSBkZSBtw6FzIGRlIDIsNSB2ZWNlcy4gTG9zIHByb21lZGlvcyBkZSBzb2wgeSBzb21icmEgc2Ugc29sYXBhbiBhbXBsaWFtZW50ZTogZWwgcmFuZ28gZGUgc29sICgzMywzNeKAkzg5LDUyIGNtwrIpIGN1YnJlIGNhc2kgcG9yIGNvbXBsZXRvIGVsIGRlIHNvbWJyYSAoNDQsODXigJM3NCw3MCBjbcKyKSwgeSBsb3Mgw6FyYm9sZXMgZGUgbWF5b3IgeSBtZW5vciBtZWRpYSAoRzdfVDMgeSBHN19UNSkgcGVydGVuZWNlbiBhbWJvcyBhbCBncnVwbyBkZSBzb2wuIExhIGRpc3BlcnNpw7NuIGludGVybmEgKENWKSBvc2NpbMOzIGVudHJlIDE1LDElIChHN19UNSkgeSA1MCw2JSAoRzdfVDMpLCBsbyBxdWUgaW5kaWNhIHF1ZSBlbiBhbGd1bm9zIMOhcmJvbGVzIGxhcyBob2phcyBzb24gYmFzdGFudGUgaG9tb2fDqW5lYXMgeSBlbiBvdHJvcyB2YXLDrWFuIG11Y2hvIGRlIHRhbWHDsW8uIEVzYSBoZXRlcm9nZW5laWRhZCBpbnRlcm5hIGp1c3RpZmljYSB0cmF0YXIgZWwgw6FyYm9sIGNvbW8gdW5pZGFkIGRlIGFuw6FsaXNpcy4NCg0KYGBge3IgZmlndXJhLWNhamFzLCBmaWcud2lkdGg9MTAuNSwgZmlnLmhlaWdodD01LjQsIGZpZy5jYXA9IkZpZ3VyYSAxLiDDgXJlYSBmb2xpYXIgcG9yIMOhcmJvbCAoaXpxdWllcmRhKSB5IHBvciBleHBvc2ljacOzbiAoZGVyZWNoYSkuIFJvbWJvczogbWVkaWE7IGzDrW5lYSBwdW50ZWFkYTogbWVkaWEgZ2VuZXJhbC4ifQ0KZGcgPC0gZGF0b3Nfb2sNCmRnJGV4cG8gPC0gZmFjdG9yKGRnJGV4cG9zaWNpb24sIGxldmVscyA9IGMoInNvbCIsICJzb21icmEiKSkNCmRnJGlkX2FyYm9sX2YgPC0gZmFjdG9yKHN1YigiXkdbMC05XStfIiwgIiIsIGRnJGlkX2FyYm9sKSkNCg0KZXhwb19wb3JfYXJib2wgPC0gYXMuY2hhcmFjdGVyKHRhcHBseShkZyRleHBvc2ljaW9uLCBkZyRpZF9hcmJvbF9mLCBmdW5jdGlvbih4KSB1bmlxdWUoeClbMV0pKQ0KY29sX2ZpbGwgICA8LSB1bm5hbWUoY29sX2V4cG9bZXhwb19wb3JfYXJib2xdKQ0KY29sX2JvcmRlICA8LSB1bm5hbWUoY29sX2V4cG9fb3NjW2V4cG9fcG9yX2FyYm9sXSkNCmlkeCAgICAgICAgPC0gYXMuaW50ZWdlcihkZyRpZF9hcmJvbF9mKQ0KcGNoX2FyYm9sICA8LSBjKDIxLCAyMiwgMjMsIDI0LCAyNSlbaWR4XQ0KeW1heCAgICAgICA8LSBtYXgoZGckYXJlYV9jbTIpICogMS4xMA0KbWVkaWFfZ3JhbCA8LSBtZWFuKGRnJGFyZWFfY20yKQ0KeWxhYl9hcmVhICA8LSBleHByZXNzaW9uKCLDgXJlYSBmb2xpYXIgKGNtIl4yKiIpIikNCg0KcGFyKG1mcm93ID0gYygxLCAyKSwgbWFyID0gYyg0LjYsIDQuOCwgMy40LCAxKSkNCmVzdGlsb19iYXNlKCkNCg0KIyAtLS0gUGFuZWwgaXpxdWllcmRvOiBwb3Igw6FyYm9sIC0tLQ0KYm94cGxvdChhcmVhX2NtMiB+IGlkX2FyYm9sX2YsIGRhdGEgPSBkZywgb3V0bGluZSA9IEZBTFNFLCB5bGltID0gYygwLCB5bWF4KSwgY29sID0gTkEsIGJvcmRlciA9IE5BLA0KICAgICAgICB4bGFiID0gIsOBcmJvbCIsIHlsYWIgPSB5bGFiX2FyZWEsIG1haW4gPSAiVmFyaWFjacOzbiBkZWwgw6FyZWEgZm9saWFyIHBvciDDoXJib2wiKQ0KZ3JpZChueCA9IE5BLCBueSA9IE5VTEwsIGNvbCA9ICJncmV5OTAiLCBsdHkgPSAxKQ0KYWJsaW5lKGggPSBtZWRpYV9ncmFsLCBsdHkgPSAyLCBjb2wgPSAiZ3JleTQ1IikNCnRleHQoMC40NSwgbWVkaWFfZ3JhbCwgIm1lZGlhIGdlbmVyYWwiLCBhZGogPSBjKDAsIC0wLjUpLCBjZXggPSAwLjcsIGNvbCA9ICJncmV5MzUiKQ0KYm94cGxvdChhcmVhX2NtMiB+IGlkX2FyYm9sX2YsIGRhdGEgPSBkZywgb3V0bGluZSA9IEZBTFNFLCBhZGQgPSBUUlVFLCBheGVzID0gRkFMU0UsDQogICAgICAgIGJveHdleCA9IDAuNTUsIGNvbCA9IGFkanVzdGNvbG9yKGNvbF9maWxsLCAwLjQwKSwgYm9yZGVyID0gY29sX2JvcmRlLCBsd2QgPSAxLjYsIG1lZGx3ZCA9IDMpDQpzZXQuc2VlZCgyKQ0KcG9pbnRzKGlkeCArIHJ1bmlmKG5yb3coZGcpLCAtMC4xNywgMC4xNyksIGRnJGFyZWFfY20yLCBwY2ggPSAyMSwNCiAgICAgICBiZyA9IGFkanVzdGNvbG9yKGNvbF9maWxsW2lkeF0sIDAuODUpLCBjb2wgPSAiZ3JleTE1IiwgY2V4ID0gMS4xNSwgbHdkID0gMC41KQ0KcG9pbnRzKHNlcV9sZW4obmxldmVscyhkZyRpZF9hcmJvbF9mKSksIHRhcHBseShkZyRhcmVhX2NtMiwgZGckaWRfYXJib2xfZiwgbWVhbiksDQogICAgICAgcGNoID0gMjMsIGJnID0gIndoaXRlIiwgY29sID0gImdyZXkxMCIsIGNleCA9IDEuNiwgbHdkID0gMS44KQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IGMoIlNvbCIsICJTb21icmEiLCAiTWVkaWEgZGVsIMOhcmJvbCIpLCBwY2ggPSBjKDIxLCAyMSwgMjMpLA0KICAgICAgIHB0LmJnID0gYyh1bm5hbWUoY29sX2V4cG8pLCAid2hpdGUiKSwgY29sID0gYygiZ3JleTE1IiwgImdyZXkxNSIsICJncmV5MTAiKSwNCiAgICAgICBidHkgPSAibiIsIGNleCA9IDAuODUsIHB0LmNleCA9IDEuNCkNCg0KIyAtLS0gUGFuZWwgZGVyZWNobzogcG9yIGV4cG9zaWNpw7NuIC0tLQ0KYm94cGxvdChhcmVhX2NtMiB+IGV4cG8sIGRhdGEgPSBkZywgb3V0bGluZSA9IEZBTFNFLCB5bGltID0gYygwLCB5bWF4KSwgY29sID0gTkEsIGJvcmRlciA9IE5BLA0KICAgICAgICB4bGFiID0gIkV4cG9zaWNpw7NuIiwgeWxhYiA9IHlsYWJfYXJlYSwgbWFpbiA9ICLDgXJlYSBmb2xpYXIgc2Vnw7puIGV4cG9zaWNpw7NuIGEgbGEgbHV6IikNCmdyaWQobnggPSBOQSwgbnkgPSBOVUxMLCBjb2wgPSAiZ3JleTkwIiwgbHR5ID0gMSkNCmJveHBsb3QoYXJlYV9jbTIgfiBleHBvLCBkYXRhID0gZGcsIG91dGxpbmUgPSBGQUxTRSwgYWRkID0gVFJVRSwgYXhlcyA9IEZBTFNFLA0KICAgICAgICBib3h3ZXggPSAwLjUsIGNvbCA9IGFkanVzdGNvbG9yKHVubmFtZShjb2xfZXhwbyksIDAuNDApLCBib3JkZXIgPSB1bm5hbWUoY29sX2V4cG9fb3NjKSwgbHdkID0gMS42LCBtZWRsd2QgPSAzKQ0Kc2V0LnNlZWQoMikNCnBvaW50cyhhcy5pbnRlZ2VyKGRnJGV4cG8pICsgcnVuaWYobnJvdyhkZyksIC0wLjE3LCAwLjE3KSwgZGckYXJlYV9jbTIsIHBjaCA9IHBjaF9hcmJvbCwNCiAgICAgICBiZyA9IGFkanVzdGNvbG9yKHVubmFtZShjb2xfZXhwbylbYXMuaW50ZWdlcihkZyRleHBvKV0sIDAuODUpLCBjb2wgPSAiZ3JleTE1IiwgY2V4ID0gMS4xNSwgbHdkID0gMC41KQ0KcG9pbnRzKDE6MiwgdGFwcGx5KGRnJGFyZWFfY20yLCBkZyRleHBvLCBtZWFuKSwgcGNoID0gMjMsIGJnID0gIndoaXRlIiwgY29sID0gImdyZXkxMCIsIGNleCA9IDEuNiwgbHdkID0gMS44KQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IHBhc3RlKCLDgXJib2wiLCBsZXZlbHMoZGckaWRfYXJib2xfZikpLCBwY2ggPSBjKDIxLCAyMiwgMjMsIDI0LCAyNSksDQogICAgICAgcHQuYmcgPSAiZ3JleTcwIiwgY29sID0gImdyZXkyMCIsIGJ0eSA9ICJuIiwgY2V4ID0gMC44NSwgcHQuY2V4ID0gMS4xKQ0KcGFyKG1mcm93ID0gYygxLCAxKSkNCmBgYA0KDQoqKkRpc3RyaWJ1Y2nDs24gZGVsIMOhcmVhIGZvbGlhci4qKiBFbCBwYW5lbCBpenF1aWVyZG8gKEZpZ3VyYSAxKSBtdWVzdHJhIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbGFzIDEwIGhvamFzIGRlIGNhZGEgw6FyYm9sLCBjb2xvcmVhZGFzIHNlZ8O6biBzdSBleHBvc2ljacOzbi4gTG9zIHB1bnRvcyBpbmRpdmlkdWFsZXMgcmV2ZWxhbiBsYSBkaXNwZXJzacOzbiByZWFsOiBHN19UMyAoc29sKSB5IEc3X1Q1IChzb2wpIG9jdXBhbiBsb3MgZXh0cmVtb3MsIGNvbiBlbCBwcmltZXJvIG1vc3RyYW5kbyBsYXMgaG9qYXMgbcOhcyBncmFuZGVzIHkgZWwgc2VndW5kbyBsYXMgbcOhcyBwZXF1ZcOxYXMgeSBob21vZ8OpbmVhcy4gTG9zIMOhcmJvbGVzIGRlIHNvbWJyYSBzZSB1YmljYW4gZW4gdW5hIGZyYW5qYSBpbnRlcm1lZGlhLiBFbCBwYW5lbCBkZXJlY2hvIGFncnVwYSBsb3MgZGF0b3MgcG9yIGV4cG9zaWNpw7NuOiBsYXMgY2FqYXMgZGUgc29sIHkgc29tYnJhIHNlIHN1cGVycG9uZW4gY2FzaSBwb3IgY29tcGxldG8geSBzdXMgbWVkaWFuYXMgc29uIG11eSBzaW1pbGFyZXMuIEFsIG9ic2VydmFyIGxvcyBzw61tYm9sb3MsIGVzIGV2aWRlbnRlIHF1ZSBsYSBhbHRhIHZhcmlhYmlsaWRhZCBkZWwgZ3J1cG8gc29sIHNlIGRlYmUgYSBsYSBtZXpjbGEgZGUgw6FyYm9sZXMgY29uIGVzdHJhdGVnaWFzIGZvbGlhcmVzIG9wdWVzdGFzIChHN19UMyBjb24gaG9qYXMgbXV5IGdyYW5kZXMgeSBHN19UNSBjb24gaG9qYXMgbXV5IHBlcXVlw7FhcykuIEVzdGUgcGF0csOzbiBhbnRpY2lwYSBlbCByZXN1bHRhZG8gZGVsIGFuw6FsaXNpcyBlc3RhZMOtc3RpY286IGxhIHZhcmlhY2nDs24gZW50cmUgw6FyYm9sZXMgZGUgdW5hIG1pc21hIGV4cG9zaWNpw7NuIGVzIHRhbiBncmFuZGUgcXVlLCBhIG5pdmVsIGRlIGhvamEsIGVsIGVmZWN0byBkZSBsYSBleHBvc2ljacOzbiBxdWVkYSBlbm1hc2NhcmFkby4NCg0KYGBge3IgYXRpcGljb3MsIHJlc3VsdHM9J2FzaXMnfQ0KZXNfYXRpcGljb190dWtleSA8LSBmdW5jdGlvbih4KSB7IHEgPC0gcXVhbnRpbGUoeCwgYygwLjI1LCAwLjc1KSwgbmEucm0gPSBUUlVFKTsgcmljIDwtIHFbMl0gLSBxWzFdOyB4IDwgKHFbMV0gLSAxLjUqcmljKSB8IHggPiAocVsyXSArIDEuNSpyaWMpIH0NCmRhdG9zX29rJGF0aXBpY29fdHVrZXkgPC0gYXZlKGRhdG9zX29rJGFyZWFfY20yLCBkYXRvc19vayRpZF9hcmJvbCwgRlVOID0gZXNfYXRpcGljb190dWtleSkNCmF0aXBpY29zX3Jlc3VtZW4gPC0gYWdncmVnYXRlKGF0aXBpY29fdHVrZXkgfiBpZF9hcmJvbCArIGV4cG9zaWNpb24sIGRhdGEgPSBkYXRvc19vaywgRlVOID0gc3VtKQ0KbmFtZXMoYXRpcGljb3NfcmVzdW1lbilbM10gPC0gIm5fYXRpcGljb3MiDQoNCmNhdCgiPGI+VGFibGEgMy48L2I+IFJlc3VtZW4gZGUgdmFsb3JlcyBhdMOtcGljb3MgcG9yIMOhcmJvbC48YnI+PGJyPlxuIikNCmNhdChlc3Qoa25pdHI6OmthYmxlKGF0aXBpY29zX3Jlc3VtZW4sIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IGMoIsOBcmJvbCIsICJFeHBvc2ljacOzbiIsICJIb2phcyBhdMOtcGljYXMiKSwgY2FwdGlvbiA9ICJEZXRlY2Npw7NuIGRlIGF0w61waWNvczogcmVnbGEgZGUgVHVrZXkgKDEsNSDDlyBSSUMpIGRlbnRybyBkZSBjYWRhIMOhcmJvbC4iKSkpDQppZiAoc3VtKGRhdG9zX29rJGF0aXBpY29fdHVrZXkpID09IDApIGNhdCgiPGJyPjxicj48aT5ObyBzZSBkZXRlY3Rhcm9uIGhvamFzIGF0w61waWNhcyBzZWfDum4gbGEgcmVnbGEgZGUgVHVrZXkuPC9pPjxicj5cbiIpDQpgYGANCg0KKipWYWxvcmVzIGF0w61waWNvcy4qKiBQYXJhIGlkZW50aWZpY2FyIGhvamFzIGNvbiB0YW1hw7FvcyBhbsOzbWFsb3MgZGVudHJvIGRlIGNhZGEgw6FyYm9sLCBzZSBhcGxpY8OzIGxhIHJlZ2xhIGRlIFR1a2V5ICgxLDUgdmVjZXMgZWwgcmFuZ28gaW50ZXJjdWFydMOtbGljbykuIExhIGFwbGljYWNpw7NuIGRlIGVzdGEgcmVnbGEgbm8gZGV0ZWN0w7MgbmluZ3VuYSBob2phIGF0w61waWNhIGVuIGxvcyBjaW5jbyDDoXJib2xlcy4gRXN0byBpbmRpY2EgcXVlIGxhcyAxMCBob2phcyBtZWRpZGFzIHBvciDDoXJib2wgZm9ybWFuIHVuYSBtdWVzdHJhIGludGVybmFtZW50ZSBob21vZ8OpbmVhLiBQb3IgbG8gdGFudG8sIHNlIGNvbnNlcnZhcm9uIGxhcyA1MCBob2phcyBwYXJhIHRvZG9zIGxvcyBhbsOhbGlzaXMgcG9zdGVyaW9yZXMsIHkgbGEgZGlzcGVyc2nDs24gb2JzZXJ2YWRhIGVuIGxhcyBncsOhZmljYXMgc2UgaW50ZXJwcmV0YSBjb21vIHZhcmlhY2nDs24gbmF0dXJhbCBkZW50cm8gZGVsIG1pc21vIMOhcmJvbC4NCg0KYGBge3Igc29sLXNvbWJyYSwgcmVzdWx0cz0nYXNpcyd9DQpwcm9tZWRpb3NfYXJib2wgPC0gYWdncmVnYXRlKGFyZWFfY20yIH4gaWRfYXJib2wgKyBleHBvc2ljaW9uLCBkYXRhID0gZGF0b3Nfb2ssIEZVTiA9IG1lYW4pDQpuYW1lcyhwcm9tZWRpb3NfYXJib2wpWzNdIDwtICJtZWRpYV9hcmVhIg0KY2F0KCI8Yj5UYWJsYSA0LjwvYj4gUHJvbWVkaW8gZGVsIMOhcmVhIGZvbGlhciBwb3Igw6FyYm9sICh1bmlkYWQgZGUgYW7DoWxpc2lzKS48YnI+PGJyPlxuIikNCmNhdChlc3Qoa25pdHI6OmthYmxlKHByb21lZGlvc19hcmJvbCwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gYygiw4FyYm9sIiwgIkV4cG9zaWNpw7NuIiwgIk1lZGlhIGRlbCDDoXJib2wgKGNtwrIpIiksIGNhcHRpb24gPSAiw4FyZWEgZm9saWFyIHByb21lZGlvIHBvciDDoXJib2wuIEVsIG4gZXMgNSAow6FyYm9sZXMpLiIpKSkNCm1vZF9zb2xfc29tYnJhIDwtIGxtKG1lZGlhX2FyZWEgfiBleHBvc2ljaW9uLCBkYXRhID0gcHJvbWVkaW9zX2FyYm9sKQ0KY2F0KCI8YnI+PGJyPjxiPkFOT1ZBIGNvbiBlbCDDoXJib2wgY29tbyB1bmlkYWQgKHNvbCB2cy4gc29tYnJhKTo8L2I+PGJyPjxicj5cbiIpDQpjYXQoZXN0KGtuaXRyOjprYWJsZShmb3JtYXRvX2Fub3ZhKHRhYmxhX2Fub3ZhKG1vZF9zb2xfc29tYnJhKSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiUmVzdWx0YWRvcyBkZWwgQU5PVkEgcGFyYSBsYSBjb21wYXJhY2nDs24gc29sIHZzLiBzb21icmEuIikpKQ0KYGBgDQoNCioqQ29tcGFyYWNpw7NuIHNvbOKAk3NvbWJyYS4qKiBQcm9tZWRpYW5kbyBwcmltZXJvIGxhcyAxMCBob2phcyBkZSBjYWRhIMOhcmJvbCwgbG9zIHRyZXMgw6FyYm9sZXMgZGUgc29sIHR1dmllcm9uIG1lZGlhcyBkZSA0OSwyMywgODksNTIgeSAzMywzNSBjbcKyIChwcm9tZWRpbyBkZWwgZ3J1cG86IDU3LDM3IGNtwrIpLCBtaWVudHJhcyBxdWUgbG9zIGRlIHNvbWJyYSBwcm9tZWRpYXJvbiA0NCw4NSB5IDc0LDcwIGNtwrIgKHByb21lZGlvIGRlbCBncnVwbzogNTksNzcgY23CsikuIEVsIEFOT1ZBIG5vIGVuY29udHLDsyBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyBlbnRyZSBleHBvc2ljaW9uZXMgKEYgPSAwLDAxOyBnbCA9IDEsIDM7IHAgPSAwLDkyNykuIExhIHZhcmlhYmlsaWRhZCBlbnRyZSBsb3Mgw6FyYm9sZXMgZGUgdW5hIG1pc21hIGV4cG9zaWNpw7NuIGVzIHRhbiBncmFuZGUgcXVlIGVsIGVmZWN0byBkZSBsYSBleHBvc2ljacOzbiBxdWVkYSBjb21wbGV0YW1lbnRlIGVubWFzY2FyYWRvIGEgZXN0ZSBuaXZlbC4NCg0KYGBge3IgZmlndXJhLW1lZGlhcywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NC4yLCBmaWcuY2FwPSJGaWd1cmEgMi4gw4FyZWEgZm9saWFyIG1lZGlhIHBvciDDoXJib2wgY29uIGludGVydmFsbyBkZSBjb25maWFuemEgZGVsIDk1ICUuIn0NCmljIDwtIHF0KDAuOTc1LCBkZXNjciRuIC0gMSkgKiBkZXNjciRzZCAvIHNxcnQoZGVzY3IkbikNCm8gIDwtIG9yZGVyKGRlc2NyJG1lZGlhKQ0KZCAgPC0gZGVzY3JbbywgXQ0KaWMgPC0gaWNbb10NCmsgIDwtIHNlcV9sZW4obnJvdyhkKSkNCmNvbF9wdCA8LSB1bm5hbWUoY29sX2V4cG9bZCRleHBvc2ljacOzbl0pDQoNCnBhcihtYXIgPSBjKDQuNiwgNywgMy40LCAxLjUpKQ0KZXN0aWxvX2Jhc2UoKQ0KcGxvdChOQSwgeGxpbSA9IGMoMCwgbWF4KGQkbWVkaWEgKyBpYykgKiAxLjA1KSwgeWxpbSA9IGMoMC41LCBucm93KGQpICsgMC41KSwgeWF4dCA9ICJuIiwNCiAgICAgeGxhYiA9IGV4cHJlc3Npb24oIsOBcmVhIGZvbGlhciBtZWRpYSAoY20iXjIqIikiKSwgeWxhYiA9ICIiLA0KICAgICBtYWluID0gIsOBcmVhIGZvbGlhciBtZWRpYSBwb3Igw6FyYm9sICjCsSBJQyA5NSAlKSIpDQpncmlkKG54ID0gTlVMTCwgbnkgPSBOQSwgY29sID0gImdyZXk5MCIsIGx0eSA9IDEpDQpzZWdtZW50cyhkJG1lZGlhIC0gaWMsIGssIGQkbWVkaWEgKyBpYywgaywgY29sID0gY29sX3B0LCBsd2QgPSAzLjUsIGxlbmQgPSAxKQ0KcG9pbnRzKGQkbWVkaWEsIGssIHBjaCA9IDIxLCBiZyA9IGNvbF9wdCwgY29sID0gIndoaXRlIiwgY2V4ID0gMi4zLCBsd2QgPSAxLjUpDQpheGlzKDIsIGF0ID0gaywgbGFiZWxzID0gcGFzdGUwKGQkw6FyYm9sLCAiICgiLCBkJGV4cG9zaWNpw7NuLCAiKSIpLCBsYXMgPSAxLCB0aWNrID0gRkFMU0UsIGNleC5heGlzID0gMC45KQ0KbGVnZW5kKCJib3R0b21yaWdodCIsIGxlZ2VuZCA9IGMoIlNvbCIsICJTb21icmEiKSwgcGNoID0gMjEsIHB0LmJnID0gdW5uYW1lKGNvbF9leHBvKSwNCiAgICAgICBjb2wgPSAid2hpdGUiLCBidHkgPSAibiIsIHB0LmNleCA9IDEuNiwgY2V4ID0gMC45KQ0KYGBgDQoNCmBgYHtyIGFub3ZhLWFyYm9sZXMsIHJlc3VsdHM9J2FzaXMnfQ0KbW9kX2FyYm9sZXMgPC0gYW92KGFyZWFfY20yIH4gaWRfYXJib2wsIGRhdGEgPSBkYXRvc19vaykNCmNhdCgiPGI+VGFibGEgNS48L2I+IEFOT1ZBIGRlIHVuIGZhY3RvciBwYXJhIGVsIMOhcmVhIGZvbGlhciBlbnRyZSBsb3MgNSDDoXJib2xlcy48YnI+PGJyPlxuIikNCmNhdChlc3Qoa25pdHI6OmthYmxlKGZvcm1hdG9fYW5vdmEodGFibGFfYW5vdmEobW9kX2FyYm9sZXMpKSwgZm9ybWF0ID0gImh0bWwiLCByb3cubmFtZXMgPSBGQUxTRSwgY2FwdGlvbiA9ICJEaWZlcmVuY2lhcyBlbiBlbCDDoXJlYSBmb2xpYXIgZW50cmUgbG9zIGNpbmNvIMOhcmJvbGVzLiIpKSkNCg0KdHVrZXlfYXJib2xlcyA8LSBUdWtleUhTRChtb2RfYXJib2xlcykNCnR1a2V5X2RmIDwtIGFzLmRhdGEuZnJhbWUodHVrZXlfYXJib2xlcyRpZF9hcmJvbCkNCnR1a2V5X2ZtdCA8LSBkYXRhLmZyYW1lKENvbXBhcmFjacOzbiA9IHJvd25hbWVzKHR1a2V5X2RmKSwgRGlmZXJlbmNpYSA9IGZtdCh0dWtleV9kZiRkaWZmLCAyKSwgTMOtbWl0ZV9pbmYgPSBmbXQodHVrZXlfZGYkbHdyLCAyKSwgTMOtbWl0ZV9zdXAgPSBmbXQodHVrZXlfZGYkdXByLCAyKSwgcF92YWxvciA9IGZtdF9wKHR1a2V5X2RmJGBwIGFkamApLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpuYW1lcyh0dWtleV9mbXQpIDwtIGMoIkNvbXBhcmFjacOzbiIsICJEaWZlcmVuY2lhIiwgIkzDrW1pdGUgaW5mLiAoOTUlKSIsICJMw61taXRlIHN1cC4gKDk1JSkiLCAicCBhanVzdGFkbyIpDQpjYXQoIjxicj48YnI+PGI+Q29tcGFyYWNpb25lcyBtw7psdGlwbGVzIGRlIFR1a2V5IEhTRDo8L2I+PGJyPjxicj5cbiIpDQpjYXQoZXN0KGtuaXRyOjprYWJsZSh0dWtleV9mbXQsIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNhcHRpb24gPSAiUHJ1ZWJhIGRlIFR1a2V5IEhTRC4iKSkpDQpgYGANCg0KYGBge3IgZmlndXJhLXR1a2V5LCBmaWcud2lkdGg9OC41LCBmaWcuaGVpZ2h0PTUuMiwgZmlnLmNhcD0iRmlndXJhIDMuIENvbXBhcmFjaW9uZXMgbcO6bHRpcGxlcyBkZSBUdWtleSBIU0QuIEVuIHZlcmRlLCBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyAocCBhanVzdGFkbyA8IDAsMDUpLiJ9DQpkZl90dWtleSA8LSBhcy5kYXRhLmZyYW1lKHR1a2V5X2FyYm9sZXMkaWRfYXJib2wpDQpkZl90dWtleSRjb21wYXJhY2lvbiA8LSBnc3ViKCJHN18iLCAiIiwgcm93bmFtZXMoZGZfdHVrZXkpKQ0KZGZfdHVrZXkkY29tcGFyYWNpb24gPC0gZ3N1YigiLSIsICIgLSAiLCBkZl90dWtleSRjb21wYXJhY2lvbikNCmRmX3R1a2V5IDwtIGRmX3R1a2V5W29yZGVyKGRmX3R1a2V5JGRpZmYpLCBdDQpuX2MgIDwtIG5yb3coZGZfdHVrZXkpDQpzaWcgIDwtIGRmX3R1a2V5JGBwIGFkamAgPCAwLjA1DQpjb2xfc2VnIDwtIGlmZWxzZShzaWcsIGNvbF92ZXJkZSwgImdyZXk2NSIpDQp4X3JuZyA8LSByYW5nZShjKGRmX3R1a2V5JGx3ciwgZGZfdHVrZXkkdXByKSkNCnhfbWF4IDwtIHhfcm5nWzJdICsgZGlmZih4X3JuZykgKiAwLjIyDQoNCnBhcihtYXIgPSBjKDQuOCwgNi41LCAzLjQsIDEuNSkpDQplc3RpbG9fYmFzZSgpDQpwbG90KE5BLCB4bGltID0gYyh4X3JuZ1sxXSwgeF9tYXgpLCB5bGltID0gYygwLjUsIG5fYyArIDAuNSksIHlheHQgPSAibiIsDQogICAgIHhsYWIgPSBleHByZXNzaW9uKCJEaWZlcmVuY2lhIGVuIGVsIMOhcmVhIGZvbGlhciAoY20iXjIqIikiKSwgeWxhYiA9ICIiLA0KICAgICBtYWluID0gIkNvbXBhcmFjaW9uZXMgbcO6bHRpcGxlcyBkZSBUdWtleSBIU0QgKElDIDk1ICUpIikNCmdyaWQobnggPSBOVUxMLCBueSA9IE5BLCBjb2wgPSAiZ3JleTkwIiwgbHR5ID0gMSkNCmFibGluZSh2ID0gMCwgbHR5ID0gMiwgY29sID0gIiNDNjI4MjgiLCBsd2QgPSAyKQ0Kc2VnbWVudHMoZGZfdHVrZXkkbHdyLCAxOm5fYywgZGZfdHVrZXkkdXByLCAxOm5fYywgY29sID0gY29sX3NlZywgbHdkID0gMy41LCBsZW5kID0gMSkNCnBvaW50cyhkZl90dWtleSRkaWZmLCAxOm5fYywgcGNoID0gMjEsIGJnID0gY29sX3NlZywgY29sID0gIndoaXRlIiwgY2V4ID0gMS45LCBsd2QgPSAxLjUpDQp0ZXh0KHhfbWF4LCAxOm5fYywgcGFzdGUwKCJwICIsIGlmZWxzZShkZl90dWtleSRgcCBhZGpgIDwgMC4wMDEsICIiLCAiPSAiKSwgZm10X3AoZGZfdHVrZXkkYHAgYWRqYCkpLA0KICAgICBhZGogPSAxLCBjZXggPSAwLjgsIGNvbCA9IGlmZWxzZShzaWcsIGNvbF92ZXJkZSwgImdyZXk0NSIpLCBmb250ID0gaWZlbHNlKHNpZywgMiwgMSkpDQpheGlzKDIsIGF0ID0gMTpuX2MsIGxhYmVscyA9IGRmX3R1a2V5JGNvbXBhcmFjaW9uLCBsYXMgPSAxLCB0aWNrID0gRkFMU0UsIGNleC5heGlzID0gMC45KQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kID0gYygiU2lnbmlmaWNhdGl2YSIsICJObyBzaWduaWZpY2F0aXZhIiksIHBjaCA9IDIxLA0KICAgICAgIHB0LmJnID0gYyhjb2xfdmVyZGUsICJncmV5NjUiKSwgY29sID0gIndoaXRlIiwgYnR5ID0gIm4iLCBwdC5jZXggPSAxLjUsIGNleCA9IDAuODUpDQpgYGANCg0KKipEaWZlcmVuY2lhcyBlbnRyZSDDoXJib2xlcy4qKiBFbCBBTk9WQSBkZSB1biBmYWN0b3IgcmV2ZWzDsyBkaWZlcmVuY2lhcyBhbHRhbWVudGUgc2lnbmlmaWNhdGl2YXMgZW50cmUgw6FyYm9sZXMgKEYgPSA4LDE5OyBnbCA9IDQsIDQ1OyBwIDwgMCwwMDEpLiBMYSBwcnVlYmEgZGUgVHVrZXkgSFNEIG1vc3Ryw7MgcXVlIEc3X1QzIChzb2wpIHRpZW5lIGhvamFzIHNpZ25pZmljYXRpdmFtZW50ZSBtw6FzIGdyYW5kZXMgcXVlIEc3X1QxIChzb2wpLCBHN19UMiAoc29tYnJhKSB5IEc3X1Q1IChzb2wpLiBQb3Igb3RybyBsYWRvLCBHN19UNSAoc29sKSByZXN1bHTDsyBzaWduaWZpY2F0aXZhbWVudGUgbcOhcyBwZXF1ZcOxbyBxdWUgRzdfVDQgKHNvbWJyYSkuIEVsIHJlc3RvIGRlIGNvbXBhcmFjaW9uZXMgbm8gYWxjYW56w7Mgc2lnbmlmaWNhbmNpYS4gRXN0byBkZW11ZXN0cmEgcXVlIGRvcyDDoXJib2xlcyBkZSBsYSBtaXNtYSBleHBvc2ljacOzbiAoRzdfVDMgeSBHN19UNSkgZGlmaWVyZW4gZW50cmUgc8OtIG11Y2jDrXNpbW8gbcOhcyBxdWUgcmVzcGVjdG8gYSBsb3MgZGUgc29tYnJhLCBwb3IgbG8gcXVlIGxhIGNhdGVnb3LDrWEgInNvbCIgbm8gZXMgdW4gYnVlbiBwcmVkaWN0b3IgZGVsIMOhcmVhIGZvbGlhci4NCg0KYGBge3IgYW5vdmEtYW5pZGFkbywgcmVzdWx0cz0nYXNpcyd9DQptb2RfYW5pZGFkbyA8LSBhb3YoYXJlYV9jbTIgfiBleHBvc2ljaW9uICsgRXJyb3IoaWRfYXJib2wpLCBkYXRhID0gZGF0b3Nfb2spDQp0YWJsYV9hbmlkYWRhIDwtIHN1bW1hcnkobW9kX2FuaWRhZG8pDQpjYXQoIjxiPlRhYmxhIDcuPC9iPiBBTk9WQSBhbmlkYWRvIChleHBvc2ljacOzbiArIMOhcmJvbCkuPGJyPjxicj5cbiIpDQpjYXQoZXN0KGtuaXRyOjprYWJsZShhcy5kYXRhLmZyYW1lKHRhYmxhX2FuaWRhZGEkYEVycm9yOiBpZF9hcmJvbGBbWzFdXSksIGZvcm1hdCA9ICJodG1sIiwgcm93Lm5hbWVzID0gVFJVRSwgY2FwdGlvbiA9ICJSZXN1bHRhZG9zIGRlbCBBTk9WQSBhbmlkYWRvLiIpKSkNCmBgYA0KDQoqKkFOT1ZBIGFuaWRhZG8uKiogVW5hIHZleiBkZXNjb250YWRhIGxhIHZhcmlhY2nDs24gZW50cmUgw6FyYm9sZXMsIGxhIGV4cG9zaWNpw7NuIG5vIHRpZW5lIHVuIGVmZWN0byBzaWduaWZpY2F0aXZvIHNvYnJlIGVsIMOhcmVhIGZvbGlhciAoRiA9IDAsMDE7IGdsID0gMSwgMzsgcCA9IDAsOTI3KS4gTGEgc3VtYSBkZSBjdWFkcmFkb3MgZGUgbGEgZXhwb3NpY2nDs24gZnVlIGRlIGFwZW5hcyA2OSw0NyBmcmVudGUgYSAyMS4yMjMsNzAgZGVsIHJlc2lkdWFsLiBFc3RvIHJlY2hhemEgbGEgaGlww7N0ZXNpcyBpbmljaWFsIHkgc3VnaWVyZSBxdWUgbGEgcmVzcHVlc3RhIHBsw6FzdGljYSBhIGxhIGx1eiBxdWVkYSBzdWJvcmRpbmFkYSBhIG90cm9zIGZhY3RvcmVzIGRlbCBpbmRpdmlkdW8uDQoNCmBgYHtyIG1pc21hLWVzcGVjaWUsIHJlc3VsdHM9J2FzaXMnfQ0KcGFyX2VzcCA8LSBkYXRvc19va1tkYXRvc19vayRpZF9hcmJvbCAlaW4lIGMoIkc3X1QxIiwgIkc3X1Q0IiksIF0NCnJlc3VtZW5fZXNwIDwtIGFnZ3JlZ2F0ZShhcmVhX2NtMiB+IGlkX2FyYm9sICsgZXhwb3NpY2lvbiwgZGF0YSA9IHBhcl9lc3AsIEZVTiA9IGZ1bmN0aW9uKHgpIGMobiA9IGxlbmd0aCh4KSwgbWVkaWEgPSBtZWFuKHgpLCBzZCA9IHNkKHgpKSkNCnJlc3VtZW5fZGYgPC0gZGF0YS5mcmFtZSjDgXJib2wgPSByZXN1bWVuX2VzcCRpZF9hcmJvbCwgRXhwb3NpY2nDs24gPSByZXN1bWVuX2VzcCRleHBvc2ljaW9uLCBuID0gcmVzdW1lbl9lc3AkYXJlYV9jbTJbLCAibiJdLCBNZWRpYSA9IGZtdChyZXN1bWVuX2VzcCRhcmVhX2NtMlssICJtZWRpYSJdLCAyKSwgREUgPSBmbXQocmVzdW1lbl9lc3AkYXJlYV9jbTJbLCAic2QiXSwgMikpDQoNCmNhdCgiPGI+VGFibGEgOC48L2I+IENvbXBhcmFjacOzbiBkZSBsYSBtaXNtYSBlc3BlY2llOiBHN19UMSAoc29sKSB2cy4gRzdfVDQgKHNvbWJyYSkuPGJyPjxicj5cbiIpDQpjYXQoZXN0KGtuaXRyOjprYWJsZShyZXN1bWVuX2RmLCBmb3JtYXQgPSAiaHRtbCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjYXB0aW9uID0gIlByb21lZGlvcyBkZSDDoXJlYSBmb2xpYXIgcGFyYSBsb3MgZG9zIGluZGl2aWR1b3MgZGUgbGEgbWlzbWEgZXNwZWNpZS4iKSkpDQoNCnRfZXNwIDwtIHQudGVzdChhcmVhX2NtMiB+IGlkX2FyYm9sLCBkYXRhID0gcGFyX2VzcCkNCmNhdCgiPGJyPjxicj48Yj5QcnVlYmEgdCBwYXJhIG1pc21hIGVzcGVjaWUgKEc3X1Q0IHZzLiBHN19UMSk6PC9iPjxicj5cbiIpDQpjYXQoc3ByaW50ZigiRGlmZXJlbmNpYSBkZSBtZWRpYXMgKEc3X1Q0IC0gRzdfVDEpOiAlcyBjbcKyPGJyPlxuIiwgZm10KGRpZmYodF9lc3AkZXN0aW1hdGUpLCAyKSkpDQpjYXQoc3ByaW50ZigiSW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBhbCA5NSUlOiBbJXMsICVzXTxicj5cbiIsIGZtdCh0X2VzcCRjb25mLmludFsxXSwgMiksIGZtdCh0X2VzcCRjb25mLmludFsyXSwgMikpKQ0KY2F0KHNwcmludGYoIkVzdGFkw61zdGljbyB0OiAlcywgZ2w6ICVzLCB2YWxvciBwOiAlczxicj5cbiIsIGZtdCh0X2VzcCRzdGF0aXN0aWMsIDIpLCBmbXQodF9lc3AkcGFyYW1ldGVyLCAxKSwgZm10X3AodF9lc3AkcC52YWx1ZSkpKQ0KYGBgDQoNCiMgSW50ZXJwcmV0YWNpw7NuIGRlIHJlc3VsdGFkb3MgZW4gKk1hbmdpZmVyYSBpbmRpY2EqDQoNCkxhIGNvbXBhcmFjacOzbiBlbnRyZSBsb3MgZG9zIGluZGl2aWR1b3MgZGUgKk1hbmdpZmVyYSBpbmRpY2EqIGV2aWRlbmNpw7MgdW5hIGRpZmVyZW5jaWEgZW4gZWwgw6FyZWEgZm9saWFyIHByb21lZGlvLCBzaWVuZG8gc3VwZXJpb3IgZW4gZWwgw6FyYm9sIGRlc2Fycm9sbGFkbyBiYWpvIGNvbmRpY2lvbmVzIGRlIHNvbWJyYSAoNzQsNzAgY23CsikgcmVzcGVjdG8gYWwgaW5kaXZpZHVvIGV4cHVlc3RvIGRpcmVjdGFtZW50ZSBhIGxhIHJhZGlhY2nDs24gc29sYXIgKDQ5LDIzIGNtwrIpLiBFc3RhIGRpZmVyZW5jaWEgcmVwcmVzZW50YSB1biBpbmNyZW1lbnRvIGFwcm94aW1hZG8gZGVsIDUxLDcgJSBlbiBlbCDDoXJlYSBmb2xpYXIgZGVsIGluZGl2aWR1byBkZSBzb21icmEgeSBwcmVzZW50YSB1bmEgdGVuZGVuY2lhIGNvbmNvcmRhbnRlIGNvbiBsYSBoaXDDs3Rlc2lzIHBsYW50ZWFkYS4gRGVzZGUgdW5hIHBlcnNwZWN0aXZhIGZpc2lvbMOzZ2ljYSwgZXN0ZSBjb21wb3J0YW1pZW50byBwb2Ryw61hIHJlbGFjaW9uYXJzZSBjb24gbGEgcGxhc3RpY2lkYWQgZmVub3TDrXBpY2EgZGUgbGFzIGhvamFzIGZyZW50ZSBhIGxhIGRpc3BvbmliaWxpZGFkIGRlIHJhZGlhY2nDs24uDQoNCkxvcyByZXN1bHRhZG9zIG9idGVuaWRvcyBjb2luY2lkZW4gcGFyY2lhbG1lbnRlIGNvbiBpbnZlc3RpZ2FjaW9uZXMgcHJldmlhcyBlbiAqTWFuZ2lmZXJhIGluZGljYSouIFJvbWVyby1Sb21lcm8gZXQgYWwuICgyMDIwKSBlbmNvbnRyYXJvbiBxdWUgbGFzIGhvamFzIGRlc2Fycm9sbGFkYXMgYmFqbyBzb21icmEgcHJlc2VudGFiYW4gdW5hIG1heW9yIMOhcmVhIGZvbGlhciwgbWllbnRyYXMgcXVlIGFxdWVsbGFzIGV4cHVlc3RhcyBhbCBzb2wgbW9zdHJhYmFuIHVuYSBtYXlvciBkZW5zaWRhZCBlc3RvbcOhdGljYS4gRGUgbWFuZXJhIHNpbWlsYXIsIEF6ZXJlZG8gZXQgYWwuICgyMDE3KSBpZGVudGlmaWNhcm9uIHF1ZSBsYXMgaG9qYXMgZXhwdWVzdGFzIGEgbWF5b3IgaXJyYWRpYW5jaWEgcHJlc2VudGFiYW4gdW4gbWF5b3IgZ3Jvc29yIHkgdW5hIG1lbm9yIMOhcmVhIGZvbGlhciBlc3BlY8OtZmljYS4gU2luIGVtYmFyZ28sIENoZWVzbWFuIGV0IGFsLiAoMjAyNSkgZW5jb250cmFyb24gcXVlIGVsIMOhcmVhIGZvbGlhciBpbmRpdmlkdWFsIG5vIHZhcmlhYmEgc2lnbmlmaWNhdGl2YW1lbnRlIGNvbiBsYSBpcnJhZGlhbmNpYSwgbG8gcXVlIGluZGljYSBxdWUgZXN0YXMgcmVzcHVlc3RhcyBwdWVkZW4gZGVwZW5kZXIgZGVsIGN1bHRpdmFyIHkgZGUgbGFzIGNvbmRpY2lvbmVzIGFtYmllbnRhbGVzLg0KDQpFbiBjb25qdW50bywgbGEgZGlmZXJlbmNpYSBvYnNlcnZhZGEgZW50cmUgRzdfVDEgeSBHN19UNCBjb2luY2lkZSBjb24gcGF0cm9uZXMgZGUgdmFyaWFjacOzbiBmb2xpYXIgcHJldmlhbWVudGUgZG9jdW1lbnRhZG9zIHBhcmEgKk0uIGluZGljYSosIHBhcnRpY3VsYXJtZW50ZSBjb24gbGEgdGVuZGVuY2lhIGRlIGxhcyBob2phcyBkZSBzb21icmEgYSBwcmVzZW50YXIgbWF5b3JlcyBzdXBlcmZpY2llcy4gU2luIGVtYmFyZ28sIGRlYmlkbyBhIHF1ZSBsYSBjb21wYXJhY2nDs24gY29tcHJlbmRlIMO6bmljYW1lbnRlIGRvcyBpbmRpdmlkdW9zLCB1bm8gcG9yIGNvbmRpY2nDs24gbHVtw61uaWNhLCBubyBlcyBwb3NpYmxlIGF0cmlidWlyIGV4Y2x1c2l2YW1lbnRlIGEgbGEgcmFkaWFjacOzbiBsYXMgZGlmZXJlbmNpYXMgZW5jb250cmFkYXMuDQoNCiMgTGltaXRhY2lvbmVzIGRlbCBlc3R1ZGlvDQoNCkVsIHByZXNlbnRlIGVzdHVkaW8gcHJlc2VudGEgY2llcnRhcyBsaW1pdGFjaW9uZXMgbWV0b2RvbMOzZ2ljYXMgcXVlIGRlYmVuIHNlciBjb25zaWRlcmFkYXMgYWwgaW50ZXJwcmV0YXIgbG9zIHJlc3VsdGFkb3MuIEVuIHByaW1lciBsdWdhciwgZWwgdGFtYcOxbyBkZSBtdWVzdHJhIGZ1ZSByZWR1Y2lkbywgeWEgcXVlIHNlIGV2YWx1YXJvbiDDum5pY2FtZW50ZSBjaW5jbyDDoXJib2xlcywgZGlzdHJpYnVpZG9zIGVuIHRyZXMgaW5kaXZpZHVvcyBleHB1ZXN0b3MgYWwgc29sIHkgZG9zIGJham8gc29tYnJhLiBFc3RhIGNhbnRpZGFkIGxpbWl0YSBsYSByZXByZXNlbnRhdGl2aWRhZCBkZSBsb3MgZ3J1cG9zIHkgbGEgY2FwYWNpZGFkIHBhcmEgZGV0ZWN0YXIgZGlmZXJlbmNpYXMgYXNvY2lhZGFzIGEgbGEgZXhwb3NpY2nDs24gbHVtw61uaWNhLCBlc3BlY2lhbG1lbnRlIGFudGUgbGEgY29uc2lkZXJhYmxlIHZhcmlhYmlsaWRhZCBvYnNlcnZhZGEgZW50cmUgaW5kaXZpZHVvcyBkZSB1bmEgbWlzbWEgY2F0ZWdvcsOtYS4gQXNpbWlzbW8sIGFsIHRyYXRhcnNlIGRlIHVuIGRpc2XDsW8gb2JzZXJ2YWNpb25hbCwgbG9zIMOhcmJvbGVzIGZ1ZXJvbiBzZWxlY2Npb25hZG9zIHNlZ8O6biBsYXMgY29uZGljaW9uZXMgZGUgbHV6IGVuIGxhcyBxdWUgY3JlY8OtYW4gbmF0dXJhbG1lbnRlLCBzaW4gYXNpZ25hY2nDs24gYWxlYXRvcmlhIG5pIG1hbmlwdWxhY2nDs24gZXhwZXJpbWVudGFsLg0KDQpPdHJhIGxpbWl0YWNpw7NuIGNvcnJlc3BvbmRlIGEgbGEgY2xhc2lmaWNhY2nDs24gY3VhbGl0YXRpdmEgZGUgbGEgZXhwb3NpY2nDs24gbHVtw61uaWNhLiBBdW5xdWUgc2UgZGlmZXJlbmNpYXJvbiDDoXJib2xlcyBkZSBzb2wgeSBzb21icmEgbWVkaWFudGUgY3JpdGVyaW9zIHJlbGFjaW9uYWRvcyBjb24gbGEgcHJlc2VuY2lhIGRlIHJhZGlhY2nDs24gZGlyZWN0YSB5IGNvYmVydHVyYSB2ZWdldGFsLCBubyBzZSByZWFsaXphcm9uIG1lZGljaW9uZXMgY3VhbnRpdGF0aXZhcyBkZSBsYSBpbnRlbnNpZGFkIG8gZHVyYWNpw7NuIGRlIGxhIHJhZGlhY2nDs24gcmVjaWJpZGEuIERlIGlndWFsIG1hbmVyYSwgc2Ugc3VtYW4gcG9zaWJsZXMgZXJyb3JlcyBhc29jaWFkb3MgYWwgdHJhemFkbywgbGEgY2FwdHVyYSBmb3RvZ3LDoWZpY2EsIGxhIGNhbGlicmFjacOzbiBkZSBsYXMgaW3DoWdlbmVzIHkgZWwgcHJvY2VzYW1pZW50byBtZWRpYW50ZSBlbCBzY3JpcHQgdXRpbGl6YWRvIHBhcmEgZXN0aW1hciBlbCDDoXJlYSBmb2xpYXIuDQoNClBvciBvdHJhIHBhcnRlLCBlbCBtdWVzdHJlbyBzZSByZWFsaXrDsyBlbiB1biBzb2xvIGluc3RhbnRlIGRlIG9jdHVicmUgeSBiYWpvIGNvbmRpY2lvbmVzIGFtYmllbnRhbGVzIG51YmxhZGFzIHkgaMO6bWVkYXMuIEVuIGNvbnNlY3VlbmNpYSwgbG9zIHJlc3VsdGFkb3MgcmVwcmVzZW50YW4gbGFzIGNhcmFjdGVyw61zdGljYXMgZm9saWFyZXMgb2JzZXJ2YWRhcyBlbiB1biBtb21lbnRvIGVzcGVjw61maWNvIHkgcG9kcsOtYW4gdmFyaWFyIGVuIGZ1bmNpw7NuIGRlIGxhcyBjb25kaWNpb25lcyBlc3RhY2lvbmFsZXMsIGxhIGRpc3BvbmliaWxpZGFkIGjDrWRyaWNhIHkgZWwgZXN0YWRvIGZpc2lvbMOzZ2ljbyBkZSBsb3Mgw6FyYm9sZXMuIFRhbWJpw6luIGRlYmUgY29uc2lkZXJhcnNlIHF1ZSBubyBzZSBjb250cm9sYXJvbiBlbiBwcmltZXJhIGluc3RhbmNpYSBvdHJvcyBmYWN0b3JlcyBwb3RlbmNpYWxtZW50ZSBpbmZsdXllbnRlcywgY29tbyBsYSBpZGVudGlkYWQgZGUgbGEgZXNwZWNpZSwgbGEgZWRhZCBkZSBsb3MgaW5kaXZpZHVvcywgbGEgZGlzcG9uaWJpbGlkYWQgZGUgbnV0cmllbnRlcyB5IGxhcyBjb25kaWNpb25lcyBwYXJ0aWN1bGFyZXMgZGVsIHN1ZWxvLg0K