Resumen

Contexto y objetivo. Las hojas son los principales órganos captadores de luz y su tamaño condiciona la luz que el árbol puede interceptar. Evaluamos si el área foliar de Bauhinia picta difiere entre árboles a pleno sol y a la sombra en el Bosque Urbano Multicentro (Cali, Valle del Cauca; 987 m s. n. m.), contrastando dos hipótesis opuestas planteadas por los dos autores: H1, el área foliar promedio por árbol es mayor a pleno sol; H2, es mayor en la sombra.

Diseño. Se registraron 60 hojas en 6 árboles (3 de sol y 3 de sombra); el área de cada hoja se obtuvo de su fotografía escalada con un marco rectangular de lados conocidos. Como la exposición es una propiedad del árbol y no de la hoja, la unidad de análisis fue el árbol. Las 60 hojas tienen área medida.

Resultados. Con el árbol como unidad de análisis (3 de sol y 3 de sombra), la razón de áreas sombra/sol fue 1,19 (IC 95 %: 0,61–2,33; p = 0,448). El 68 % de la variación del tamaño de las hojas se debió a diferencias entre árboles (CCI = 0,68; IC 95 %: 0,41–0,93). Un análisis independiente basado en el área del marco de cada hoja dio razón 1,24, IC 95 % 0,67–2,27.

Conclusión. La dirección es la de H2 (hojas algo mayores en sombra), pero el intervalo de confianza incluye la ausencia de efecto: no hay evidencia suficiente ni a favor de H1 ni a favor de H2. Con tan pocos árboles, el diseño tiene una potencia limitada: los resultados son estimaciones preliminares y generadoras de hipótesis, no una confirmación.

6
Árboles
3 sol · 3 sombra
60
Hojas registradas
60 con área medida
1,19
Razón sombra/sol
IC 95 %: [0,61; 2,33]
68 %
Variación entre árboles
CCI (tamaño de la hoja)

Introducción

Bauhinia picta, conocida comúnmente como pata de vaca, es una especie de la familia Fabaceae cultivada en Colombia, México, Panamá, Venezuela y Ecuador. Presenta hojas simples, con lóbulos ovados y acuminados o algo caudados en el ápice, y es semicaducifolia, es decir, pierde parcialmente su follaje durante la época seca. Se utiliza como planta ornamental, como barrera rompevientos y en procesos de restauración ecológica, y su rango altitudinal va desde 0 hasta 2000 m s. n. m.1

Las hojas son los principales órganos captadores de luz solar y el sitio donde ocurre la mayor parte de la fotosíntesis. El tamaño y la forma de una hoja determinan la cantidad de luz que la planta puede interceptar, por lo que el área foliar es un rasgo útil para evaluar cómo responde un árbol a su ambiente lumínico.2,3

En este estudio se buscó responder cómo cambia el área foliar de B. picta según la exposición a la luz (sol o sombra). El trabajo se realizó en el Bosque Urbano Multicentro, ubicado en el área forestal protectora del río Meléndez, comuna 22, Cali, Valle del Cauca, a 987 m s. n. m., donde se comparó el área foliar de árboles expuestos a pleno sol con la de árboles en sombra.

Hipótesis. Cada uno de los dos autores planteó una hipótesis distinta sobre cómo cambia el área foliar promedio por árbol con la luz (H0: no hay diferencia, razón de áreas sombra/sol = 1).

  • H1: mayor área a pleno sol (razón sombra/sol < 1). Uno de los autores propone que el área de la hoja aumenta con una mayor exposición al sol: más radiación aporta más energía para la fotosíntesis y podría favorecer una superficie foliar mayor, en línea con el patrón global en que las hojas grandes predominan en ambientes cálidos, húmedos y soleados.4
  • H2: mayor área en la sombra (razón sombra/sol > 1). El otro autor propone lo contrario: que el área de la hoja aumenta en la sombra, porque con poca luz las plantas suelen desplegar rasgos que favorecen la captura de luz, como láminas más extensas.5,6

Una hoja más grande no siempre significa mayor producción. Con exceso de calor o poca disponibilidad de agua la planta puede reducir su actividad fotosintética, y una lámina mayor engrosa la capa límite de aire y dificulta disipar calor.7,8 Por eso el sentido del efecto no es evidente de antemano y este estudio pone a prueba ambas hipótesis. Además, el verdadero aprovechamiento de la luz depende de cómo se organiza todo el follaje y de las condiciones ambientales que rodean al árbol.

Objetivos.

  • Estimar la razón de áreas sombra/sol con el árbol como unidad experimental y valorar cuál de las dos hipótesis (H1 o H2) respalda mejor.
  • Repartir la variación entre árboles y entre hojas.
  • Comprobar la robustez de la conclusión frente a la prueba empleada, la influencia de árboles individuales y los valores atípicos.
  • Cuantificar qué diferencia podría detectar este diseño.

1 Diseño muestral y datos

1.1 Diseño jerárquico y flujo de medición

La base contiene 60 hojas de 6 árboles de Bauhinia picta (3 de sol y 3 de sombra), con 10–10 hojas por árbol. La exposición se asignó al árbol y las hojas son submuestras (Fig. 1); por eso el árbol es la unidad de análisis. La Tabla 1 resume los árboles de cada exposición.

caja <- function(x, y, w, h, lab, fill = "white", col = "grey25", face = "plain", size = 3.2)
  list(annotate("rect", xmin = x - w/2, xmax = x + w/2, ymin = y - h/2, ymax = y + h/2, fill = fill, colour = col, linewidth = .5),
       annotate("text", x = x, y = y, label = lab, size = size, fontface = face, lineheight = .95))
flecha <- function(x, y, xe, ye) annotate("segment", x = x, xend = xe, y = y, yend = ye, colour = "grey35", linewidth = .5, arrow = arrow(length = unit(2.2, "mm"), type = "closed"))
capa <- list()
cs <- comp[comp$exposicion == "sol", ]; cb <- comp[comp$exposicion == "sombra", ]
pos_arbol <- function(k) if (k == 0) numeric(0) else seq(50, 50 + 6.5 * (k - 1), length.out = k)
alt_txt <- if (length(R$altitud)) paste0(fx(R$altitud[1], 0), " m s. n. m.") else ""
capa <- c(capa, caja(11, 30, 20, 17, paste0("Bosque Urbano\nMulticentro, Cali\n", alt_txt), fill = "#f1f3f4", face = "bold"))
capa <- c(capa, caja(33, 44, 17, 10, paste0("A pleno sol\n(", nrow(cs), " árboles)"), fill = adjustcolor(COL["sol"], .25)),
                 caja(33, 16, 17, 10, paste0("A la sombra\n(", nrow(cb), " árboles)"), fill = adjustcolor(COL["sombra"], .22)))
capa <- c(capa, list(flecha(21, 33, 24.4, 41), flecha(21, 27, 24.4, 19)))
for (ex in list(list(d = cs, y = 44, c = COL["sol"]), list(d = cb, y = 16, c = COL["sombra"]))) {
  if (nrow(ex$d) == 0) next
  xs <- pos_arbol(nrow(ex$d))
  capa <- c(capa, list(flecha(41.8, ex$y, min(xs) - 3.3, ex$y),
    annotate("point", x = xs, y = ex$y, shape = 21, size = 11, fill = ifelse(ex$d$n_medida == 0, "white", ex$c), colour = "grey15", stroke = .7),
    annotate("text", x = xs, y = ex$y, label = ex$d$arbol, size = 3.1, fontface = "bold"),
    annotate("text", x = xs, y = ex$y - 6.4, label = paste0(ex$d$n_medida, "/", ex$d$n_total), size = 2.7, colour = "grey30")))
}
capa <- c(capa, caja(89, 30, 20, 22, "Hojas por árbol\n(unidad de muestreo)\n\ncontorno → marco → foto\n→ área (cm²)", fill = "#f1f3f4"))
capa <- c(capa, list(flecha(77.5, 40, 78.8, 34.5), flecha(77.5, 20, 78.8, 25.5)))
cab <- data.frame(x = c(11, 33, 59, 89), l = c("SITIO", "FACTOR (fijo)", "UNIDAD EXPERIMENTAL: el árbol", "SUBMUESTRA"))
ggplot() + capa + geom_text(data = cab, aes(x, 57, label = l), size = 3, fontface = "bold", colour = "grey20") +
  coord_cartesian(xlim = c(0, 100), ylim = c(4, 60), clip = "off") + theme_void()
**Fig. 1 | Diseño jerárquico del estudio y flujo de medición.** El factor fijo (exposición) se asigna a árboles, que son la unidad experimental; las hojas son submuestras. Círculos: árboles, con el número de hojas con área medida sobre el total. Las áreas se obtienen de la fotografía de cada hoja: un marco rectangular dibujado con regla alrededor de su contorno fija la escala para convertir píxeles a cm² con un script en R. Un círculo vacío indica que el árbol aún no tiene ninguna área medida.

Fig. 1 | Diseño jerárquico del estudio y flujo de medición. El factor fijo (exposición) se asigna a árboles, que son la unidad experimental; las hojas son submuestras. Círculos: árboles, con el número de hojas con área medida sobre el total. Las áreas se obtienen de la fotografía de cada hoja: un marco rectangular dibujado con regla alrededor de su contorno fija la escala para convertir píxeles a cm² con un script en R. Un círculo vacío indica que el árbol aún no tiene ninguna área medida.

car_df <- merge(geo[, c("arbol", "exposicion", "x_m", "y_m")], comp[, c("arbol", "n_total", "n_medida")], by = "arbol")
car_df <- merge(car_df, desc_all[, c("arbol", "media", "cv")], by = "arbol", all.x = TRUE)
car_df <- merge(car_df, aggregate(cbind(marco_cm2, aspecto) ~ arbol, data = datos, FUN = mean), by = "arbol", all.x = TRUE)
car_df$dist <- sqrt(car_df$x_m^2 + car_df$y_m^2)
car_df$expo <- factor(as.character(car_df$exposicion), levels = c("sol", "sombra"), labels = c("A pleno sol", "A la sombra"))
cat(tcap("car", "Características de los árboles según su exposición lumínica",
         "Cada fila resume los árboles de la columna (<i>N</i> = número de árboles); datos como media (DE) y mediana [mín.–máx.]. DE, desviación estándar; CV, coeficiente de variación dentro del árbol; el marco es el rectángulo dibujado alrededor de cada hoja (lado 1 × lado 2); la distancia se mide al centroide de los árboles. Los árboles sin áreas medidas no contribuyen a las filas de área."))
Tabla 1. Características de los árboles según su exposición lumínica
ok_t1 <- FALSE
if (HAS_T1) {
  rc_stats <- function(x, ...) {
    x <- x[is.finite(x)]; n <- length(x)
    if (n == 0) return(c("", "n/d" = ""))
    c("", "Media (DE)" = paste0(fx(mean(x), 1), " (", if (n > 1) fx(sd(x), 1) else "n/d", ")"),
      "Mediana [mín.–máx.]" = paste0(fx(median(x), 1), " [", fx(min(x), 1), "–", fx(max(x), 1), "]"))
  }
  table1::label(car_df$n_total) <- "Hojas registradas por árbol (n)"
  table1::label(car_df$n_medida) <- "Hojas con área medida por árbol (n)"
  table1::label(car_df$media) <- "Área foliar media del árbol (cm²)"
  table1::label(car_df$cv) <- "CV del área dentro del árbol (%)"
  table1::label(car_df$marco_cm2) <- "Área del marco (cm²)"
  table1::label(car_df$aspecto) <- "Relación de aspecto del marco (lado mayor/menor)"
  table1::label(car_df$dist) <- "Distancia al centroide (m)"
  t_car <- tryCatch(table1::table1(~ n_total + n_medida + media + cv + marco_cm2 + aspecto + dist | expo, data = car_df,
                                   overall = "Total", rowlabelhead = "Característica", render.continuous = rc_stats,
                                   render.missing = NULL, topclass = "Rtable1-times"), error = function(e) NULL)
  if (!is.null(t_car)) { t1_out(t_car); ok_t1 <- TRUE }
}
```{=html}
Característica A pleno sol
(N=3)
A la sombra
(N=3)
Total
(N=6)
Hojas registradas por árbol (n)
Media (DE) 10,0 (0,0) 10,0 (0,0) 10,0 (0,0)
Mediana [mín.–máx.] 10,0 [10,0–10,0] 10,0 [10,0–10,0] 10,0 [10,0–10,0]
Hojas con área medida por árbol (n)
Media (DE) 10,0 (0,0) 10,0 (0,0) 10,0 (0,0)
Mediana [mín.–máx.] 10,0 [10,0–10,0] 10,0 [10,0–10,0] 10,0 [10,0–10,0]
Área foliar media del árbol (cm²)
Media (DE) 95,3 (13,9) 117,3 (34,6) 106,3 (26,5)
Mediana [mín.–máx.] 96,1 [81,0–108,7] 123,1 [80,2–148,7] 102,4 [80,2–148,7]
CV del área dentro del árbol (%)
Media (DE) 14,2 (1,8) 17,7 (0,7) 15,9 (2,2)
Mediana [mín.–máx.] 13,3 [13,0–16,2] 17,5 [17,1–18,4] 16,6 [13,0–18,4]
Área del marco (cm²)
Media (DE) 140,4 (21,6) 177,5 (49,8) 158,9 (39,9)
Mediana [mín.–máx.] 139,4 [119,2–162,5] 182,5 [125,5–224,6] 150,9 [119,2–224,6]
Relación de aspecto del marco (lado mayor/menor)
Media (DE) 1,1 (0,0) 1,1 (0,1) 1,1 (0,0)
Mediana [mín.–máx.] 1,1 [1,1–1,1] 1,1 [1,1–1,1] 1,1 [1,1–1,1]
Distancia al centroide (m)
Media (DE) 41,8 (11,3) 76,3 (86,8) 59,0 (58,5)
Mediana [mín.–máx.] 39,4 [31,9–54,1] 43,5 [10,6–174,6] 41,5 [10,6–174,6]

<p class="tnota"><b>Nota.</b> Cada fila resume los árboles de la columna (<i>N</i> = número de árboles); datos como media (DE) y mediana [mín.–máx.]. DE, desviación estándar; CV, coeficiente de variación dentro del árbol; el marco es el rectángulo dibujado alrededor de cada hoja (lado 1 × lado 2); la distancia se mide al centroide de los árboles. Los árboles sin áreas medidas no contribuyen a las filas de área.</p>

``` r
if (!ok_t1) {
  tc <- data.frame(Árbol = car_df$arbol, Exposición = as.character(car_df$exposicion), `Hojas registradas` = car_df$n_total, `Hojas medidas` = car_df$n_medida,
                   `Área media (cm²)` = fx(car_df$media, 1), `CV (%)` = fx(car_df$cv, 1), `Marco (cm²)` = fx(car_df$marco_cm2, 1),
                   `Aspecto` = fx(car_df$aspecto, 2), `Distancia al centroide (m)` = fx(car_df$dist, 0), check.names = FALSE)
  tabla(tc, align = "llrrrrrrr")
}

1.2 Calidad de la base de datos

Ver la descripción de las variables de la base
vars_tab <- data.frame(
  Variable = c("Árbol", "Exposición", "Lado 1 y lado 2", "Área del marco", "Área foliar", "ln(área)", "Cociente área/marco", "Relación de aspecto", "Latitud y longitud", "CCI", "Razón sombra/sol"),
  `Columna o cálculo` = c("arbol (T1, T2…)", "exposicion", "lado_1_mm, lado_2_mm", "lado 1 × lado 2 / 100", "area_real_cm2", "log(área foliar)", "área foliar / área del marco", "lado mayor / lado menor", "latitud, longitud", "ANOVA de un factor sobre ln(área)", "exp(β) del modelo mixto o razón de medias geométricas"),
  Unidad = c("—", "sol / sombra", "mm", "cm²", "cm²", "ln(cm²)", "0–1", "≥ 1", "grados decimales", "0–1", "sin unidad"),
  Descripción = c("Identificador del árbol; es la unidad experimental.", "Condición lumínica del árbol (factor de interés).", "Lados del rectángulo dibujado alrededor de cada hoja.",
                  "Escala de la fotografía y referencia del tamaño de la hoja.", "Área de la hoja obtenida de la fotografía escalada.", "Variable respuesta de la inferencia (el tamaño es multiplicativo).",
                  "Fracción del marco que ocupa la hoja.", "Indicador burdo de la forma de la lámina.", "Posición del árbol.", "Fracción de la varianza que ocurre entre árboles.", "Cociente de áreas de sombra respecto de sol; 1 = sin efecto."),
  check.names = FALSE, stringsAsFactors = FALSE)
cat(tcap("vars", "Variables de la base y su significado", "Las columnas del archivo de datos se normalizan al leerlas (minúsculas, sin tildes)."))
Tabla 2. Variables de la base y su significado
tabla(vars_tab, align = "llll")
VariableColumna o cálculoUnidadDescripción
Árbolarbol (T1, T2…)—Identificador del árbol; es la unidad experimental.
Exposiciónexposicionsol / sombraCondición lumínica del árbol (factor de interés).
Lado 1 y lado 2lado_1_mm, lado_2_mmmmLados del rectángulo dibujado alrededor de cada hoja.
Área del marcolado 1 × lado 2 / 100cm²Escala de la fotografía y referencia del tamaño de la hoja.
Área foliararea_real_cm2cm²Área de la hoja obtenida de la fotografía escalada.
ln(área)log(área foliar)ln(cm²)Variable respuesta de la inferencia (el tamaño es multiplicativo).
Cociente área/marcoárea foliar / área del marco0–1Fracción del marco que ocupa la hoja.
Relación de aspectolado mayor / lado menor≥ 1Indicador burdo de la forma de la lámina.
Latitud y longitudlatitud, longitudgrados decimalesPosición del árbol.
CCIANOVA de un factor sobre ln(área)0–1Fracción de la varianza que ocurre entre árboles.
Razón sombra/solexp(β) del modelo mixto o razón de medias geométricassin unidadCociente de áreas de sombra respecto de sol; 1 = sin efecto.

Nota. Las columnas del archivo de datos se normalizan al leerlas (minúsculas, sin tildes).

cat(tcap("qc", "Revisión de calidad de la base y decisiones tomadas", "Cada problema se resuelve con una regla explícita y reproducible; la fila original se conserva en la base de trabajo."))
Tabla 3. Revisión de calidad de la base y decisiones tomadas
tabla(qc_tab, align = "lll")
VerificaciónResultadoDecisión
Estructura de la base60 filas × 12 columnas; 6 árbolesSe normalizan nombres de columna y tipos
Hojas por árbol10 (protocolo: 10)Se conserva el n real de cada árbol
Áreas en blanco (pendientes)0 de 60 (0,0 %)Se excluyen del análisis primario; se estiman aparte (sensibilidad)
Árboles sin ninguna área medidaningunoSe excluyen del nivel de árbol; se usan en el análisis del marco
Espacios sobrantes en el área24 celdasSe eliminan al leer (strip)
Coordenadas con separador de miles60 filasSe reconstruye el valor decimal (3.379.480 → 3,379480)
Exposición válida y constante por árbol0 valores no reconocidos; 0 inconsistenciasSe verifica; los no válidos se excluirían
Área ≤ 0 o mayor que el marco0 filas (0 corregidas por unidad)Se corrigen si el cociente /100 es plausible; si no, se excluyen
Archivos de foto repetidos0Se eliminan duplicados
Árbol medido dos veces (< umbral de distancia)0 paresSe unificarían bajo un solo árbol
Columnas de la plantilla ausentesgrupo, id_arbol, fecha, observacionesSe advierte; no afecta al análisis

Nota. Cada problema se resuelve con una regla explícita y reproducible; la fila original se conserva en la base de trabajo.

Áreas completas. Todas las hojas tienen área medida (Fig. 2).

dd <- datos
dd$est <- ifelse(dd$estado == "ok", "Medida", ifelse(grepl("corregida", dd$estado), "Corregida (unidad)",
          ifelse(dd$estado == "sin área (pendiente)", "Pendiente", "Excluida")))
dd$arbol_f <- factor(dd$arbol, levels = rev(comp$arbol))
etq <- setNames(paste0(comp$arbol, " · ", comp$exposicion), comp$arbol)
pa <- ggplot(dd, aes(factor(n_hoja, levels = sort(unique(n_hoja))), arbol_f, fill = est)) +
  geom_tile(colour = "white", linewidth = .8) + geom_text(aes(label = ifelse(usar, sprintf("%.0f", area), "")), size = 2.6, colour = "white") +
  scale_fill_manual(values = c("Medida" = "#009E73", "Corregida (unidad)" = "#CC79A7", "Pendiente" = "grey85", "Excluida" = "#D55E00"), name = "Estado de la hoja") +
  scale_y_discrete(labels = function(x) etq[x]) + labs(x = "Hoja (n.º dentro del árbol)", y = "Árbol · exposición") +
  theme(axis.line = element_blank(), axis.ticks = element_blank(), legend.position = "top")
pb <- ggplot(comp, aes(factor(arbol, levels = rev(comp$arbol)), pct, fill = exposicion)) + geom_col(width = .65) +
  geom_text(aes(label = paste0(n_medida, "/", n_total)), hjust = -.15, size = 3) + coord_flip(ylim = c(0, 125)) +
  scale_fill_manual(values = COL) + scale_y_continuous(breaks = c(0, 50, 100)) + labs(x = NULL, y = "Hojas con área medida (%)") +
  theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), legend.position = "top")
pa + pb + plot_layout(widths = c(2.3, 1)) + plot_annotation(tag_levels = "a")
**Fig. 2 | Completitud de la base por hoja y por árbol.** **a**, Mosaico hoja a hoja; los números son el área (cm²) usada en el análisis. **b**, Porcentaje de hojas con área medida por árbol.

Fig. 2 | Completitud de la base por hoja y por árbol. a, Mosaico hoja a hoja; los números son el área (cm²) usada en el análisis. b, Porcentaje de hojas con área medida por árbol.

1.3 Ubicación de los árboles: mapa interactivo

Los árboles están separados entre 11 y 230 m; el más alejado del centroide es T6 (175 m), un detalle relevante porque la posición espacial puede confundirse con la exposición (véase Forma de la hoja y contexto espacial). Haz clic en un marcador para ver la fotografía y los datos del árbol; el control de capas permite cambiar el mapa base y ocultar una exposición.

presentes <- intersect(niveles_expo, unique(sitios$exposicion))
if (HAS_LEAFLET) {
  library(leaflet)
  mapa <- leaflet(height = 480) %>%
    addProviderTiles(providers$Esri.WorldImagery, group = "Satélite") %>%
    addTiles(group = "Calles")
  for (e in presentes) {
    d <- sitios[sitios$exposicion == e, ]
    mapa <- addCircleMarkers(mapa, data = d, lng = ~lon, lat = ~lat, radius = 9, weight = 2,
                             color = "white", fillColor = col_expo[[e]], fillOpacity = 0.95,
                             label = ~id_arbol, popup = ~popup,
                             popupOptions = popupOptions(maxWidth = 260), group = lab_expo[[e]])
  }
  mapa %>%
    addLayersControl(baseGroups = c("Satélite", "Calles"), overlayGroups = unname(lab_expo[presentes]),
                     options = layersControlOptions(collapsed = FALSE)) %>%
    addLegend("bottomright", colors = unname(col_expo[presentes]), labels = unname(lab_expo[presentes]),
              title = "Exposición", opacity = 1) %>%
    addScaleBar("bottomleft")
} else {
  cat("El paquete 'leaflet' no está instalado: se muestra un mapa simple.",
      "Para el mapa interactivo ejecuta install.packages('leaflet').\n")
  plot(sitios$lon, sitios$lat, pch = 21, cex = 3, bg = col_expo[sitios$exposicion],
       asp = 1 / cos(mean(sitios$lat) * pi / 180), xlab = "Longitud (°)", ylab = "Latitud (°)",
       main = "Ubicación de los árboles")
  text(sitios$lon, sitios$lat, sub(".*_", "", sitios$id_arbol), cex = 0.8)
  legend("topright", legend = lab_expo[presentes], pt.bg = col_expo[presentes], pch = 21, bty = "n")
}
Fig. 3 | Mapa interactivo de los árboles muestreados. Cada círculo es un árbol (color = exposición lumínica). Al pulsarlo se muestran su fotografía, el número de hojas registradas, el área foliar media y sus coordenadas (grados decimales).
gm <- merge(geo, desc_all[, c("arbol", "media")], by = "arbol", all.x = TRUE)
rx <- range(gm$x_m); ry <- range(gm$y_m); pad <- 0.12 * max(diff(rx), diff(ry), 60)
pa <- ggplot(gm, aes(x_m, y_m)) +
  geom_point(data = gm[!is.na(gm$media), ], aes(fill = exposicion, size = media), shape = 21, colour = "grey15", stroke = .6) +
  geom_point(data = gm[is.na(gm$media), ], shape = 21, size = 5, fill = "white", colour = "grey15", stroke = .9) +
  geom_text(aes(label = arbol), nudge_y = pad * .55, fontface = "bold", size = 3.2) +
  annotate("segment", x = rx[1] - pad * .5, xend = rx[1] - pad * .5 + 50, y = ry[1] - pad, yend = ry[1] - pad, linewidth = 1) +
  annotate("text", x = rx[1] - pad * .5 + 25, y = ry[1] - pad * 1.5, label = "50 m", size = 3) +
  scale_fill_manual(values = COL, name = "Exposición") + scale_size_continuous(range = c(4.5, 10), name = "Área media (cm²)") +
  coord_equal(xlim = rx + c(-pad, pad), ylim = ry + c(-pad * 2, pad * 1.4)) +
  labs(x = "Este–oeste (m)", y = "Norte–sur (m)") + guides(fill = guide_legend(override.aes = list(size = 5))) +
  theme(legend.box = "vertical", legend.position = "right")
dm <- expand.grid(a = geo$arbol, b = geo$arbol, stringsAsFactors = FALSE)
dm$d <- haversine(geo$lat[match(dm$a, geo$arbol)], geo$lon[match(dm$a, geo$arbol)], geo$lat[match(dm$b, geo$arbol)], geo$lon[match(dm$b, geo$arbol)])
dm$a <- factor(dm$a, levels = geo$arbol); dm$b <- factor(dm$b, levels = rev(geo$arbol))
pb <- ggplot(dm, aes(a, b, fill = d)) + geom_tile(colour = "white") + geom_text(aes(label = ifelse(d == 0, "", fx(d, 0))), size = 2.9) +
  scale_fill_gradient(low = "#f7fbff", high = "#6baed6", guide = "none") + labs(x = NULL, y = NULL) +
  theme(axis.line = element_blank(), axis.ticks = element_blank(), panel.grid = element_blank())
pa + pb + plot_layout(widths = c(1.35, 1)) + plot_annotation(tag_levels = "a")
**Fig. 4 | Posición de los árboles en el bosque urbano.** **a**, Plano local (metros respecto del centroide, a partir de las coordenadas registradas). El tamaño del círculo es proporcional al área media medida; los círculos vacíos son árboles sin áreas medidas. **b**, Distancia entre pares de árboles (m).

Fig. 4 | Posición de los árboles en el bosque urbano. a, Plano local (metros respecto del centroide, a partir de las coordenadas registradas). El tamaño del círculo es proporcional al área media medida; los círculos vacíos son árboles sin áreas medidas. b, Distancia entre pares de árboles (m).

1.4 Fotografías de los árboles

Fotografía de referencia de cada árbol, que documenta su estado, su entorno y su grado de exposición solar. Haz clic en una imagen para ampliarla y usa los botones para filtrar por exposición. Se cargaron 6 fotografías.

fig_html <- vapply(seq_len(nrow(sitios)), function(i) {
  s <- sitios[i, ]
  marco <- if (is.na(s$uri_gal)) paste0('<div class="marco vacio"><span>Foto no disponible<br><code>arbol', s$num, '.jpg</code></span></div>') else
    paste0('<div class="marco"><img src="', s$uri_gal, '" alt="Árbol ', s$id_arbol, ' · ', lab_expo[[s$exposicion]], '" loading="lazy"><span class="badge ', s$exposicion, '">', toupper(s$exposicion), '</span></div>')
  meta <- paste0(s$hojas, " hojas · ", if (is.na(s$media)) "sin áreas medidas" else paste0("área media ", fx(s$media, 1), " cm²"))
  paste0('<figure class="', s$exposicion, '" data-expo="', s$exposicion, '">', marco,
         '<figcaption><b>Árbol ', s$id_arbol, '</b> · ', lab_expo[[s$exposicion]], '<br><span class="meta">', meta, '</span></figcaption></figure>')
}, character(1))
js <- paste0("<script>(function(){var lb=document.getElementById('lb'),im=lb.querySelector('img'),cp=lb.querySelector('.lbcap');",
  "document.querySelectorAll('.galeria .marco img').forEach(function(el){el.addEventListener('click',function(){im.src=el.src;cp.textContent=el.alt;lb.classList.add('on');});});",
  "lb.addEventListener('click',function(){lb.classList.remove('on');});",
  "document.addEventListener('keydown',function(e){if(e.key==='Escape'){lb.classList.remove('on');}});",
  "var bs=document.querySelectorAll('.galeria-filtros button');bs.forEach(function(b){b.addEventListener('click',function(){bs.forEach(function(x){x.classList.remove('on');});b.classList.add('on');var f=b.getAttribute('data-f');",
  "document.querySelectorAll('.galeria figure').forEach(function(fg){fg.classList.toggle('oculto',f!=='todos'&&fg.getAttribute('data-expo')!==f);});});});})();</script>")
# Se devuelve como objeto 'asis' (no con cat): imprimir varios MB de base64 en una sola linea hace que knitr se congele
knitr::asis_output(paste0('\n```{=html}\n',
    '<div class="galeria-filtros"><button class="on" data-f="todos">Todos</button><button data-f="sol">A pleno sol</button><button data-f="sombra">A la sombra</button></div>\n',
    '<div class="galeria">\n', paste(fig_html, collapse = "\n"), '\n</div>\n',
    '<div id="lb" class="lb"><img alt=""><div class="lbcap"></div></div>\n', js, '\n```\n\n'))
Árbol T1 · A la sombraSOMBRA
Árbol T1 · A la sombra
10 hojas · área media 80,2 cm²
Árbol T2 · A pleno solSOL
Árbol T2 · A pleno sol
10 hojas · área media 108,7 cm²
Árbol T3 · A pleno solSOL
Árbol T3 · A pleno sol
10 hojas · área media 81,0 cm²
Árbol T4 · A la sombraSOMBRA
Árbol T4 · A la sombra
10 hojas · área media 123,1 cm²
Árbol T5 · A pleno solSOL
Árbol T5 · A pleno sol
10 hojas · área media 96,1 cm²
Árbol T6 · A la sombraSOMBRA
Árbol T6 · A la sombra
10 hojas · área media 148,7 cm²
Fig. 5 | Fotografías de referencia de los árboles muestreados. Marco superior: exposición lumínica (naranja, pleno sol; azul, sombra). Pie: identificador del árbol, número de hojas registradas y área foliar media.

2 Resultados

2.1 El marco rectangular como indicador del tamaño de la hoja

Cada hoja se trazó dentro de un marco rectangular cuyos lados se midieron con regla, de modo que el área del marco (lado 1 × lado 2) existe para las 60 hojas, incluso cuando el área medida por imagen está pendiente. Entre las 60 hojas con ambas medidas, el área de la hoja fue en promedio el 66,9 % del área del marco (rango 54–73 %), y ambas medidas se relacionan de forma muy estrecha (R² = 0,964; Fig. 6). Al predecir el área de una hoja con su marco, el error típico es de ≈ 5,3 %. El cociente área/marco difirió entre árboles (p = 0,006) y sí entre exposiciones (p = 0,009); el marco no es, por tanto, un indicador neutral respecto de la exposición. Por eso el marco sirve, con cautela, para validar las áreas medidas, detectar errores de unidad y estimar las áreas pendientes.

shp_f <- setNames(rep(c(21, 22, 23, 24, 25), length.out = length(arboles_all)), arboles_all)
if (R$proxy_ok) {
  xr <- range(lim$marco_cm2)
  pa <- ggplot(lim, aes(marco_cm2, area)) +
    geom_abline(slope = 1, intercept = log10(R$fill_mean), linetype = 2, colour = "grey45") +
    geom_smooth(method = "lm", formula = y ~ x, se = TRUE, colour = "black", fill = "grey80", linewidth = .6) +
    geom_point(aes(fill = exposicion, shape = arbol), size = 2.6, colour = "grey15", stroke = .3, alpha = .9) +
    scale_x_log10(breaks = c(50, 100, 150, 250)) + scale_y_log10(breaks = c(40, 80, 120, 200)) +
    scale_fill_manual(values = COL, name = "Exposición") + scale_shape_manual(values = shp_f, name = "Árbol") +
    labs(x = "Área del marco (cm², escala log)", y = "Área de la hoja (cm², escala log)") +
    annotate("text", x = xr[1], y = max(lim$area), hjust = 0, vjust = 1, size = 3.3,
             label = paste0("R² = ", fx(R$px_r2, 3), "\npendiente = ", fx(R$px_b, 2))) +
    guides(fill = guide_legend(override.aes = list(shape = 21)), shape = guide_legend(nrow = 1))
  fr <- lim; fr$arbol_f <- factor(fr$arbol, levels = comp$arbol)
  pb <- ggplot(fr, aes(arbol_f, razon_marco)) +
    geom_jitter(aes(fill = exposicion), width = .12, height = 0, shape = 21, size = 2.2, colour = "grey15", stroke = .3, alpha = .85) +
    stat_summary(fun.data = function(x) data.frame(y = mean(x), ymin = mean(x) - sd(x), ymax = mean(x) + sd(x)), geom = "pointrange", size = .35, colour = "black") +
    geom_hline(yintercept = R$fill_mean, linetype = 2, colour = "grey45") + scale_x_discrete(drop = FALSE) +
    scale_fill_manual(values = COL, guide = "none") + labs(x = NULL, y = "Área / área del marco")
  pa + pb + plot_layout(widths = c(1.15, 1)) + plot_annotation(tag_levels = "a")
}
**Fig. 6 | El área del marco predice el área de la hoja.** **a**, Relación entre el área del marco y el área medida (escala log–log); línea sólida, ajuste por mínimos cuadrados; línea discontinua, proporcionalidad con el cociente medio. **b**, Cociente área/marco por árbol (puntos: hojas; barras: media ± DE).

Fig. 6 | El área del marco predice el área de la hoja. a, Relación entre el área del marco y el área medida (escala log–log); línea sólida, ajuste por mínimos cuadrados; línea discontinua, proporcionalidad con el cociente medio. b, Cociente área/marco por árbol (puntos: hojas; barras: media ± DE).

2.2 Variación entre y dentro de árboles

td <- merge(comp[, c("arbol", "exposicion", "n_medida", "n_total")], desc_all[, c("arbol", "media", "mediana", "de", "cv", "li", "ls", "min", "max", "geom")], by = "arbol", all.x = TRUE)
td <- td[order(as.integer(gsub("\\D", "", td$arbol))), ]
td_out <- data.frame(Árbol = td$arbol, Exposición = td$exposicion, `n (medidas/total)` = paste0(td$n_medida, "/", td$n_total),
                     Media = fx(td$media, 1), Mediana = fx(td$mediana, 1), DE = fx(td$de, 1), `CV (%)` = fx(td$cv, 1),
                     `IC 95 % de la media` = ifelse(is.na(td$li), "n/d", paste0(fx(td$li, 1), "–", fx(td$ls, 1))),
                     `Mín.–máx.` = ifelse(is.na(td$min), "n/d", paste0(fx(td$min, 1), "–", fx(td$max, 1))),
                     `Media geom.` = fx(td$geom, 1), check.names = FALSE, stringsAsFactors = FALSE)
cat(tcap("desc", "Estadísticos descriptivos del área foliar (cm²) por árbol",
         "Cada columna es un árbol (exposición tras el punto); datos de las hojas con área medida. DE, desviación estándar; CV, coeficiente de variación (DE/media); IC, intervalo de confianza <i>t</i> de Student de la media; n/d, no disponible (sin áreas medidas o una sola hoja)."))
Tabla 4. Estadísticos descriptivos del área foliar (cm²) por árbol
ok_t1 <- FALSE
if (HAS_T1) {
  rc_arbol <- function(x, ...) {
    x <- x[is.finite(x)]; n <- length(x)
    if (n == 0) return(c("", "n" = "0", "Media (DE)" = "n/d", "Mediana [mín.–máx.]" = "n/d", "CV (%)" = "n/d", "Media geométrica" = "n/d", "IC 95 % de la media" = "n/d"))
    m <- mean(x); s <- if (n > 1) sd(x) else NA
    ic <- if (n > 1) m + c(-1, 1) * qt(.975, n - 1) * s / sqrt(n) else c(NA, NA)
    c("", "n" = as.character(n), "Media (DE)" = paste0(fx(m, 1), " (", fx(s, 1), ")"),
      "Mediana [mín.–máx.]" = paste0(fx(median(x), 1), " [", fx(min(x), 1), "–", fx(max(x), 1), "]"),
      "CV (%)" = fx(if (n > 1) 100 * s / m else NA, 1), "Media geométrica" = fx(exp(mean(log(x))), 1),
      "IC 95 % de la media" = if (n > 1) paste0(fx(ic[1], 1), "–", fx(ic[2], 1)) else "n/d")
  }
  ld <- lim[, c("area", "arbol")]
  ld$arbol_f <- factor(paste0(ld$arbol, " · ", as.character(lim$exposicion)), levels = paste0(comp$arbol, " · ", comp$exposicion))
  table1::label(ld$area) <- "Área foliar de la hoja (cm²)"
  t_desc <- tryCatch(table1::table1(~ area | arbol_f, data = ld, overall = FALSE, droplevels = FALSE, rowlabelhead = "Variable",
                                    render.continuous = rc_arbol, render.missing = NULL, topclass = "Rtable1-times"), error = function(e) NULL)
  if (!is.null(t_desc)) { t1_out(t_desc); ok_t1 <- TRUE }
}
```{=html}
Variable T1 · sombra
(N=10)
T2 · sol
(N=10)
T3 · sol
(N=10)
T4 · sombra
(N=10)
T5 · sol
(N=10)
T6 · sombra
(N=10)
Área foliar de la hoja (cm²)
n 10 10 10 10 10 10
Media (DE) 80,2 (14,7) 108,7 (14,5) 81,0 (10,5) 123,1 (21,6) 96,1 (15,6) 148,7 (25,4)
Mediana [mín.–máx.] 82,5 [50,8–103,4] 107,3 [92,7–139,0] 76,0 [69,3–97,0] 126,1 [91,1–152,5] 93,8 [73,4–122,4] 142,4 [119,0–191,4]
CV (%) 18,4 13,3 13,0 17,5 16,2 17,1
Media geométrica 78,8 107,9 80,4 121,4 94,9 146,8
IC 95 % de la media 69,7–90,7 98,4–119,1 73,4–88,5 107,7–138,6 84,9–107,2 130,5–166,8

<p class="tnota"><b>Nota.</b> Cada columna es un árbol (exposición tras el punto); datos de las hojas con área medida. DE, desviación estándar; CV, coeficiente de variación (DE/media); IC, intervalo de confianza <i>t</i> de Student de la media; n/d, no disponible (sin áreas medidas o una sola hoja).</p>

``` r
if (!ok_t1) tabla(td_out, align = "llrrrrrrrr")

Las medias de árbol fueron de 80,2 a 148,7 cm² (T1 y T6, respectivamente), y el CV dentro de árbol de 13,0 a 18,4 % (Tabla 4, Fig. 7). Las diferencias entre árboles son comparables o mayores que las que hay entre hojas de un mismo árbol.

lim$arbol_f2 <- factor(lim$arbol, levels = comp$arbol)
vacios <- which(comp$n_medida == 0)
etq2 <- setNames(comp$exposicion, comp$arbol)
pa <- ggplot(lim, aes(arbol_f2, area, fill = exposicion)) +
  geom_boxplot(width = .55, outlier.shape = NA, alpha = .5, colour = "grey25", linewidth = .4) +
  geom_jitter(aes(colour = exposicion), width = .13, height = 0, size = 1.7, alpha = .85) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3, fill = "white", colour = "grey15") +
  scale_x_discrete(drop = FALSE, labels = function(x) paste0(x, "\n", etq2[x])) +
  scale_fill_manual(values = COL, name = "Exposición") + scale_colour_manual(values = COL, guide = "none") + labs(x = NULL, y = "Área foliar (cm²)")
if (length(vacios)) pa <- pa + annotate("text", x = vacios, y = mean(range(lim$area)), label = "sin áreas\nmedidas", size = 3, colour = "grey40")
pb <- ggplot(desc_all[!is.na(desc_all$de), ], aes(media, de)) + geom_smooth(method = "lm", formula = y ~ x, se = FALSE, colour = "grey40", linewidth = .4, linetype = 2) +
  geom_point(aes(fill = exposicion), shape = 21, size = 3.4, colour = "grey15") + geom_text(aes(label = arbol), nudge_y = diff(range(desc_all$de, na.rm = TRUE)) * .1 + .3, size = 3) +
  scale_fill_manual(values = COL, guide = "none") + labs(x = "Media del árbol (cm²)", y = "DE dentro del árbol (cm²)")
pc <- ggplot(desc_all[!is.na(desc_all$de_ln), ], aes(media_ln, de_ln)) + geom_smooth(method = "lm", formula = y ~ x, se = FALSE, colour = "grey40", linewidth = .4, linetype = 2) +
  geom_point(aes(fill = exposicion), shape = 21, size = 3.4, colour = "grey15") +
  scale_fill_manual(values = COL, guide = "none") + labs(x = "Media del área (escala log)", y = "DE del área (escala log)")
dd2 <- desc_all[!is.na(desc_all$de), ]
if (nrow(dd2) >= 3) {
  R$r_orig <- cor(dd2$media, dd2$de); R$r_log <- cor(dd2$media_ln, dd2$de_ln)
  pb <- pb + annotate("text", x = min(dd2$media), y = max(dd2$de), hjust = 0, size = 3.2, label = paste0("r = ", fx(R$r_orig, 2)))
  pc <- pc + annotate("text", x = min(dd2$media_ln), y = max(dd2$de_ln), hjust = 0, size = 3.2, label = paste0("r = ", fx(R$r_log, 2)))
}
pa / (pb | pc) + plot_layout(heights = c(1.25, 1)) + plot_annotation(tag_levels = "a")
**Fig. 7 | Distribución del área foliar por árbol y relación media–dispersión.** **a**, Una caja por árbol (mediana, rango intercuartílico y bigotes de 1,5 × RIC); puntos, hojas; rombos blancos, medias. **b, c**, Desviación estándar frente a la media de cada árbol en la escala original (**b**) y en logaritmos (**c**); la transformación logarítmica estabiliza la varianza si desaparece la dependencia.

Fig. 7 | Distribución del área foliar por árbol y relación media–dispersión. a, Una caja por árbol (mediana, rango intercuartílico y bigotes de 1,5 × RIC); puntos, hojas; rombos blancos, medias. b, c, Desviación estándar frente a la media de cada árbol en la escala original (b) y en logaritmos (c); la transformación logarítmica estabiliza la varianza si desaparece la dependencia.

Entre árboles, la dispersión de las hojas crece con el tamaño medio (r = 0,93) y esa relación pasa a r = 0,06 al usar logaritmos (6 árboles; coeficientes solo descriptivos). Por eso el análisis se hace en escala logarítmica y los efectos se expresan como razones de tamaño.

2.2.1 Cuánta variación hay entre árboles

Los árboles sí difieren entre sí en el tamaño de sus hojas (ANOVA, F(5; 54) = 21,97; p < 0,001). El 68 % de la variación del tamaño se debe a diferencias entre árboles (coeficiente de correlación intraclase, CCI = 0,68; IC 95 %: 0,41–0,93)9 y el resto, a diferencias entre hojas de un mismo árbol (Fig. 8). Es decir, las hojas de un mismo árbol tienden a parecerse entre sí.

if (!is.null(R$icc)) {
  a1 <- R$icc$an; msb <- a1$`Mean Sq`[1]; msw <- a1$`Mean Sq`[2]
  v_t_a <- max((msb - msw) / R$icc$n0, 0); v_e_a <- msw
  vv <- data.frame(modelo = "Solo árbol\n(ANOVA)", comp = c("Entre árboles", "Entre hojas (dentro del árbol)"), v = c(v_t_a, v_e_a))
  if (!is.null(R$mix)) {
    Xm <- lme4::getME(R$mix$m, "X"); vf <- var(as.numeric(Xm %*% lme4::fixef(R$mix$m)))
    vv <- rbind(vv, data.frame(modelo = "Con exposición\n(mixto)", comp = c("Exposición (fija)", "Entre árboles", "Entre hojas (dentro del árbol)"), v = c(vf, R$mix$v_t, R$mix$v_e)))
  }
  vv$pct <- ave(vv$v, vv$modelo, FUN = function(z) 100 * z / sum(z))
  vv$comp <- factor(vv$comp, levels = c("Exposición (fija)", "Entre árboles", "Entre hojas (dentro del árbol)"))
  pa <- ggplot(vv, aes(pct, modelo, fill = comp)) + geom_col(width = .55, colour = "white") +
    geom_text(aes(label = ifelse(pct > 6, paste0(fx(pct, 0), " %"), "")), position = position_stack(vjust = .5), size = 3, colour = "white", fontface = "bold") +
    scale_fill_manual(values = c("Exposición (fija)" = "#E69F00", "Entre árboles" = "#0072B2", "Entre hojas (dentro del árbol)" = "grey70"), name = "Fuente de variación") +
    labs(x = "% de la variación del tamaño de la hoja", y = NULL) + guides(fill = guide_legend(nrow = 2))
  pb <- ggplot(data.frame(x = "CCI", e = R$icc$icc, lo = R$icc$li, hi = R$icc$ls), aes(e, x)) +
    geom_vline(xintercept = c(0, 1), linetype = 3, colour = "grey60") +
    geom_segment(aes(x = lo, xend = hi, y = x, yend = x), linewidth = .8) + geom_point(size = 3.6, shape = 21, fill = "#0072B2") +
    scale_x_continuous(limits = c(min(0, R$icc$li) - .05, 1.02)) + labs(x = "Coeficiente de correlación intraclase", y = NULL) +
    theme(axis.text.y = element_blank(), axis.ticks.y = element_blank())
  pa + pb + plot_layout(widths = c(1.8, 1)) + plot_annotation(tag_levels = "a")
}
**Fig. 8 | Reparto de la variación del tamaño de la hoja.** **a**, Componentes de varianza (porcentaje del total) del modelo solo con árbol (estimadores de ANOVA) y, si está disponible, del modelo mixto con la exposición como efecto fijo.<sup>10</sup> **b**, Coeficiente de correlación intraclase con su intervalo de confianza de 95 %.

Fig. 8 | Reparto de la variación del tamaño de la hoja. a, Componentes de varianza (porcentaje del total) del modelo solo con árbol (estimadores de ANOVA) y, si está disponible, del modelo mixto con la exposición como efecto fijo.10 b, Coeficiente de correlación intraclase con su intervalo de confianza de 95 %.

2.3 Valores atípicos: ¿error de medición u hoja realmente distinta?

Criterio para decidir si una hoja atípica se conserva (dos pasos)

Se aplicó un criterio en dos pasos. Primero, ¿hay una causa de medición (unidad equivocada, área mayor que el marco, trazo dudoso, foto borrosa)? Si la hay, se corrige o se excluye, como en la revisión de calidad (Tabla 3). Segundo, si no hay causa de medición pero la hoja queda fuera de la regla de Tukey de su árbol (Q1 − 1,5·RIC, Q3 + 1,5·RIC) o su z robusto basado en la MAD supera 3,5 en valor absoluto, se considera una hoja realmente distinta: se conserva y se mide cuánto cambia el resultado sin ella (análisis de sensibilidad). Además se examinaron los residuos studentizados y la distancia de Cook del modelo con árbol.

cat(tcap("atip", "Hojas marcadas por algún criterio de atipicidad", "Se evalúan árboles con al menos 4 hojas medidas. <i>z</i> robusto = 0,6745·(x − mediana)/MAD."))
Tabla 5. Hojas marcadas por algún criterio de atipicidad
if (nrow(atip_marcadas) > 0) {
  ta <- data.frame(Árbol = atip_marcadas$arbol, `Hoja (n.º)` = atip_marcadas$n_hoja, `Área (cm²)` = fx(atip_marcadas$area, 1),
                   `z robusto` = fx(atip_marcadas$z_robusto, 2), `Fuera de Tukey` = ifelse(atip_marcadas$fuera_tukey, "sí", "no"),
                   `|z| > 3,5` = ifelse(atip_marcadas$fuera_z, "sí", "no"), `Razón área / mediana del árbol` = fx(atip_marcadas$razon_mediana, 2), check.names = FALSE)
  tabla(ta, align = "lrrrccr")
} else cat("<p><i>Ninguna hoja queda fuera de los criterios en los árboles evaluables.</i></p>\n")
ÁrbolHoja (n.º)Área (cm²)z robustoFuera de Tukey|z| > 3,5Razón área / mediana del árbol
T1550,8-2,55síno0,62

Nota. Se evalúan árboles con al menos 4 hojas medidas. z robusto = 0,6745·(x − mediana)/MAD.

R$txt_atip <- paste0("Con los criterios descritos se marcaron ", R$n_atip, " hojas (", tref("atip"), "). Ninguna tiene una causa de medición evidente (su cociente área/marco está dentro del rango observado, ", fx(R$ratio_ok[1], 2), "–", fx(R$ratio_ok[2], 2), "), por lo que se conservan. Según cómo se resuma cada árbol (media, mediana, etc.), la diferencia sombra − sol va de ",
  fx(R$sens_rango[1], 1), " a ", fx(R$sens_rango[2], 1), " cm² (", fref("atipicos"), "b)",
  if (!is.na(R$sens_rango[1]) && R$sens_rango[1] * R$sens_rango[2] < 0) ": **el signo cambia con el resumen elegido**, así que la conclusión depende de unas pocas hojas." else ": el signo no cambia, así que la conclusión no depende de hojas individuales.")

Con los criterios descritos se marcaron 1 hojas (Tabla 5). Ninguna tiene una causa de medición evidente (su cociente área/marco está dentro del rango observado, 0,54–0,73), por lo que se conservan. Según cómo se resuma cada árbol (media, mediana, etc.), la diferencia sombra − sol va de 22,1 a 24,6 cm² (Fig. 9b): el signo no cambia, así que la conclusión no depende de hojas individuales.

if (nrow(atip) > 0) {
  atip$cls <- ifelse(atip$fuera_tukey | atip$fuera_z, "marcada", "dentro")
  pa <- ggplot(atip, aes(arbol, z_robusto)) + geom_hline(yintercept = c(-3.5, 3.5), linetype = 2, colour = "grey50") + geom_hline(yintercept = 0, colour = "grey85") +
    geom_jitter(aes(fill = cls), width = .12, height = 0, shape = 21, size = 2.6, colour = "grey20") +
    scale_fill_manual(values = c(dentro = "grey80", marcada = "#D55E00"), name = "Clasificación") + labs(x = NULL, y = "z robusto (MAD)")
} else pa <- ggplot() + theme_void() + annotate("text", x = 0, y = 0, label = "Sin árboles evaluables")
sens_tab$Resumen <- factor(sens_tab$Resumen, levels = sens_tab$Resumen[order(sens_tab$dif)])
pb <- ggplot(sens_tab, aes(dif, Resumen)) + geom_vline(xintercept = 0, linetype = 3) +
  geom_segment(aes(x = 0, xend = dif, yend = Resumen), colour = "grey60") + geom_point(size = 3.5, shape = 21, fill = COL["sombra"], colour = "grey15") +
  labs(x = "Sombra − sol (cm²)", y = NULL)
pa + pb + plot_layout(widths = c(1, 1.15)) + plot_annotation(tag_levels = "a")
**Fig. 9 | Detección de hojas atípicas y sensibilidad del resultado.** **a**, *z* robusto de cada hoja respecto de la mediana de su árbol; líneas discontinuas, ±3,5. **b**, Diferencia sombra − sol entre árboles según el estadístico con que se resume cada árbol.

Fig. 9 | Detección de hojas atípicas y sensibilidad del resultado. a, z robusto de cada hoja respecto de la mediana de su árbol; líneas discontinuas, ±3,5. b, Diferencia sombra − sol entre árboles según el estadístico con que se resume cada árbol.

2.4 La unidad de análisis es el árbol

La exposición se asignó al árbol, no a la hoja: las hojas de un mismo árbol comparten suelo, edad, genotipo y luz. Tratarlas como réplicas de la exposición multiplica artificialmente el tamaño de muestra.11 Cuantificamos esa inflación con el efecto de diseño, DEFF = 1 + (m̄ − 1)·CCI, y con el tamaño de muestra efectivo, N/DEFF.

R$deff <- NA; R$neff <- NA
if (!is.null(R$icc)) { mbar <- nrow(limA) / nlevels(limA$arbol_f); R$deff <- 1 + (mbar - 1) * max(R$icc$icc, 0); R$neff <- nrow(limA) / R$deff; R$mbar <- mbar }
filas <- list()
if (!is.null(R$pseudo)) filas[[1]] <- c("Hojas como datos independientes (incorrecto)", R$pseudo$n, fx(R$pseudo$razon, 2), fci(R$pseudo$li, R$pseudo$ls), fp(R$pseudo$p))
filas[[length(filas) + 1]] <- c("Un promedio por árbol (correcto)", paste0(R$n_sol, " + ", R$n_som, " = ", R$n_sol + R$n_som), fx(bA$razon, 2), fci(bA$li, bA$ls), fp(bA$p_welch))
tp <- as.data.frame(do.call(rbind, filas), stringsAsFactors = FALSE)
names(tp) <- c("Estrategia de análisis", "Unidades analizadas (n)", "Razón sombra/sol", "IC 95 %", "Valor de p (Welch)")
cat(tcap("pseudo", "Pseudorreplicación: hojas frente a árboles como unidad de análisis", paste0("Prueba de Welch en escala logarítmica (razón de medias geométricas). Efecto de diseño estimado: ", fx(R$deff, 1), "; tamaño de muestra efectivo ≈ ", fx(R$neff, 1), " hojas independientes de ", nrow(limA), ".")))
Tabla 6. Pseudorreplicación: hojas frente a árboles como unidad de análisis
tabla(tp, align = "lrrrr")
Estrategia de análisisUnidades analizadas (n)Razón sombra/solIC 95 %Valor de p (Welch)
Hojas como datos independientes (incorrecto)601,19[1,04; 1,37]0,011
Un promedio por árbol (correcto)3 + 3 = 61,19[0,61; 2,33]0,448

Nota. Prueba de Welch en escala logarítmica (razón de medias geométricas). Efecto de diseño estimado: 7,1; tamaño de muestra efectivo ≈ 8,5 hojas independientes de 60.

R$txt_pseudo <- if (!is.null(R$pseudo)) paste0("Si las ", R$pseudo$n, " hojas se trataran como datos independientes, el valor de *p* sería ", fp(R$pseudo$p), " (en lugar de ", fp(bA$p_welch), ") y el intervalo parecería más estrecho (", fci(R$pseudo$li, R$pseudo$ls), " frente a ", fci(bA$li, bA$ls),
  "). Esa precisión es ilusoria: como las hojas de un mismo árbol se parecen entre sí (CCI = ", fx(R$icc$icc, 2), "), las ", nrow(limA), " hojas aportan información equivalente a solo unas ", fx(R$neff, 0), " hojas independientes.") else "No hay dos exposiciones con datos suficientes para ilustrar la pseudorreplicación."

Si las 60 hojas se trataran como datos independientes, el valor de p sería 0,011 (en lugar de 0,448) y el intervalo parecería más estrecho ([1,04; 1,37] frente a [0,61; 2,33]). Esa precisión es ilusoria: como las hojas de un mismo árbol se parecen entre sí (CCI = 0,68), las 60 hojas aportan información equivalente a solo unas 8 hojas independientes.

if (nlevels(limA$exposicion) == 2) {
  pa <- ggplot(limA, aes(exposicion, area)) +
    geom_violin(aes(fill = exposicion), alpha = .22, colour = NA, scale = "width") +
    geom_boxplot(width = .14, outlier.shape = NA, fill = "white", colour = "grey25", linewidth = .4) +
    geom_jitter(aes(fill = exposicion, shape = arbol), width = .14, height = 0, size = 2.2, colour = "grey15", stroke = .3, alpha = .85) +
    scale_fill_manual(values = COL, guide = "none") + scale_shape_manual(values = shp_f, name = "Árbol") + labs(x = NULL, y = "Área foliar de la hoja (cm²)")
  ex_sum <- do.call(rbind, lapply(split(arb, droplevels(arb$exposicion)), function(d) {
    n <- nrow(d); m <- mean(d$media); s <- if (n > 1) sd(d$media) else NA; tc <- if (n > 1) qt(.975, n - 1) else NA
    data.frame(exposicion = as.character(d$exposicion[1]), n = n, m = m, li = m - tc * s / sqrt(n), ls = m + tc * s / sqrt(n))
  }))
  ex_sum$exposicion <- factor(ex_sum$exposicion, levels = c("sol", "sombra"))
  pb <- ggplot() +
    geom_segment(data = ex_sum, aes(x = exposicion, xend = exposicion, y = li, yend = ls), linewidth = 1.1, colour = "grey20", na.rm = TRUE) +
    geom_point(data = ex_sum, aes(exposicion, m), shape = 95, size = 14, colour = "grey20") +
    geom_point(data = arb, aes(exposicion, media, fill = exposicion, shape = arbol), size = 4, colour = "grey15", stroke = .5, position = position_nudge(x = .18)) +
    geom_text(data = arb, aes(exposicion, media, label = arbol), nudge_x = .32, size = 3, colour = "grey25") +
    geom_text(data = ex_sum, aes(exposicion, Inf, label = paste0("n = ", n, " árboles")), vjust = 1.6, size = 3.2) +
    scale_fill_manual(values = COL, guide = "none") + scale_shape_manual(values = shp_f, guide = "none") + labs(x = NULL, y = "Área foliar media del árbol (cm²)")
  pa + pb + plot_layout(widths = c(1.2, 1)) + plot_annotation(tag_levels = "a")
}
**Fig. 10 | El contraste sol–sombra: hojas frente a árboles.** **a**, Hojas (descriptivo): cada símbolo es un árbol distinto; las hojas del mismo árbol se agrupan, lo que revela su falta de independencia. **b**, Unidad de análisis correcta: un punto por árbol (media aritmética de sus hojas), con la media de cada exposición y su intervalo de confianza <i>t</i> de 95 % (barra); *n* = número de árboles.

Fig. 10 | El contraste sol–sombra: hojas frente a árboles. a, Hojas (descriptivo): cada símbolo es un árbol distinto; las hojas del mismo árbol se agrupan, lo que revela su falta de independencia. b, Unidad de análisis correcta: un punto por árbol (media aritmética de sus hojas), con la media de cada exposición y su intervalo de confianza t de 95 % (barra); n = número de árboles.

2.5 Inferencia sobre la exposición con el árbol como unidad

Sobre los promedios de árbol se aplicaron seis enfoques complementarios (Tabla 7), que se resumen en la Fig. 12.

Ver los seis enfoques y el tamaño del efecto

Los enfoques fueron: la prueba t de Welch,12 sobre la escala original y sobre la escala logarítmica (que da directamente una razón de medias geométricas); la prueba de Wilcoxon exacta;13 una prueba de permutación exacta que enumera todos los repartimientos posibles de las etiquetas sol/sombra entre los árboles; un bootstrap jerárquico en dos etapas (árboles y luego hojas dentro de árbol);14 el modelo mixto con el árbol como efecto aleatorio, con grados de libertad de Satterthwaite;15–17 y el ANOVA anidado, que prueba la exposición contra la variación entre árboles. El tamaño del efecto se resume con la g de Hedges.18,19

fil <- list()
fil[[1]] <- c("Welch con el promedio por árbol (escala log)", paste0("razón = ", fx(bA$razon, 2)), fci(bA$li, bA$ls), paste0("gl = ", fx(bA$df, 1)), fp(bA$p_welch))
fil[[2]] <- c("Welch sobre área media por árbol (cm²)", if (!is.null(bcm)) paste0("dif. = ", fx(bcm$dif, 1), " cm²") else "n/d", if (!is.null(bcm)) fci(bcm$li, bcm$ls, 1) else "n/d", "", if (!is.null(bcm)) fp(bcm$p) else "n/d")
fil[[3]] <- c("Wilcoxon (exacta)", "—", "—", "", fp(bA$p_wilcox))
fil[[4]] <- c("Permutación exacta de etiquetas", "—", "—", paste0(if (!is.null(bA$perm)) bA$perm$n_rep else "n/d", " repartos; p mínimo = ", R$pmin_txt), fp(bA$p_perm))
fil[[5]] <- c("Bootstrap jerárquico (percentil)", if (!is.null(R$boot)) paste0("razón = ", fx(exp(median(R$boot)), 2)) else "n/d", if (!is.null(R$boot)) fci(R$boot_ci[1], R$boot_ci[2]) else "n/d",
              if (!is.null(R$boot)) paste0("P(razón > 1) = ", fx(R$boot_prob, 2)) else "", "—")
fil[[6]] <- c("Modelo mixto (árbol aleatorio)", if (!is.null(R$mix)) paste0("razón = ", fx(R$mix$razon, 2)) else "no disponible", if (!is.null(R$mix)) fci(R$mix$li, R$mix$ls) else "—",
              if (!is.null(R$mix)) paste0("t = ", fx(R$mix$t, 2), "; gl = ", fx(R$mix$df, 1)) else "", if (!is.null(R$mix)) fp(R$mix$p) else "—")
fil[[7]] <- c("ANOVA anidado (exposición vs. árbol)", "—", "—", if (!is.null(R$nested)) paste0("F(1; ", R$nested$an$Df[2], ") = ", fx(R$nested$Fe, 2)) else "n/d", if (!is.null(R$nested)) fp(R$nested$pe) else "n/d")
fil[[8]] <- c("Tamaño del efecto (g de Hedges, escala log)", paste0("g = ", fx(bA$g, 2)), fci(bA$g_li, bA$g_ls), "", "—")
tb <- as.data.frame(do.call(rbind, fil), stringsAsFactors = FALSE); names(tb) <- c("Método de análisis", "Estimación (sombra respecto de sol)", "IC 95 %", "Estadístico / detalle", "Valor de p")
cat(tcap("bateria", "Comparación sol–sombra con el árbol como unidad (análisis primario: áreas medidas)", paste0("Razones y diferencias son sombra respecto de sol; ", R$n_sol, " árboles de sol y ", R$n_som, " de sombra. El IC del bootstrap es percentil; los demás son <i>t</i> (Welch o Satterthwaite).")))
Tabla 7. Comparación sol–sombra con el árbol como unidad (análisis primario: áreas medidas)
tabla(tb, align = "lrrrr")
Método de análisisEstimación (sombra respecto de sol)IC 95 %Estadístico / detalleValor de p
Welch con el promedio por árbol (escala log)razón = 1,19[0,61; 2,33]gl = 2,80,448
Welch sobre área media por árbol (cm²)dif. = 22,1 cm²[-52,3; 96,4]0,390
Wilcoxon (exacta)——0,700
Permutación exacta de etiquetas——20 repartos; p mínimo = 0,1000,500
Bootstrap jerárquico (percentil)razón = 1,20[0,85; 1,62]P(razón > 1) = 0,84—
Modelo mixto (árbol aleatorio)razón = 1,19[0,68; 2,10]t = 0,88; gl = 4,00,429
ANOVA anidado (exposición vs. árbol)——F(1; 4) = 0,770,429
Tamaño del efecto (g de Hedges, escala log)g = 0,57[-1,08; 2,22]—

Nota. Razones y diferencias son sombra respecto de sol; 3 árboles de sol y 3 de sombra. El IC del bootstrap es percentil; los demás son t (Welch o Satterthwaite).

bt_txt <- if (!is.null(R$boot)) paste0("El bootstrap jerárquico solo dispone de ", R$boot_nuniq, " combinaciones distintas de árboles, por lo que su intervalo describe la inestabilidad del resultado más que una inferencia fiable.") else ""
R$txt_bat <- if (is.na(bA$p_welch)) "Con los árboles disponibles no es posible estimar un contraste inferencial." else paste0(
  "En promedio, las hojas de los árboles de sombra midieron ", fx(R$m_som, 1), " cm² y las de sol, ", fx(R$m_sol, 1), " cm² (diferencia = ", fx(R$dif_cm, 1), " cm²). En razón de tamaños sombra/sol, ", fx(bA$razon, 2), " (IC 95 %: ", fx(bA$li, 2), "–", fx(bA$ls, 2),
  "; ", fpp(bA$p_welch), "; tamaño del efecto *g* de Hedges = ", fx(bA$g, 2), "). ", R$frase_h1, " ",
  if (R$no_alcanza) paste0("Además, con ", R$n_sol, " y ", R$n_som, " árboles solo hay ", bA$perm$n_rep, " repartos posibles de las etiquetas sol/sombra, de modo que el menor valor de *p* que se podría obtener es ", R$pmin_txt, ": **este diseño no puede alcanzar significación al 5 %, sean cuales sean los datos**. ") else
    paste0("La prueba de permutación exacta da ", fpp(bA$p_perm), ". "), bt_txt)

En promedio, las hojas de los árboles de sombra midieron 117,3 cm² y las de sol, 95,3 cm² (diferencia = 22,1 cm²). En razón de tamaños sombra/sol, 1,19 (IC 95 %: 0,61–2,33; p = 0,448; tamaño del efecto g de Hedges = 0,57). La dirección es la de H2 (hojas algo mayores en sombra), pero el intervalo de confianza incluye la ausencia de efecto: no hay evidencia suficiente ni a favor de H1 ni a favor de H2. Además, con 3 y 3 árboles solo hay 20 repartos posibles de las etiquetas sol/sombra, de modo que el menor valor de p que se podría obtener es 0,100: este diseño no puede alcanzar significación al 5 %, sean cuales sean los datos. El bootstrap jerárquico solo dispone de 100 combinaciones distintas de árboles, por lo que su intervalo describe la inestabilidad del resultado más que una inferencia fiable.

pe <- bA$perm
if (!is.null(pe)) {
  dfp <- data.frame(r = exp(pe$d)); dfp$k <- round(dfp$r, 4); dfp$y <- ave(dfp$k, dfp$k, FUN = seq_along)
  ggplot(dfp, aes(r, y)) + geom_vline(xintercept = 1, linetype = 3) + geom_vline(xintercept = exp(pe$obs), colour = COL["sombra"], linewidth = 1) +
    geom_point(size = 4.2, shape = 21, fill = "grey85", colour = "grey30") +
    annotate("text", x = exp(pe$obs), y = max(dfp$y) + .7, label = "observado", colour = COL["sombra"], size = 3.3, hjust = -.1) +
    scale_x_log10() + scale_y_continuous(expand = expansion(add = c(.5, 1))) +
    labs(x = "Razón de medias geométricas sombra/sol (escala log)", y = "Repartos") + theme(axis.text.y = element_blank(), axis.ticks.y = element_blank())
}
**Fig. 11 | Distribución de permutación exacta de la razón sombra/sol.** Cada punto es un reparto posible de las etiquetas *sol* y *sombra* entre los árboles analizados; la línea azul es el reparto observado y la línea punteada, la ausencia de efecto (razón = 1). Si el factor no importara, todos los repartos serían igualmente probables.

Fig. 11 | Distribución de permutación exacta de la razón sombra/sol. Cada punto es un reparto posible de las etiquetas sol y sombra entre los árboles analizados; la línea azul es el reparto observado y la línea punteada, la ausencia de efecto (razón = 1). Si el factor no importara, todos los repartos serían igualmente probables.

fr <- data.frame(label = character(), est = numeric(), lo = numeric(), hi = numeric(), tipo = character(), stringsAsFactors = FALSE)
addf <- function(l, e, lo, hi, t) if (!is.null(e) && length(e) == 1 && !is.na(e)) fr <<- rbind(fr, data.frame(label = l, est = e, lo = lo, hi = hi, tipo = t, stringsAsFactors = FALSE))
addf("A · Welch sobre promedios de árbol", bA$razon, bA$li, bA$ls, "correcto")
if (!is.null(R$mix)) addf("A · Modelo mixto (árbol aleatorio)", R$mix$razon, R$mix$li, R$mix$ls, "correcto")
if (!is.null(R$boot)) addf("A · Bootstrap jerárquico", exp(median(R$boot)), R$boot_ci[1], R$boot_ci[2], "correcto")
addf("B · Marco de todas las hojas", bB$razon, bB$li, bB$ls, "correcto")
if (R$n_imp > 0) addf("C · Medidas + completadas", bC$razon, bC$li, bC$ls, "correcto")
if (!is.null(R$pseudo)) addf("Hojas como réplicas (incorrecto)", R$pseudo$razon, R$pseudo$li, R$pseudo$ls, "incorrecto")
if (nrow(fr) > 0) {
  fr$label <- factor(fr$label, levels = rev(fr$label))
  ggplot(fr, aes(est, label, colour = tipo)) + geom_vline(xintercept = 1, linetype = 2, colour = "grey50") +
    geom_segment(aes(x = lo, xend = hi, yend = label), linewidth = 1, na.rm = TRUE) + geom_point(size = 3.4) +
    scale_colour_manual(values = c(correcto = "#0072B2", incorrecto = "#D55E00"), guide = "none") +
    scale_x_log10(breaks = c(.25, .5, 1, 2, 4, 8)) + labs(x = "Razón de áreas sombra/sol (escala log)", y = NULL)
}
**Fig. 12 | La razón sombra/sol según el método y la base de datos.** Puntos: estimaciones; barras: intervalos de confianza de 95 % (escala logarítmica). **A**, áreas medidas, con el árbol como unidad; **B**, área del marco de las hojas; **C** (solo si hubo áreas pendientes), áreas medidas más las pendientes completadas con el modelo del marco. En rojo, el análisis con hojas como réplicas (incorrecto). Una razón de 1 significa ausencia de efecto.

Fig. 12 | La razón sombra/sol según el método y la base de datos. Puntos: estimaciones; barras: intervalos de confianza de 95 % (escala logarítmica). A, áreas medidas, con el árbol como unidad; B, área del marco de las hojas; C (solo si hubo áreas pendientes), áreas medidas más las pendientes completadas con el modelo del marco. En rojo, el análisis con hojas como réplicas (incorrecto). Una razón de 1 significa ausencia de efecto.

2.6 Modelo mixto y ANOVA anidado

El modelo mixto compara la exposición usando todas las hojas, pero respetando que cada hoja pertenece a un árbol: el tamaño de la hoja depende de la exposición (efecto fijo) y de un efecto propio de cada árbol (efecto aleatorio). Es el equivalente moderno del ANOVA anidado y, con datos desbalanceados (distinto número de hojas por árbol, como aquí), es preferible.

if (!is.null(R$mix)) {
  mx <- R$mix
  t1 <- data.frame(
    Medida = c("Razón de áreas sombra/sol", "Variación explicada por la exposición", "Variación debida a diferencias entre árboles", "Variación entre hojas del mismo árbol", "¿Difieren los árboles entre sí?"),
    Valor = c(paste0(fx(mx$razon, 2), " ", fci(mx$li, mx$ls), "; ", gsub("\\*", "", fpp(mx$p))),
              paste0(fx(100 * mx$r2m, 0), " %"), paste0(fx(100 * (mx$r2c - mx$r2m), 0), " %"), paste0(fx(100 * (1 - mx$r2c), 0), " %"),
              gsub("\\*", "", fpp(mx$p_ranef))),
    `Qué significa` = c("Cuántas veces es mayor (> 1) o menor (< 1) la hoja de sombra respecto de la de sol; 1 = sin diferencia. Entre corchetes, IC 95 %.",
                        "Parte de la variación total del tamaño de las hojas que se explica solo por sol o sombra.",
                        "Parte de la variación total debida a que unos árboles tienen hojas más grandes que otros, además de lo que explica la exposición.",
                        "Parte de la variación total que corresponde a diferencias entre hojas de un mismo árbol.",
                        paste0("Prueba de que la variación entre árboles es mayor que cero.", ifelse(mx$singular, " Ajuste singular: la variación entre árboles estimada es ≈ 0.", ""))),
    check.names = FALSE, stringsAsFactors = FALSE)
  cat(tcap("mixto", "Modelo mixto: razón sombra/sol y reparto de la variación del tamaño de la hoja", "Estimado con todas las hojas y el árbol como efecto aleatorio (REML; gl de Satterthwaite). El modelo se ajusta en escala logarítmica, pero aquí la razón se expresa en la escala original. Los tres porcentajes suman 100 % (salvo redondeo)."))
  tabla(t1, align = "lll")
} else cat("<p><i>Modelo mixto no disponible (faltan paquetes o árboles).</i></p>")
Tabla 8. Modelo mixto: razón sombra/sol y reparto de la variación del tamaño de la hoja
MedidaValorQué significa
Razón de áreas sombra/sol1,19 [0,68; 2,10]; p = 0,429Cuántas veces es mayor (> 1) o menor (< 1) la hoja de sombra respecto de la de sol; 1 = sin diferencia. Entre corchetes, IC 95 %.
Variación explicada por la exposición9 %Parte de la variación total del tamaño de las hojas que se explica solo por sol o sombra.
Variación debida a diferencias entre árboles63 %Parte de la variación total debida a que unos árboles tienen hojas más grandes que otros, además de lo que explica la exposición.
Variación entre hojas del mismo árbol29 %Parte de la variación total que corresponde a diferencias entre hojas de un mismo árbol.
¿Difieren los árboles entre sí?p < 0,001Prueba de que la variación entre árboles es mayor que cero.

Nota. Estimado con todas las hojas y el árbol como efecto aleatorio (REML; gl de Satterthwaite). El modelo se ajusta en escala logarítmica, pero aquí la razón se expresa en la escala original. Los tres porcentajes suman 100 % (salvo redondeo).

if (!is.null(R$nested)) {
  an <- R$nested$an
  t2 <- data.frame(`Fuente de variación` = c("Exposición", "Árbol (dentro de exposición)", "Hojas (residual)"), `gl` = an$Df, `Suma de cuadrados` = fx(an$`Sum Sq`, 3), `Cuadrado medio` = fx(an$`Mean Sq`, 3),
                   `Se prueba contra` = c("CM de árbol", "CM de hojas", ""), `F` = c(fx(R$nested$Fe, 2), fx(R$nested$Fa, 2), ""), `Valor de p` = c(fp(R$nested$pe), fp(R$nested$pa), ""), check.names = FALSE, stringsAsFactors = FALSE)
  cat(tcap("anova", "ANOVA anidado: hojas dentro de árboles dentro de exposición", "Análisis en escala logarítmica. La exposición se prueba contra el cuadrado medio de árbol, que es su error experimental correcto. Con número desigual de hojas por árbol la partición secuencial es aproximada; el modelo mixto es la referencia."))
  tabla(t2, align = "lrrrlrr")
  R$txt_nested <- paste0("El ANOVA anidado da el mismo mensaje: la exposición ", ifelse(R$nested$pe < 0.05, "tiene un efecto detectable", "no tiene un efecto detectable"), " (*F*(1; ", an$Df[2], ") = ", fx(R$nested$Fe, 2), "; ", fpp(R$nested$pe), ") y los árboles de una misma exposición ",
                         ifelse(R$nested$pa < 0.05, "sí difieren entre sí", "no difieren de forma detectable"), " (", fpp(R$nested$pa), "). ")
} else { cat("<p><i>ANOVA anidado no disponible (se requieren al menos 3 árboles y las dos exposiciones).</i></p>"); R$txt_nested <- "" }
Tabla 9. ANOVA anidado: hojas dentro de árboles dentro de exposición
Fuente de variaciónglSuma de cuadradosCuadrado medioSe prueba contraFValor de p
Exposición10,4760,476CM de árbol0,770,429
Árbol (dentro de exposición)42,4640,616CM de hojas23,02< 0,001
Hojas (residual)541,4450,027

Nota. Análisis en escala logarítmica. La exposición se prueba contra el cuadrado medio de árbol, que es su error experimental correcto. Con número desigual de hojas por árbol la partición secuencial es aproximada; el modelo mixto es la referencia.

R$txt_mix <- if (!is.null(R$mix)) paste0("El modelo mixto estima una razón sombra/sol de ", fx(R$mix$razon, 2), " (IC 95 %: ", fx(R$mix$li, 2), "–", fx(R$mix$ls, 2), "; ", fpp(R$mix$p),
  "). La exposición explica solo el ", fx(100 * R$mix$r2m, 0), " % de la variación del tamaño de las hojas; las diferencias entre árboles, el ", fx(100 * (R$mix$r2c - R$mix$r2m), 0), " %; y el ", fx(100 * (1 - R$mix$r2c), 0), " % restante corresponde a diferencias entre hojas del mismo árbol (", tref("mixto"), "). ") else ""

El modelo mixto estima una razón sombra/sol de 1,19 (IC 95 %: 0,68–2,10; p = 0,429). La exposición explica solo el 9 % de la variación del tamaño de las hojas; las diferencias entre árboles, el 63 %; y el 29 % restante corresponde a diferencias entre hojas del mismo árbol (Tabla 8). El ANOVA anidado da el mismo mensaje: la exposición no tiene un efecto detectable (F(1; 4) = 0,77; p = 0,429) y los árboles de una misma exposición sí difieren entre sí (p < 0,001). Como la exposición se asignó a árboles y no a hojas, el contraste depende del número de árboles; por eso los intervalos son anchos aunque haya muchas hojas. A continuación se revisan los supuestos del modelo (Fig. 13).

mm <- NULL
if (!is.null(R$mix)) mm <- R$mix$m else if (exists("m_nest")) mm <- m_nest
if (!is.null(mm)) {
  dd3 <- data.frame(e = as.numeric(resid(mm)), f = as.numeric(fitted(mm)), arbol = limA$arbol, expo = limA$exposicion)
  p1 <- ggplot(dd3, aes(f, e)) + geom_hline(yintercept = 0, linetype = 2) + geom_point(aes(fill = expo), shape = 21, size = 2.2, colour = "grey20", alpha = .85) +
    scale_fill_manual(values = COL, guide = "none") + labs(x = "Valor ajustado", y = "Residuo")
  p2 <- ggplot(dd3, aes(sample = e)) + stat_qq_line(colour = "grey40") + stat_qq(size = 1.8, alpha = .8) + labs(x = "Cuantiles teóricos", y = "Cuantiles de los residuos")
  p1 + p2 + plot_annotation(tag_levels = "a")
}
**Fig. 13 | Diagnóstico del modelo.** **a**, Residuos frente a valores ajustados: no debería verse ningún patrón. **b**, Gráfico cuantil–cuantil de los residuos: los puntos deberían seguir la línea. Los residuos del modelo mixto son los condicionales.

Fig. 13 | Diagnóstico del modelo. a, Residuos frente a valores ajustados: no debería verse ningún patrón. b, Gráfico cuantil–cuantil de los residuos: los puntos deberían seguir la línea. Los residuos del modelo mixto son los condicionales.

En el diagnóstico del modelo (Fig. 13) los residuos son compatibles con una distribución normal (Shapiro–Wilk, p = 0,408)20 y la variación es similar entre árboles (Fligner–Killeen, p = 0,814)21. Las pruebas que no dependen de esos supuestos (ANOVA de Welch y Kruskal–Wallis)12,22 llevan a la misma conclusión que el ANOVA (p < 0,001 y p < 0,001, respectivamente). Con pocas hojas por árbol estas pruebas detectan poco, por eso se interpreta siempre el gráfico.

2.7 Diferencias entre árboles: ANOVA y comparaciones múltiples de Tukey

Con 6 árboles hay 15 comparaciones por pares. Hacer tantas pruebas sueltas al 5 % elevaría la probabilidad de algún falso positivo a ≈ 54 %, por lo que se usó la prueba HSD de Tukey,23 que controla el error del conjunto, contrastada con pruebas de Welch por pares con ajuste de Holm.24 Los árboles difieren en 9 de 15 pares (Tabla 10, Fig. 14), y en 3 de 6 pares de árboles de la misma exposición. Es decir, dos árboles con la misma exposición pueden diferir tanto como uno de sol y uno de sombra: esa variación entre árboles es el ruido frente al cual debe competir el efecto de la exposición.

if (!is.null(R$tk)) {
  tk <- R$tk
  t3 <- data.frame(`Comparación (A / B)` = tk$comparacion, `Misma exposición` = ifelse(tk$misma, "sí", "no"), `Razón A/B` = fx(tk$razon, 2), `IC 95 % (Tukey)` = fci(tk$li, tk$ls),
                   `p ajustado (Tukey)` = fp(tk$p), `p ajustado (Welch + Holm)` = fp(tk$p_welch_holm), `Difieren (5 %)` = ifelse(tk$p < 0.05, "sí", "no"), check.names = FALSE, stringsAsFactors = FALSE)
  cat(tcap("tukey", "Comparaciones por pares entre árboles", "Escala logarítmica, mostradas como razones de áreas (A respecto de B)."))
  tabla(t3, align = "lcrrrrc")
}
Tabla 10. Comparaciones por pares entre árboles
Comparación (A / B)Misma exposiciónRazón A/BIC 95 % (Tukey)p ajustado (Tukey)p ajustado (Welch + Holm)Difieren (5 %)
T6 / T1sí1,86[1,50; 2,31]< 0,001< 0,001sí
T6 / T3no1,83[1,47; 2,27]< 0,001< 0,001sí
T6 / T5no1,55[1,25; 1,92]< 0,001< 0,001sí
T4 / T1sí1,54[1,24; 1,91]< 0,001< 0,001sí
T4 / T3no1,51[1,22; 1,87]< 0,001< 0,001sí
T2 / T1no1,37[1,10; 1,70]0,0010,006sí
T6 / T2no1,36[1,10; 1,69]0,0010,002sí
T3 / T2sí0,74[0,60; 0,92]0,002< 0,001sí
T5 / T4no0,78[0,63; 0,97]0,0170,037sí
T6 / T4sí1,21[0,97; 1,50]0,1150,129no
T5 / T1no1,20[0,97; 1,49]0,1310,143no
T5 / T3sí1,18[0,95; 1,47]0,2210,127no
T5 / T2sí0,88[0,71; 1,09]0,5070,206no
T4 / T2no1,12[0,91; 1,40]0,5970,228no
T3 / T1no1,02[0,82; 1,27]1,0000,802no

Nota. Escala logarítmica, mostradas como razones de áreas (A respecto de B).

if (!is.null(R$tk)) {
  tk <- R$tk; tk$y <- factor(tk$comparacion, levels = rev(tk$comparacion)); tk$sig <- ifelse(tk$p < 0.05, "sí", "no")
  ggplot(tk, aes(razon, y, colour = sig)) + geom_vline(xintercept = 1, linetype = 2, colour = "grey50") +
    geom_segment(aes(x = li, xend = ls, yend = y), linewidth = .9) +
    geom_point(aes(shape = misma), size = 3.2, fill = "white", stroke = 1) +
    scale_shape_manual(values = c(`TRUE` = 16, `FALSE` = 21), labels = c(`TRUE` = "misma exposición", `FALSE` = "exposición distinta"), name = NULL) +
    scale_colour_manual(values = c("sí" = "#D55E00", "no" = "grey45"), guide = "none") + scale_x_log10() + labs(x = "Razón de áreas A/B (escala log)", y = NULL)
}
**Fig. 14 | Razón de áreas entre pares de árboles.** Razón con su intervalo HSD de Tukey (escala log). Si el intervalo cruza 1, no hay diferencia detectable. Círculos rellenos: árboles de la misma exposición; círculos vacíos: exposiciones distintas. Rojo: diferencia detectable al 5 %.

Fig. 14 | Razón de áreas entre pares de árboles. Razón con su intervalo HSD de Tukey (escala log). Si el intervalo cruza 1, no hay diferencia detectable. Círculos rellenos: árboles de la misma exposición; círculos vacíos: exposiciones distintas. Rojo: diferencia detectable al 5 %.

2.8 Robustez frente a la base de datos y a árboles individuales

Todas las hojas tienen área medida, por lo que no hay nada que completar. El resultado primario (A) se contrasta con (B), el análisis del área del marco, que usa solo los lados medidos con regla y es independiente del script de imagen; y se repite el contraste omitiendo un árbol a la vez.

mk <- function(lab, b, extra = "") c(lab, paste0(b$n_sol, " / ", b$n_som), fx(b$razon, 2), fci(b$li, b$ls), fp(b$p_welch), fp(b$p_wilcox), fp(b$p_perm))
fs <- list(mk("A · Áreas medidas", bA), mk("B · Marco de todas las hojas", bB))
if (R$n_imp > 0) fs[[3]] <- mk("C · Medidas + completadas", bC)
if (!is.null(R$sim)) fs[[length(fs) + 1]] <- c("C · incertidumbre del completado (mediana y rango 2,5–97,5 %)", "—", fx(R$sim_q[2], 2), fci(R$sim_q[1], R$sim_q[3]), "—", "—", "—")
if (!is.null(R$jk)) fs[[length(fs) + 1]] <- c("A · dejando un árbol fuera (rango)", "—", paste0(fx(R$jk_rango[1], 2), "–", fx(R$jk_rango[2], 2)), "—", "—", "—", "—")
ts <- as.data.frame(do.call(rbind, fs), stringsAsFactors = FALSE)
names(ts) <- c("Base de datos", "n árboles (sol / sombra)", "Razón sombra/sol", "IC 95 %", "p Welch", "p Wilcoxon", "p permutación")
cat(tcap("sens", "Sensibilidad del contraste sol–sombra a la base de datos y a árboles individuales", "Welch, Wilcoxon exacta y permutación exacta sobre promedios de árbol (escala log para las razones)."))
Tabla 11. Sensibilidad del contraste sol–sombra a la base de datos y a árboles individuales
tabla(ts, align = "lrrrrrr")
Base de datosn árboles (sol / sombra)Razón sombra/solIC 95 %p Welchp Wilcoxonp permutación
A · Áreas medidas3 / 31,19[0,61; 2,33]0,4480,7000,500
B · Marco de todas las hojas3 / 31,24[0,67; 2,27]0,3500,4000,300
A · dejando un árbol fuera (rango)—1,04–1,42————

Nota. Welch, Wilcoxon exacta y permutación exacta sobre promedios de árbol (escala log para las razones).

dirs <- c(bA$razon, bB$razon, if (R$n_imp > 0) bC$razon); dirs <- dirs[!is.na(dirs)]
R$concord <- length(dirs) >= 2 && (all(dirs > 1) || all(dirs < 1))
R$txt_sens <- paste0("Las bases de datos analizadas ", if (R$concord) paste0("apuntan en la misma dirección (", ifelse(all(dirs > 1), "hojas mayores en sombra", "hojas mayores en sol"), ")") else "**no coinciden** en la dirección del efecto",
  ". Clasificación: A, ", R$conc_A, "; B, ", R$conc_B, if (R$n_imp > 0) paste0("; C, ", R$conc_C) else "", ". ",
  if (!is.null(R$sim)) paste0("Completar las áreas pendientes añade poca incertidumbre (", fx(R$sim_q[1], 2), "–", fx(R$sim_q[3], 2), ") frente a la que impone el número de árboles. ") else "",
  if (!is.na(R$jk_rango[1])) paste0("Al quitar un árbol a la vez, la razón varía entre ", fx(R$jk_rango[1], 2), " y ", fx(R$jk_rango[2], 2),
    if (R$jk_cruza) paste0(": **el resultado cambia de signo según el árbol que se omita**, es decir, depende de árboles concretos (", fref("jack"), ").") else paste0(": la dirección se mantiene (", fref("jack"), ").")) else "")

Las bases de datos analizadas apuntan en la misma dirección (hojas mayores en sombra). Clasificación: A, no concluyente (el intervalo incluye 1); B, no concluyente (el intervalo incluye 1). Al quitar un árbol a la vez, la razón varía entre 1,04 y 1,42: la dirección se mantiene (Fig. 16).

if (!is.null(R$sim)) {
  ggplot(data.frame(r = exp(R$sim)), aes(r)) + geom_histogram(bins = 40, fill = "grey80", colour = "white") +
    geom_vline(xintercept = bC$razon, colour = COL["sombra"], linewidth = 1) + geom_vline(xintercept = bA$razon, colour = "black", linetype = 2) + geom_vline(xintercept = 1, linetype = 3, colour = "grey50") +
    labs(x = "Razón sombra/sol", y = "Simulaciones")
} else ggplot() + theme_void() + annotate("text", x = 0, y = 0, label = "No hay áreas pendientes que completar")
**Fig. 15 | Incertidumbre propagada del completado de las áreas pendientes.** Distribución de la razón sombra/sol en las simulaciones que reemplazan cada área pendiente por una predicción del modelo marco → área más ruido residual. Línea azul: estimación con el completado determinista (C); línea negra: análisis con solo áreas medidas (A).

Fig. 15 | Incertidumbre propagada del completado de las áreas pendientes. Distribución de la razón sombra/sol en las simulaciones que reemplazan cada área pendiente por una predicción del modelo marco → área más ruido residual. Línea azul: estimación con el completado determinista (C); línea negra: análisis con solo áreas medidas (A).

jj <- R$jk[!is.na(R$jk$razon), ]
if (nrow(jj) > 0) ggplot(jj, aes(razon, reorder(omitido, razon))) + geom_vline(xintercept = 1, linetype = 3) + geom_vline(xintercept = bA$razon, linetype = 2, colour = "grey40") +
  geom_segment(aes(x = bA$razon, xend = razon, yend = omitido), colour = "grey60") + geom_point(aes(fill = exposicion), shape = 21, size = 4, colour = "grey15") +
  scale_fill_manual(values = COL, name = "Exposición del árbol omitido") + labs(x = "Razón sombra/sol sin ese árbol", y = "Árbol omitido")
**Fig. 16 | Influencia de cada árbol (omisión de un árbol a la vez).** Razón sombra/sol al excluir cada árbol. Línea discontinua: estimación con todos los árboles; línea punteada: ausencia de efecto. Un árbol cuya omisión cambia mucho la estimación es un árbol influyente.

Fig. 16 | Influencia de cada árbol (omisión de un árbol a la vez). Razón sombra/sol al excluir cada árbol. Línea discontinua: estimación con todos los árboles; línea punteada: ausencia de efecto. Un árbol cuya omisión cambia mucho la estimación es un árbol influyente.

2.9 Potencia y tamaño de muestra

Con la desviación estándar entre árboles observada (en escala logarítmica; σ = 0,25, IC 95 %: 0,15–0,71, con solo 4 grados de libertad), se calculó la razón mínima detectable con 80 % de potencia y α = 0,05 según el número de árboles por exposición (Fig. 17).

if (!is.null(R$pot)) {
  p <- R$pot
  lo <- vapply(p$ns, function(n) exp(power.t.test(n = n, power = .8, sd = p$sd_ic[1])$delta), numeric(1))
  hi <- vapply(p$ns, function(n) exp(power.t.test(n = n, power = .8, sd = p$sd_ic[2])$delta), numeric(1))
  dfp <- data.frame(n = p$ns, mde = p$mde, lo = lo, hi = hi)
  ggplot(dfp, aes(n, mde)) + geom_ribbon(aes(ymin = lo, ymax = hi), fill = "grey87") + geom_line(linewidth = .9) +
    geom_hline(yintercept = 1, linetype = 3) + geom_hline(yintercept = bA$razon, colour = COL["sombra"], linetype = 2) +
    geom_vline(xintercept = min(R$n_sol, R$n_som), colour = "grey40", linetype = 2) +
    scale_y_log10(breaks = c(1, 1.25, 1.5, 2, 3, 5)) + coord_cartesian(ylim = c(1, 5)) +
    labs(x = "Árboles por exposición", y = "Razón mínima detectable (sombra/sol)")
}
**Fig. 17 | Diferencia mínima detectable en función del número de árboles.** Razón sombra/sol detectable con 80 % de potencia (prueba *t* de dos muestras sobre promedios de árbol; banda: incertidumbre de la desviación estándar entre árboles estimada con pocos grados de libertad). Línea vertical: árboles por exposición en el análisis A; línea azul discontinua: razón observada.

Fig. 17 | Diferencia mínima detectable en función del número de árboles. Razón sombra/sol detectable con 80 % de potencia (prueba t de dos muestras sobre promedios de árbol; banda: incertidumbre de la desviación estándar entre árboles estimada con pocos grados de libertad). Línea vertical: árboles por exposición en el análisis A; línea azul discontinua: razón observada.

Con 3 árboles por exposición, la razón mínima detectable es ≈ 2,14, es decir, solo diferencias muy grandes. Para detectar razones de 1,2; 1,3; 1,5 y 2,0 se necesitarían aproximadamente 31, 16, 7, 4 árboles por exposición, respectivamente (con la desviación entre árboles aquí estimada, que es incierta). La conclusión práctica coincide con la de la partición de varianza: conviene medir más árboles antes que más hojas por árbol.

2.10 Forma de la hoja y contexto espacial

dfa <- datos[!is.na(datos$aspecto), ]; dfa$arbol_f <- factor(dfa$arbol, levels = comp$arbol)
pa <- ggplot(dfa, aes(arbol_f, aspecto, fill = exposicion)) + geom_boxplot(width = .55, outlier.shape = NA, alpha = .5, colour = "grey25", linewidth = .4) +
  geom_jitter(width = .12, height = 0, size = 1.4, alpha = .7) + scale_fill_manual(values = COL, name = "Exposición") + labs(x = NULL, y = "Lado mayor / lado menor")
pbd <- merge(desc_all[, c("arbol", "exposicion", "geom")], geo[, c("arbol", "y_m")], by = "arbol")
pb <- ggplot(pbd, aes(y_m, geom, fill = exposicion)) + geom_point(shape = 21, size = 4, colour = "grey15") + geom_text(aes(label = arbol), nudge_y = diff(range(pbd$geom)) * .08 + .5, size = 3) +
  scale_fill_manual(values = COL, guide = "none") + labs(x = "Posición norte–sur respecto del centroide (m)", y = "Media geométrica del área (cm²)")
if (nrow(pbd) >= 4) { ct <- suppressWarnings(cor.test(pbd$y_m, pbd$geom, method = "spearman")); R$sp_rho <- unname(ct$estimate); R$sp_p <- ct$p.value }
pa + pb + plot_annotation(tag_levels = "a")
**Fig. 18 | Relación de aspecto del marco y posición espacial de los árboles.** **a**, Relación de aspecto (lado mayor/lado menor del marco) por árbol, como indicador burdo de la forma. **b**, Media geométrica del área de cada árbol frente a su posición norte–sur; un patrón espacial podría confundirse con la exposición.

Fig. 18 | Relación de aspecto del marco y posición espacial de los árboles. a, Relación de aspecto (lado mayor/lado menor del marco) por árbol, como indicador burdo de la forma. b, Media geométrica del área de cada árbol frente a su posición norte–sur; un patrón espacial podría confundirse con la exposición.

La relación de aspecto del marco fue 1,11 en promedio (rango 1,00–1,33), propia de láminas bilobuladas casi tan anchas como largas; entre exposiciones la razón de aspecto fue 0,96 (IC 95 %: 0,87–1,07; p = 0,305), sin indicio de cambio de forma. El árbol más alejado del centroide (T6, a 175 m) hace que la correlación de Spearman entre la posición norte–sur y el tamaño sea ρ = 0,71 (p = 0,136, n = 6, solo exploratoria). Con tan pocos árboles, la exposición y la ubicación no pueden separarse.

3 Discusión

Con el árbol como unidad experimental, las hojas de los árboles de sombra fueron 19 % mayores que las de sol en promedio geométrico (razón = 1,19; IC 95 %: 0,61–2,33; p = 0,448). La dirección es la de H2 (hojas algo mayores en sombra), pero el intervalo de confianza incluye la ausencia de efecto: no hay evidencia suficiente ni a favor de H1 ni a favor de H2. Más informativo que el contraste es el reparto de la variación: el 68 % de la variación del tamaño de las hojas está entre árboles (CCI = 0,68), es decir, el árbol es la fuente de variación dominante y la exposición, una de varias posibles causas de ella. Con 3 árboles por exposición, el diseño solo habría detectado razones de ≈ 2,14 o mayores con 80 % de potencia. Conviene leer estos números con las cautelas que recomienda la literatura estadística: un intervalo de confianza que incluye la ausencia de efecto describe imprecisión, no demuestra que no haya efecto, y la diferencia entre un resultado «significativo» y otro «no significativo» no es en sí misma significativa.25–27 Por eso este informe prioriza las estimaciones con sus intervalos y la coherencia entre análisis sobre el valor de p de una sola prueba.

3.1 Contraste con la literatura

La Fig. 19 confronta las predicciones de ambas hipótesis con lo observado. H1 se apoya en que una mayor radiación aporta más energía a la fotosíntesis y en que, a escala global, las hojas grandes predominan en ambientes cálidos, húmedos y soleados.4 H2 se apoya en la compensación en sombra: con poca luz las plantas despliegan rasgos que optimizan la captura de luz y modifican la masa por área y la asignación de superficie foliar.28,29 A favor de H2 también actúa la limitación térmica e hídrica a pleno sol: una lámina mayor engrosa la capa límite y dificulta disipar calor y agua.7,8 Cuál domina depende del balance entre luz, temperatura y agua en cada micrositio, y por eso la dirección del efecto sobre el área de una hoja debe contrastarse caso por caso. Además, el área de una hoja no es una medida de producción: no se midieron fotosíntesis ni biomasa, y el aprovechamiento de la luz depende de cómo se organiza todo el follaje.

ref_a <- paste0("[", cn("wright2017"), "]")
ref_b <- paste0("[", cn("poorter2009", "poorter2019", "valladares2008", "givnish1988"), "]")
ref_c <- paste0("[", cn("parkhurst1972", "michaletz2015"), "]")
capa2 <- c(
  caja(12, 59, 24, 12, "Alta irradiancia\n(pleno sol)", fill = adjustcolor(COL["sol"], .3), face = "bold", size = 2.6),
  caja(50, 59, 36, 13, "Más energía para la fotosíntesis;\nhojas grandes en ambientes\ncálidos, húmedos y soleados", size = 2.6),
  caja(86, 59, 28, 12, "H1: lámina mayor\na pleno sol", fill = adjustcolor(COL["sol"], .15), size = 2.6, face = "bold"),
  caja(12, 38, 24, 12, "Baja irradiancia\n(sombra)", fill = adjustcolor(COL["sombra"], .3), face = "bold", size = 2.6),
  caja(50, 38, 36, 13, "Compensación morfológica:\nmás superficie para captar luz,\nmenor masa por unidad de área", size = 2.6),
  caja(86, 38, 28, 12, "H2: lámina mayor\nen sombra", fill = adjustcolor(COL["sombra"], .15), size = 2.6, face = "bold"),
  caja(12, 17, 24, 12, "Calor excesivo o\nfalta de agua (sol)", fill = adjustcolor(COL["sol"], .3), face = "bold", size = 2.6),
  caja(50, 17, 36, 13, "Capa límite más gruesa;\nmás pérdida de agua\ny dificultad para disipar calor", size = 2.6),
  caja(86, 17, 28, 12, "Limitación: lámina\nmenor a pleno sol", fill = adjustcolor(COL["sol"], .15), size = 2.6, face = "bold"),
  list(flecha(24.4, 59, 31.6, 59), flecha(68.4, 59, 71.6, 59), flecha(24.4, 38, 31.6, 38), flecha(68.4, 38, 71.6, 38), flecha(24.4, 17, 31.6, 17), flecha(68.4, 17, 71.6, 17),
       annotate("text", x = 50, y = 50, label = ref_a, size = 2.8, colour = "grey30"), annotate("text", x = 50, y = 29, label = ref_b, size = 2.8, colour = "grey30"),
       annotate("text", x = 50, y = 8.5, label = ref_c, size = 2.8, colour = "grey30")),
  caja(50, 1, 96, 7, paste0("Observado (A): razón sombra/sol = ", fx(bA$razon, 2), " [", fx(bA$li, 2), "–", fx(bA$ls, 2), "]\n→ ", R$conc_A), fill = "#f1f3f4", face = "bold", size = 2.7))
pa <- ggplot() + capa2 + coord_cartesian(xlim = c(0, 100), ylim = c(-3, 66), clip = "off") + theme_void()
pb <- ggplot() + theme_void()
fb <- fr[fr$tipo == "correcto" & grepl("^(A · Welch|B ·|C ·)", as.character(fr$label)), ]
if (nrow(fb) > 0) {
  xl <- range(c(fb$lo, fb$hi, 0.5, 2), na.rm = TRUE)
  pb <- ggplot(fb, aes(est, label)) +
    annotate("rect", xmin = 1e-3, xmax = 1, ymin = -Inf, ymax = Inf, fill = COL["sol"], alpha = .14) +
    annotate("rect", xmin = 1, xmax = 1e3, ymin = -Inf, ymax = Inf, fill = COL["sombra"], alpha = .10) +
    geom_vline(xintercept = 1, linetype = 2, colour = "grey40") +
    geom_segment(aes(x = lo, xend = hi, yend = label), linewidth = 1, na.rm = TRUE) + geom_point(size = 3.6, shape = 21, fill = "white", stroke = 1.1) +
    annotate("text", x = exp(mean(log(c(xl[1], 1)))), y = nrow(fb) + .45, label = "Región de H1 (sol > sombra)", size = 3, colour = "#a06a00") +
    annotate("text", x = exp(mean(log(c(1, xl[2])))), y = nrow(fb) + .45, label = "Región de H2 (sombra > sol)", size = 3, colour = "#005a8c") +
    scale_x_log10(breaks = c(.25, .5, 1, 2, 4, 8)) + coord_cartesian(xlim = xl, ylim = c(.5, nrow(fb) + .8)) + labs(x = "Razón de áreas sombra/sol (escala log)", y = NULL)
}
pa / pb + plot_layout(heights = c(1.45, 1)) + plot_annotation(tag_levels = "a")
**Fig. 19 | Predicciones de la literatura frente a lo observado.** **a**, Rutas causales que plantea la teoría para el área de una hoja individual; los números entre corchetes remiten a las referencias. **b**, Razón sombra/sol observada con tres bases de datos (barras: IC 95 %). La zona ocre es la región predicha por H1 (hojas mayores a pleno sol); la zona azul, la de H2 (hojas mayores en sombra).

Fig. 19 | Predicciones de la literatura frente a lo observado. a, Rutas causales que plantea la teoría para el área de una hoja individual; los números entre corchetes remiten a las referencias. b, Razón sombra/sol observada con tres bases de datos (barras: IC 95 %). La zona ocre es la región predicha por H1 (hojas mayores a pleno sol); la zona azul, la de H2 (hojas mayores en sombra).

tl <- data.frame(
  Predicción = c("Más radiación y agua suficiente favorecen láminas mayores a pleno sol (H1)", "En sombra, la compensación morfológica favorece láminas mayores (H2)", "El calor excesivo y el déficit hídrico limitan el tamaño a pleno sol", "La luz modifica la masa por área y la asignación foliar", "La variación entre individuos es grande y no puede ignorarse al replicar"),
  Fuentes = c(paste0("Ref. ", cn("wright2017")), paste0("Refs. ", cn("valladares2008", "givnish1988", "poorter2019")), paste0("Refs. ", cn("parkhurst1972", "michaletz2015")), paste0("Refs. ", cn("poorter2009", "poorter2019")), paste0("Ref. ", cn("hurlbert1984"))),
  `Este estudio` = c(paste0("razón ", fx(bA$razon, 2), " (", fx(bA$li, 2), "–", fx(bA$ls, 2), ")"), paste0("razón ", fx(bA$razon, 2), " (", fx(bA$li, 2), "–", fx(bA$ls, 2), ")"),
                     "no separable: no se midieron temperatura ni estado hídrico", "no medida (solo área de la lámina)", if (!is.null(R$icc)) paste0("CCI = ", fx(R$icc$icc, 2)) else "n/d"),
  Valoración = c(R$val_h1, R$val_alt, "no evaluable con estos datos", "no evaluable con estos datos",
                 if (!is.null(R$icc)) ifelse(R$icc$icc > 0.3, "consistente: la varianza entre árboles es sustancial", "no evidente en estos datos") else "n/d"),
  check.names = FALSE, stringsAsFactors = FALSE)
cat(tcap("lit", "Predicciones derivadas de la literatura y su contraste con los datos", "«No evaluable» significa que la variable que distingue la hipótesis no se registró."))
Tabla 12. Predicciones derivadas de la literatura y su contraste con los datos
tabla(tl, align = "llll")
PredicciónFuentesEste estudioValoración
Más radiación y agua suficiente favorecen láminas mayores a pleno sol (H1)Ref. 4razón 1,19 (0,61–2,33)no concluyente (el IC incluye 1)
En sombra, la compensación morfológica favorece láminas mayores (H2)Refs. 5,6,29razón 1,19 (0,61–2,33)no concluyente (el IC incluye 1)
El calor excesivo y el déficit hídrico limitan el tamaño a pleno solRefs. 7,8no separable: no se midieron temperatura ni estado hídricono evaluable con estos datos
La luz modifica la masa por área y la asignación foliarRefs. 28,29no medida (solo área de la lámina)no evaluable con estos datos
La variación entre individuos es grande y no puede ignorarse al replicarRef. 11CCI = 0,68consistente: la varianza entre árboles es sustancial

Nota. «No evaluable» significa que la variable que distingue la hipótesis no se registró.

3.2 Qué es un resultado y qué es una hipótesis

Siguiendo la distinción que pide la guía, con unos pocos árboles conviene separar lo que los datos establecen de lo que solo sugieren:

  • Resultados (descriptivos, bien sustentados): la distribución del área por árbol (Tabla 4); la regularidad del cociente área/marco y su utilidad como control de calidad (El marco explicó el 96 % de la variación del log-área de las hojas medidas, lo que permitió un análisis de sensibilidad con las 60 hojas.); y la magnitud de la variación entre árboles frente a la variación entre hojas.
  • Hipótesis (requieren más árboles): que la exposición cambie el área foliar de Bauhinia picta y en qué sentido. La dirección es la de H2 (hojas algo mayores en sombra), pero el intervalo de confianza incluye la ausencia de efecto: no hay evidencia suficiente ni a favor de H1 ni a favor de H2. Esta lectura es válida únicamente para los 6 árboles analizados.
  • No evaluable aquí: los mecanismos (luz, temperatura, agua, suelo pavimentado), porque no se midieron; se requeriría registrar irradiancia, temperatura foliar o del aire, humedad del suelo y masa por área.

3.3 Limitaciones

  • Pocos árboles. La réplica verdadera es el árbol y hay 3 de sol y 3 de sombra con datos; los grados de libertad del contraste son los de los árboles y la potencia es baja (véase Potencia y tamaño de muestra).
  • Árboles influyentes y confusión espacial. la exposición y la posición en el bosque urbano no están cruzadas, de modo que no se pueden separar sus efectos.
  • Exposición categórica. «Sol» y «sombra» son clases definidas visualmente (luz directa la mayor parte del día frente a cobertura de otras copas o luz filtrada), no medidas de irradiancia; el sombreado varía a lo largo del día y del año, y la sombra por «luz filtrada» es heterogénea.
  • Áreas pendientes. Hay 0 áreas pendientes (0,0 %). Completarlas con el modelo del marco es un artificio útil para evaluar la sensibilidad, pero no sustituye la medición, y el análisis con el marco no es una confirmación independiente porque el marco se dibuja a partir del contorno de la propia hoja.
  • Elección de los árboles. El único criterio de selección fue que estuvieran desarrollados y sin daño ni enfermedad aparente; no se igualaron edad, tamaño ni morfotipo, de modo que parte de la diferencia atribuida a la exposición puede reflejar esas diferencias entre individuos.
  • Una sola especie, un solo sitio y una sola fecha (no registrada en la base): los resultados no se extrapolan a otras especies ni a otras épocas.
  • Medición. La detección del marco y de la figura en la fotografía, y el dibujo del marco con regla, introducen error de medida; el error residual del modelo del marco (≈ 5,2 %) es una cota inferior del error de predicción, no del error del área.

4 Métodos

Sitio y especie. El estudio se realizó en el Bosque Urbano Multicentro, ubicado en el área forestal protectora del río Meléndez, comuna 22, Cali (Valle del Cauca, Colombia), a 987 m s. n. m. (altitud registrada en la base). La especie estudiada fue Bauhinia picta.

Selección de árboles. Dentro del bosque urbano se identificaron zonas abiertas y zonas de alta densidad arbórea. Se consideraron árboles de sol los que reciben luz directa la mayor parte del día y no están cubiertos por otras copas ni por edificaciones, y árboles de sombra los que crecen bajo la cobertura de otros árboles o en zonas con luz filtrada. Se seleccionaron 6 árboles, 3 de sol y 3 de sombra, para obtener un diseño balanceado; el único criterio de selección fue que estuvieran desarrollados y sin daño ni enfermedad aparente. De cada árbol se registraron las coordenadas y se tomó una fotografía de referencia que documenta su estado, su entorno y su grado de exposición solar.

Selección de hojas. En cada árbol se muestrearon 10 hojas (60 en total), distribuidas por toda la copa y a diferentes distancias.

Medición del área foliar. Alrededor del contorno de cada hoja se dibujó con regla un marco rectangular y se midieron sus dos lados en milímetros. Se fotografió la hoja con su marco y un script en R usó el tamaño del marco en cada fotografía como escala para convertir píxeles a cm² y calcular así el área de la hoja. El área del marco se calculó como lado 1 × lado 2 (mm²) / 100 (cm²).

Procesamiento y control de calidad. Los datos se leyeron como texto y se convirtieron a tipos numéricos con reglas explícitas: eliminación de espacios, coma o punto decimal, reconstrucción de coordenadas escritas con separador de miles, normalización de la exposición y de los identificadores. Un área mayor que su marco es físicamente imposible; si dividida entre 100 resultaba plausible (cociente entre 0,2 y 1) se interpretó como error de unidad y se corrigió; en otro caso se excluyó. Las áreas en blanco no se imputan en el análisis primario. La base analítica primaria (A) contiene las hojas con área medida válida de los árboles con al menos 3 hojas medidas.

Estadística descriptiva y transformación. Por árbol se calcularon n, media, mediana, DE, CV, error estándar, IC 95 % (t), mínimo, máximo y media geométrica. La inferencia se hizo sobre el logaritmo natural del área (ln), porque el tamaño es multiplicativo y la dispersión crece con la media; las diferencias en ln se reportan como razones de medias geométricas. En el resto del informe los resultados se expresan en la escala original (razones de tamaño) y se omite la mención al logaritmo.

Unidad de análisis y contraste sol–sombra. Para cada árbol se calculó el promedio de ln(área) y esos promedios se compararon entre exposiciones con la prueba t de Welch,12 la prueba de Wilcoxon exacta,13 una prueba de permutación exacta (diferencia de medias de árbol bajo todos los repartos de las etiquetas) y un bootstrap jerárquico de dos etapas (5000 réplicas: remuestreo de árboles dentro de cada exposición y de hojas dentro de cada árbol).14 Se calculó la g de Hedges con IC aproximado.18 El efecto de diseño se estimó como 1 + (m̄ − 1)·CCI.

Modelos. Se ajustó el modelo mixto ln(A) ~ exposición + (1 | árbol) por REML con lme4 y lmerTest (gl de Satterthwaite), con R² marginal y condicional (Nakagawa y Schielzeth), y el ANOVA anidado con la exposición contrastada contra el cuadrado medio de árbol. El CCI se estimó por ANOVA de un factor con IC de McGraw y Wong, usando el tamaño medio ponderado n0. Los supuestos se revisaron con gráficos de residuos y con las pruebas de Shapiro–Wilk y Fligner–Killeen; como alternativas robustas se usaron el ANOVA de Welch y Kruskal–Wallis. Las comparaciones por pares entre árboles usaron Tukey HSD y, como contraste, Welch con ajuste de Holm.

Valores atípicos. Regla de Tukey por árbol (1,5·RIC), z robusto con la MAD (umbral 3,5), residuos studentizados (|t| > 3) y distancia de Cook (4/N). Las hojas sin causa de medición se conservan y se evalúa la sensibilidad del resultado a distintos resúmenes del árbol (media, mediana, media recortada, media sin atípicos).

Análisis de sensibilidad. (B) El contraste se repitió con ln(área del marco) de todas las hojas. (C) Las áreas pendientes se estimaron con la regresión ln(área) ~ ln(marco) ajustada a las hojas medidas (con corrección de retransformación) y se repitió el contraste; su incertidumbre se propagó con 2000 simulaciones que añaden el error residual y el de estimación del modelo. También se omitió un árbol a la vez (jackknife por árbol).

Potencia. Se calculó la razón mínima detectable (80 % de potencia, α = 0,05, prueba t de dos muestras) con la desviación estándar entre árboles observada dentro de cada exposición y su IC por χ².

Software y reproducibilidad. Todo el análisis se ejecuta desde este documento con R version 4.4.2 (2024-10-31 ucrt); los gráficos usan ggplot2,30 con paleta de Okabe–Ito apta para daltonismo, y patchwork. Semilla aleatoria: 20261103. Paquetes: ggplot2 4.0.3, patchwork 1.3.2, lme4 2.0.1, lmerTest 3.2.1.31 Si se modifica el archivo de datos, basta volver a compilar el documento.

Disponibilidad de datos y de código. Los datos analizados son los de datos.csv. Cambiando el parámetro guardar_limpios a TRUE se escribe la base depurada (datos_limpios_area_foliar.csv).

Referencias

  1. Arroyave, M. P., Posada, M. I. & Gutiérrez, M. E. Catálogo virtual de flora del Valle de Aburrá (Universidad EIA, 2014). http://catalogofloravalleaburra.eia.edu.co
  2. Violle, C. et al. Let the concept of trait be functional! Oikos 116, 882–892 (2007). https://doi.org/10.1111/j.0030-1299.2007.15559.x
  3. Pérez-Harguindeguy, N. et al. New handbook for standardised measurement of plant functional traits worldwide. Aust. J. Bot. 61, 167–234 (2013). https://doi.org/10.1071/BT12225
  4. Wright, I. J. et al. Global climatic drivers of leaf size. Science 357, 917–921 (2017). https://doi.org/10.1126/science.aal4760
  5. Valladares, F. & Niinemets, Ü. Shade tolerance, a key plant feature of complex nature and consequences. Annu. Rev. Ecol. Evol. Syst. 39, 237–257 (2008). https://doi.org/10.1146/annurev.ecolsys.39.110707.173506
  6. Givnish, T. J. Adaptation to sun and shade: a whole-plant perspective. Aust. J. Plant Physiol. 15, 63–92 (1988). https://doi.org/10.1071/PP9880063
  7. Parkhurst, D. F. & Loucks, O. L. Optimal leaf size in relation to environment. J. Ecol. 60, 505–537 (1972). https://doi.org/10.2307/2258359
  8. Michaletz, S. T. et al. Plant thermoregulation: energetics, trait–environment interactions, and carbon economics. Trends Ecol. Evol. 30, 714–724 (2015). https://doi.org/10.1016/j.tree.2015.09.006
  9. McGraw, K. O. & Wong, S. P. Forming inferences about some intraclass correlation coefficients. Psychol. Methods 1, 30–46 (1996). https://doi.org/10.1037/1082-989X.1.1.30
  10. Nakagawa, S. & Schielzeth, H. A general and simple method for obtaining R2 from generalized linear mixed-effects models. Methods Ecol. Evol. 4, 133–142 (2013). https://doi.org/10.1111/j.2041-210x.2012.00261.x
  11. Hurlbert, S. H. Pseudoreplication and the design of ecological field experiments. Ecol. Monogr. 54, 187–211 (1984). https://doi.org/10.2307/1942661
  12. Welch, B. L. The generalization of ‘Student’s’ problem when several different population variances are involved. Biometrika 34, 28–35 (1947). https://doi.org/10.1093/biomet/34.1-2.28
  13. Wilcoxon, F. Individual comparisons by ranking methods. Biometrics Bull. 1, 80–83 (1945). https://doi.org/10.2307/3001968
  14. Efron, B. Bootstrap methods: another look at the jackknife. Ann. Stat. 7, 1–26 (1979). https://doi.org/10.1214/aos/1176344552
  15. Bates, D., Mächler, M., Bolker, B. & Walker, S. Fitting linear mixed-effects models using lme4. J. Stat. Softw. 67, 1–48 (2015). https://doi.org/10.18637/jss.v067.i01
  16. Kuznetsova, A., Brockhoff, P. B. & Christensen, R. H. B. lmerTest package: tests in linear mixed effects models. J. Stat. Softw. 82, 1–26 (2017). https://doi.org/10.18637/jss.v082.i13
  17. Satterthwaite, F. E. An approximate distribution of estimates of variance components. Biometrics Bull. 2, 110–114 (1946). https://doi.org/10.2307/3002019
  18. Hedges, L. V. Distribution theory for Glass’s estimator of effect size and related estimators. J. Educ. Stat. 6, 107–128 (1981). https://doi.org/10.3102/10769986006002107
  19. Lakens, D. Calculating and reporting effect sizes to facilitate cumulative science: a practical primer for t-tests and ANOVAs. Front. Psychol. 4, 863 (2013). https://doi.org/10.3389/fpsyg.2013.00863
  20. Shapiro, S. S. & Wilk, M. B. An analysis of variance test for normality (complete samples). Biometrika 52, 591–611 (1965). https://doi.org/10.1093/biomet/52.3-4.591
  21. Fligner, M. A. & Killeen, T. J. Distribution-free two-sample tests for scale. J. Am. Stat. Assoc. 71, 210–213 (1976). https://doi.org/10.1080/01621459.1976.10481517
  22. Kruskal, W. H. & Wallis, W. A. Use of ranks in one-criterion variance analysis. J. Am. Stat. Assoc. 47, 583–621 (1952). https://doi.org/10.1080/01621459.1952.10483441
  23. Tukey, J. W. Comparing individual means in the analysis of variance. Biometrics 5, 99–114 (1949). https://doi.org/10.2307/3001913
  24. Holm, S. A simple sequentially rejective multiple test procedure. Scand. J. Stat. 6, 65–70 (1979). https://www.jstor.org/stable/4615733
  25. Gelman, A. & Stern, H. The difference between ‘significant’ and ‘not significant’ is not itself statistically significant. Am. Stat. 60, 328–331 (2006). https://doi.org/10.1198/000313006X152649
  26. Wasserstein, R. L. & Lazar, N. A. The ASA statement on p-values: context, process, and purpose. Am. Stat. 70, 129–133 (2016). https://doi.org/10.1080/00031305.2016.1154108
  27. Amrhein, V., Greenland, S. & McShane, B. Scientists rise up against statistical significance. Nature 567, 305–307 (2019). https://doi.org/10.1038/d41586-019-00857-9
  28. Poorter, H., Niinemets, Ü., Poorter, L., Wright, I. J. & Villar, R. Causes and consequences of variation in leaf mass per area (LMA): a meta-analysis. New Phytol. 182, 565–588 (2009). https://doi.org/10.1111/j.1469-8137.2009.02830.x
  29. Poorter, H. et al. A meta-analysis of plant responses to light intensity for 70 traits ranging from molecules to whole plant performance. New Phytol. 223, 1073–1105 (2019). https://doi.org/10.1111/nph.15754
  30. Wickham, H. ggplot2: Elegant Graphics for Data Analysis (Springer, 2016). https://doi.org/10.1007/978-3-319-24277-4
  31. R Core Team. R: A Language and Environment for Statistical Computing (R Foundation for Statistical Computing, Vienna). https://www.R-project.org/

Información suplementaria

Cumplimiento del protocolo de la guía

ok <- function(x) ifelse(x, "✔ cumple", "✘ no cumple")
n_hoja_arb <- table(datos$arbol)
tpr <- data.frame(
  Requisito = c("Al menos 2 árboles a pleno sol y 2 a la sombra", "10 hojas por árbol", "5 árboles por grupo", "Área medida en todas las hojas", "ID con formato G#_T# (p. ej. G3_T2)",
                "Columnas de la plantilla (grupo, id_arbol, fecha, observaciones)", "Coordenadas en grados decimales con un mismo separador", "Ningún árbol medido dos veces"),
  Estado = c(ok(min(R$n_sol_tot, R$n_som_tot) >= 2), ok(all(n_hoja_arb == 10)), ok(R$n_arb == 5), ok(R$n_falta == 0), ok(all(grepl("^G[0-9]+_T[0-9]+$", datos$arbol_raw))),
             ok(length(R$cols_plantilla_faltan) == 0), ok(R$n_coord_miles == 0), ok(nrow(R$dup_arbol) == 0)),
  Observación = c(paste0(R$n_sol_tot, " sol / ", R$n_som_tot, " sombra"), paste0(R$hojas_x_arbol[1], "–", R$hojas_x_arbol[2], " hojas"), paste0(R$n_arb, " árboles"),
                  paste0(R$n_falta, " pendientes"), "los identificadores son T1…T", paste0("faltan: ", ifelse(length(R$cols_plantilla_faltan), paste(R$cols_plantilla_faltan, collapse = ", "), "—")),
                  paste0(R$n_coord_miles, " filas con separador de miles (reconstruidas)"), paste0(nrow(R$dup_arbol), " pares a menos de ", params$dist_duplicado_m, " m")), stringsAsFactors = FALSE)
tpr$Observación[5] <- paste0("los identificadores son ", paste(head(sort(unique(datos$arbol)), 3), collapse = ", "), "…")
cat(tcap("protocolo", "Cumplimiento de los requisitos de la guía de campo", "Las desviaciones se declaran; no impiden el análisis, pero condicionan su interpretación."))
Tabla 13. Cumplimiento de los requisitos de la guía de campo
tabla(tpr, align = "lcl")
RequisitoEstadoObservación
Al menos 2 árboles a pleno sol y 2 a la sombra✔ cumple3 sol / 3 sombra
10 hojas por árbol✔ cumple10–10 hojas
5 árboles por grupo✘ no cumple6 árboles
Área medida en todas las hojas✔ cumple0 pendientes
ID con formato G#_T# (p. ej. G3_T2)✘ no cumplelos identificadores son T1, T2, T3…
Columnas de la plantilla (grupo, id_arbol, fecha, observaciones)✘ no cumplefaltan: grupo, id_arbol, fecha, observaciones
Coordenadas en grados decimales con un mismo separador✘ no cumple60 filas con separador de miles (reconstruidas)
Ningún árbol medido dos veces✔ cumple0 pares a menos de 5 m

Nota. Las desviaciones se declaran; no impiden el análisis, pero condicionan su interpretación.

Base de datos hoja a hoja

td2 <- data.frame(Archivo = datos$archivo, Árbol = datos$arbol, Exposición = as.character(datos$exposicion), `Lado 1 (mm)` = fx(datos$lado1, 0), `Lado 2 (mm)` = fx(datos$lado2, 0),
                  `Marco (cm²)` = fx(datos$marco_cm2, 1), `Área registrada (cm²)` = fx(datos$area_orig, 2), Estado = datos$estado, `Área usada (cm²)` = fx(datos$area_f, 2),
                  Origen = ifelse(is.na(datos$origen), "—", datos$origen), check.names = FALSE, stringsAsFactors = FALSE)
cat(tcap("datos", "Base de datos depurada (una fila por hoja)", "«Área usada» es la medida o, si estaba pendiente, la estimada con el modelo del marco (solo para el análisis de sensibilidad C)."))
Tabla 14. Base de datos depurada (una fila por hoja)
cat('<div style="max-height:430px;overflow:auto">\n'); tabla(td2, align = "llcrrrrlrl"); cat('</div>\n')
ArchivoÁrbolExposiciónLado 1 (mm)Lado 2 (mm)Marco (cm²)Área registrada (cm²)EstadoÁrea usada (cm²)Origen
hoja1.jpgT1sombra105105110,272,84ok72,84medida
hoja2.jpgT1sombra122123150,1103,44ok103,44medida
hoja3.jpgT1sombra128111142,185,03ok85,03medida
hoja4.jpgT1sombra115117134,690,14ok90,14medida
hoja5.jpgT1sombra889684,550,78ok50,78medida
hoja6.jpgT1sombra109110119,976,68ok76,68medida
hoja7.jpgT1sombra111120133,291,68ok91,68medida
hoja8.jpgT1sombra110112123,279,98ok79,98medida
hoja9.jpgT1sombra108124133,985,30ok85,30medida
hoja10.jpgT1sombra109113123,266,04ok66,04medida
hoja11.jpgT2sol125150187,5120,44ok120,44medida
hoja12.jpgT2sol132153202,0139,04ok139,04medida
hoja13.jpgT2sol123141173,4119,12ok119,12medida
hoja14.jpgT2sol127134170,2111,76ok111,76medida
hoja15.jpgT2sol112132147,898,62ok98,62medida
hoja16.jpgT2sol118125147,592,72ok92,72medida
hoja17.jpgT2sol117124145,197,16ok97,16medida
hoja18.jpgT2sol111127141,093,85ok93,85medida
hoja19.jpgT2sol117132154,4107,98ok107,98medida
hoja20.jpgT2sol117133155,6106,62ok106,62medida
hoja21.jpgT3sol100111111,074,61ok74,61medida
hoja22.jpgT3sol99109107,972,00ok72,00medida
hoja23.jpgT3sol99102101,071,16ok71,16medida
hoja24.jpgT3sol99110108,976,84ok76,84medida
hoja25.jpgT3sol98111108,875,06ok75,06medida
hoja26.jpgT3sol105122128,189,99ok89,99medida
hoja27.jpgT3sol110129141,996,99ok96,99medida
hoja28.jpgT3sol112117131,089,10ok89,10medida
hoja29.jpgT3sol108129139,394,68ok94,68medida
hoja30.jpgT3sol110104114,469,28ok69,28medida
hoja31.jpgT4sombra133167222,1145,77ok145,77medida
hoja32.jpgT4sombra143140200,2137,25ok137,25medida
hoja33.jpgT4sombra133127168,9115,80ok115,80medida
hoja34.jpgT4sombra149147219,0152,47ok152,47medida
hoja35.jpgT4sombra144138198,7137,12ok137,12medida
hoja36.jpgT4sombra119121144,094,34ok94,34medida
hoja37.jpgT4sombra120127152,4106,60ok106,60medida
hoja38.jpgT4sombra139140194,6136,41ok136,41medida
hoja39.jpgT4sombra122115140,391,11ok91,11medida
hoja40.jpgT4sombra142130184,6114,59ok114,59medida
hoja41.jpgT5sol129130167,7114,45ok114,45medida
hoja42.jpgT5sol129139179,3122,43ok122,43medida
hoja43.jpgT5sol111133147,6101,07ok101,07medida
hoja44.jpgT5sol97105101,873,41ok73,41medida
hoja45.jpgT5sol104138143,593,20ok93,20medida
hoja46.jpgT5sol104124129,087,67ok87,67medida
hoja47.jpgT5sol108125135,094,46ok94,46medida
hoja48.jpgT5sol98113110,775,61ok75,61medida
hoja49.jpgT5sol117130152,1106,07ok106,07medida
hoja50.jpgT5sol104122126,992,50ok92,50medida
hoja51.jpgT6sombra132147194,0127,36ok127,36medida
hoja52.jpgT6sombra127143181,6119,04ok119,04medida
hoja53.jpgT6sombra145186269,7174,29ok174,29medida
hoja54.jpgT6sombra142148210,2140,95ok140,95medida
hoja55.jpgT6sombra139158219,6149,12ok149,12medida
hoja56.jpgT6sombra139149207,1141,33ok141,33medida
hoja57.jpgT6sombra125157196,2119,48ok119,48medida
hoja58.jpgT6sombra135155209,2143,45ok143,45medida
hoja59.jpgT6sombra158184290,7191,36ok191,36medida
hoja60.jpgT6sombra153175267,8180,34ok180,34medida

Nota. «Área usada» es la medida o, si estaba pendiente, la estimada con el modelo del marco (solo para el análisis de sensibilidad C).

Verificación de los DOI con Crossref

norm_t <- function(s) { s <- tolower(iconv(s, to = "ASCII//TRANSLIT")); s <- gsub("[^a-z0-9 ]", " ", s); w <- unique(strsplit(trimws(gsub(" +", " ", s)), " ")[[1]]); w[nchar(w) > 0] }
jacc <- function(a, b) length(intersect(a, b)) / length(union(a, b))
.doi_env <- new.env(); .doi_env$off <- FALSE
verif <- function(k, i) {
  r <- REF[[k]]; base <- data.frame(N = i, Referencia = k, DOI = ifelse(is.na(r$doi), "—", r$doi), stringsAsFactors = FALSE)
  if (is.na(r$doi)) { base$Estado <- "sin DOI (se enlaza a la URL)"; return(base) }
  if (!isTRUE(params$verificar_doi) || !HAS_JSON) { base$Estado <- "verificación desactivada"; return(base) }
  if (.doi_env$off) { base$Estado <- "no se pudo consultar (sin conexión)"; return(base) }
  res <- tryCatch(jsonlite::fromJSON(paste0("https://api.crossref.org/works/", r$doi)), error = function(e) NULL)
  if (is.null(res)) .doi_env$off <- TRUE
  if (is.null(res)) { base$Estado <- "no se pudo consultar (sin conexión o DOI no resuelto)"; return(base) }
  tt <- res$message$title[1]
  an <- tryCatch(as.integer(res$message$issued$`date-parts`[1, 1]), error = function(e) NA_integer_)
  sim <- jacc(norm_t(tt), norm_t(r$tit))
  base$Estado <- ifelse(sim >= 0.6 && (is.na(an) || abs(an - r$anio) <= 1), "✔ coincide con Crossref", "✘ revisar")
  base
}
vt <- do.call(rbind, lapply(seq_along(.cit$orden), function(i) verif(.cit$orden[i], i)))
cat(tcap("doi", "Verificación automática de los DOI citados", "Se consulta la API de Crossref y se compara el título y el año; requiere conexión a internet al compilar."))
Tabla 15. Verificación automática de los DOI citados
tabla(vt, align = "rllll")
NReferenciaDOIEstado
1ueia2014—sin DOI (se enlaza a la URL)
2violle200710.1111/j.0030-1299.2007.15559.xverificación desactivada
3perez201310.1071/BT12225verificación desactivada
4wright201710.1126/science.aal4760verificación desactivada
5valladares200810.1146/annurev.ecolsys.39.110707.173506verificación desactivada
6givnish198810.1071/PP9880063verificación desactivada
7parkhurst197210.2307/2258359verificación desactivada
8michaletz201510.1016/j.tree.2015.09.006verificación desactivada
9mcgraw199610.1037/1082-989X.1.1.30verificación desactivada
10nakagawa201310.1111/j.2041-210x.2012.00261.xverificación desactivada
11hurlbert198410.2307/1942661verificación desactivada
12welch194710.1093/biomet/34.1-2.28verificación desactivada
13wilcoxon194510.2307/3001968verificación desactivada
14efron197910.1214/aos/1176344552verificación desactivada
15bates201510.18637/jss.v067.i01verificación desactivada
16kuznetsova201710.18637/jss.v082.i13verificación desactivada
17satterthwaite194610.2307/3002019verificación desactivada
18hedges198110.3102/10769986006002107verificación desactivada
19lakens201310.3389/fpsyg.2013.00863verificación desactivada
20shapiro196510.1093/biomet/52.3-4.591verificación desactivada
21fligner197610.1080/01621459.1976.10481517verificación desactivada
22kruskal195210.1080/01621459.1952.10483441verificación desactivada
23tukey194910.2307/3001913verificación desactivada
24holm1979—sin DOI (se enlaza a la URL)
25gelman200610.1198/000313006X152649verificación desactivada
26wasserstein201610.1080/00031305.2016.1154108verificación desactivada
27amrhein201910.1038/d41586-019-00857-9verificación desactivada
28poorter200910.1111/j.1469-8137.2009.02830.xverificación desactivada
29poorter201910.1111/nph.15754verificación desactivada
30wickham201610.1007/978-3-319-24277-4verificación desactivada
31rcore—sin DOI (se enlaza a la URL)

Nota. Se consulta la API de Crossref y se compara el título y el año; requiere conexión a internet al compilar.

sessionInfo()
R version 4.4.2 (2024-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)

Matrix products: default


locale:
[1] LC_COLLATE=Spanish_Colombia.utf8  LC_CTYPE=Spanish_Colombia.utf8   
[3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C                     
[5] LC_TIME=Spanish_Colombia.utf8    

time zone: America/Bogota
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] leaflet_2.2.3   scales_1.4.0    patchwork_1.3.2 ggplot2_4.0.3  

loaded via a namespace (and not attached):
 [1] sass_0.4.10             generics_0.1.4          lattice_0.22-9         
 [4] lme4_2.0-1              digest_0.6.39           magrittr_2.0.4         
 [7] evaluate_1.0.5          grid_4.4.2              RColorBrewer_1.1-3     
[10] fastmap_1.2.0           jsonlite_2.0.0          Matrix_1.7-5           
[13] Formula_1.2-5           mgcv_1.9-4              crosstalk_1.2.2        
[16] numDeriv_2016.8-1.1     jquerylib_0.1.4         reformulas_0.4.4       
[19] Rdpack_2.6.6            cli_3.6.5               rlang_1.1.6            
[22] rbibutils_2.4.1         splines_4.4.2           withr_3.0.2            
[25] cachem_1.1.0            yaml_2.3.12             otel_0.2.0             
[28] tools_4.4.2             nloptr_2.2.1            minqa_1.2.8            
[31] dplyr_1.1.4             boot_1.3-32             mime_0.13              
[34] vctrs_0.6.5             R6_2.6.1                magick_2.9.1           
[37] lifecycle_1.0.5         leaflet.providers_3.0.0 htmlwidgets_1.6.4      
[40] MASS_7.3-65             pkgconfig_2.0.3         pillar_1.11.1          
[43] bslib_0.10.0            lmerTest_3.2-1          gtable_0.3.6           
[46] glue_1.8.0              Rcpp_1.1.1-1.1          table1_1.5.1           
[49] xfun_0.57               tibble_3.3.0            tidyselect_1.2.1       
[52] rstudioapi_0.18.0       knitr_1.51              dichromat_2.0-0.1      
[55] farver_2.1.2            htmltools_0.5.9         nlme_3.1-169           
[58] labeling_0.4.3          rmarkdown_2.31          compiler_4.4.2         
[61] S7_0.2.2               
LS0tDQp0aXRsZTogIlBsYXN0aWNpZGFkIGRlbCDDoXJlYSBmb2xpYXIgZGUgKkJhdWhpbmlhIHBpY3RhKiBmcmVudGUgYSBsYSBleHBvc2ljacOzbiBsdW3DrW5pY2EgZW4gdW4gYm9zcXVlIHVyYmFubyBkZSBDYWxpIg0Kc3VidGl0bGU6ICJVbiBlc3R1ZGlvIG9ic2VydmFjaW9uYWwgamVyw6FycXVpY28gY29uIGVsIMOhcmJvbCBjb21vIHVuaWRhZCBleHBlcmltZW50YWwiDQphdXRob3I6ICJgciBwYXJhbXMkYXV0b3Jlc2AiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclZC8lbS8lWScpYCINCmxhbmc6IGVzDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAyDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIGZpZ19jYXB0aW9uOiB0cnVlDQpwYXJhbXM6DQogIGFyY2hpdm86ICJkYXRvcy5jc3YiICAgIyBvIHJ1dGEgY29tcGxldGEsIHAuIGVqLiAiRTovcGMganVhbi9kaXNlbm8vZGF0b3MuY3N2IiAodXNhciAvIHkgbm8gXCkNCiAgYXV0b3JlczogIkp1YW4gTWFudWVsIENvcmRvYmEgQ2FzdGlsbG8gKDI1MjA4MjApIFZhbGVudGluYSBOb2d1ZXJhIFZlbGFzcXVleiAoMjUyMTA5NCkg4oCUIEdydXBvIDEgLSBGYWN1bHRhZCBkZSBDaWVuY2lhcyBOYXR1cmFsZXMgeSBFeGFjdGFzLCBVbml2ZXJzaWRhZCBkZWwgVmFsbGUiDQogIGNhcnBldGFfZm90b3M6ICJFOi9wYyBqdWFuL2Rpc2VubyIgICAgICMgY2FycGV0YSBjb24gYXJib2wxLmpwZywgYXJib2wyLmpwZy4uLiAodGFtYmllbiBzZSBidXNjYSBlbiAuL2ZvdG9zKQ0KICBhbmNob19mb3RvOiA1MDAgICAgICAgICMgYW5jaG8gKHB4KSBkZSBsYXMgZm90b3MgZGUgbGEgZ2FsZXJpYTsgcmVxdWllcmUgZWwgcGFxdWV0ZSBtYWdpY2sgcGFyYSByZWR1Y2lybGFzDQogIG1pbl9ob2phc19hcmJvbDogMw0KICBkaXN0X2R1cGxpY2Fkb19tOiA1DQogIEJfYm9vdDogNTAwMA0KICBNX2ltcDogMjAwMA0KICBzZW1pbGxhOiAyMDI2MTEwMw0KICBkZWNpbWFsOiAiLCINCiAgaW5zdGFsYXJfcGFxdWV0ZXM6IEZBTFNFICAgIyBUUlVFIHNvbG8gbGEgcHJpbWVyYSB2ZXogKGluc3RhbGFyIGRlbnRybyBkZWwga25pdCBwdWVkZSBjb2xnYXJsbykNCiAgdmVyaWZpY2FyX2RvaTogRkFMU0UgICAgICAgIyBUUlVFIGNvbnN1bHRhIENyb3NzcmVmICh+MzUgbGxhbWFkYXMpOyBwb25sbyBlbiBUUlVFIHNvbG8gY29uIGJ1ZW5hIGNvbmV4aW9uDQogIHRvbGVyYXJfZXJyb3JlczogVFJVRQ0KICBndWFyZGFyX2xpbXBpb3M6IEZBTFNFDQotLS0NCg0KYGBge2NzcywgZWNobz1GQUxTRX0NCi8qID09PT09PSBFc3TDqXRpY2EgdGlwbyBwYXBlciAvIHJlcG9ydGUgbW9kZXJubyA9PT09PT0gKi8NCjpyb290ey0taW5rOiMxZDI3MzM7LS1tdXRlZDojNjQ3MDdkOy0tcnVsZTojZGZlNGU4Oy0tYWNjZW50OiMxZjdhNWM7LS1hY2NlbnQtZDojMTQ1NDNmOy0tYWNjZW50LWw6I2VhZjVmMDsNCi0tc29sOiNFNjlGMDA7LS1zb21icmE6IzAwNzJCMjstLXBhbmVsOiNmNmY4Zjk7DQotLXNhbnM6IkludGVyIiwiU2Vnb2UgVUkiLFJvYm90bywiSGVsdmV0aWNhIE5ldWUiLEFyaWFsLHNhbnMtc2VyaWY7LS1zZXJpZjpHZW9yZ2lhLCJUaW1lcyBOZXcgUm9tYW4iLHNlcmlmO30NCmh0bWx7c2Nyb2xsLWJlaGF2aW9yOnNtb290aH0NCmJvZHl7Zm9udC1mYW1pbHk6dmFyKC0tc2Fucyk7Y29sb3I6dmFyKC0taW5rKTtmb250LXNpemU6MTZweDtsaW5lLWhlaWdodDoxLjcyO2JhY2tncm91bmQ6I2VlZjFmMzt9DQoubWFpbi1jb250YWluZXJ7bWF4LXdpZHRoOjExODBweDtiYWNrZ3JvdW5kOiNmZmY7cGFkZGluZzoxLjJyZW0gMi42cmVtIDRyZW07bWFyZ2luOjEuNHJlbSBhdXRvO2JvcmRlci1yYWRpdXM6MTRweDtib3gtc2hhZG93OjAgMnB4IDI0cHggcmdiYSgyMCw0MCw1MCwuMDgpO30NCiNoZWFkZXJ7Ym9yZGVyLWJvdHRvbTozcHggc29saWQgdmFyKC0tYWNjZW50KTtwYWRkaW5nLWJvdHRvbTouOXJlbTttYXJnaW4tYm90dG9tOjEuNHJlbTt9DQpoMS50aXRsZXtmb250LXNpemU6Mi4wNWVtO2xpbmUtaGVpZ2h0OjEuMTU7Zm9udC13ZWlnaHQ6ODAwO2xldHRlci1zcGFjaW5nOi0uMDE1ZW07bWFyZ2luOi43ZW0gMCAuMjVlbTtjb2xvcjp2YXIoLS1hY2NlbnQtZCk7fQ0KaDMuc3VidGl0bGUsLnN1YnRpdGxle2ZvbnQtc2l6ZToxLjEyZW07Zm9udC13ZWlnaHQ6NDAwO2NvbG9yOnZhcigtLW11dGVkKTttYXJnaW46MCAwIC44ZW07fQ0KaDQuYXV0aG9yLC5hdXRob3J7Zm9udC1zaXplOi45NWVtO2ZvbnQtd2VpZ2h0OjYwMDttYXJnaW46LjJlbSAwIDA7fQ0KaDQuZGF0ZSwuZGF0ZXtmb250LXNpemU6Ljg1ZW07Y29sb3I6dmFyKC0tbXV0ZWQpO21hcmdpbjouMWVtIDAgLjZlbTt9DQpoMXtmb250LXNpemU6MS41NWVtO2ZvbnQtd2VpZ2h0OjgwMDttYXJnaW46Mi40ZW0gMCAuN2VtO3BhZGRpbmctYm90dG9tOi4zZW07Ym9yZGVyLWJvdHRvbToycHggc29saWQgdmFyKC0tYWNjZW50KTtjb2xvcjp2YXIoLS1hY2NlbnQtZCk7bGV0dGVyLXNwYWNpbmc6LS4wMWVtO30NCmgye2ZvbnQtc2l6ZToxLjE4ZW07Zm9udC13ZWlnaHQ6NzAwO21hcmdpbjoyZW0gMCAuNmVtO2NvbG9yOnZhcigtLWluayk7fQ0KaDN7Zm9udC1zaXplOjEuMDJlbTtmb250LXdlaWdodDo3MDA7Y29sb3I6dmFyKC0tYWNjZW50KTttYXJnaW4tdG9wOjEuNGVtO30NCi5oZWFkZXItc2VjdGlvbi1udW1iZXJ7Y29sb3I6dmFyKC0tYWNjZW50KTttYXJnaW4tcmlnaHQ6LjQ1ZW07Zm9udC13ZWlnaHQ6NzAwO30NCnB7bWFyZ2luOi41ZW0gMCAuOTVlbTttYXgtd2lkdGg6ODRjaDt9DQp1bCxvbHttYXgtd2lkdGg6ODRjaDt9bGl7bWFyZ2luLWJvdHRvbTouMzVlbTt9DQpzdXB7Zm9udC1zaXplOi42OGVtO2ZvbnQtd2VpZ2h0OjcwMDtjb2xvcjp2YXIoLS1hY2NlbnQpO2xpbmUtaGVpZ2h0OjA7cGFkZGluZy1sZWZ0OjFweDt9DQphe2NvbG9yOnZhcigtLWFjY2VudCk7dGV4dC1kZWNvcmF0aW9uOm5vbmV9YTpob3Zlcnt0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lfQ0KLmFic3RyYWN0e2JhY2tncm91bmQ6dmFyKC0tYWNjZW50LWwpO2JvcmRlcjoxcHggc29saWQgI2NmZTZkYztib3JkZXItbGVmdDo1cHggc29saWQgdmFyKC0tYWNjZW50KTtib3JkZXItcmFkaXVzOjEwcHg7cGFkZGluZzoxLjFlbSAxLjVlbSAuNWVtO21hcmdpbjoxLjJlbSAwIDEuNGVtO2ZvbnQtc2l6ZTouOTVlbTt9DQouYWJzdHJhY3QgcHttYXJnaW46LjM1ZW0gMCAuNzVlbTttYXgtd2lkdGg6bm9uZTt9DQouYWJzdHJhY3QgcDpmaXJzdC1jaGlsZHtmb250LXNpemU6MS4wNWVtO2ZvbnQtd2VpZ2h0OjgwMDtjb2xvcjp2YXIoLS1hY2NlbnQtZCk7dGV4dC10cmFuc2Zvcm06dXBwZXJjYXNlO2xldHRlci1zcGFjaW5nOi4wNmVtO30NCi5rcGlze2Rpc3BsYXk6Z3JpZDtncmlkLXRlbXBsYXRlLWNvbHVtbnM6cmVwZWF0KGF1dG8tZml0LG1pbm1heCgxODBweCwxZnIpKTtnYXA6MTRweDttYXJnaW46MS4yZW0gMCAyZW07fQ0KLmtwaXtib3JkZXI6MXB4IHNvbGlkIHZhcigtLXJ1bGUpO2JvcmRlci10b3A6NHB4IHNvbGlkIHZhcigtLWFjY2VudCk7Ym9yZGVyLXJhZGl1czoxMnB4O3BhZGRpbmc6Ljg1ZW0gMWVtO2JhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDE4MGRlZywjZmZmLHZhcigtLXBhbmVsKSk7fQ0KLmtwaSAudntmb250LXNpemU6MS43NWVtO2ZvbnQtd2VpZ2h0OjgwMDtsaW5lLWhlaWdodDoxLjE7Y29sb3I6dmFyKC0tYWNjZW50LWQpO30NCi5rcGkgLmx7Zm9udC1zaXplOi43NGVtO3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTtsZXR0ZXItc3BhY2luZzouMDZlbTtjb2xvcjp2YXIoLS1tdXRlZCk7bWFyZ2luLXRvcDouMzVlbTtmb250LXdlaWdodDo3MDA7fQ0KLmtwaSAuc3tmb250LXNpemU6LjgyZW07Y29sb3I6dmFyKC0tbXV0ZWQpO21hcmdpbi10b3A6LjFlbTt9DQouY2FsbG91dHtib3JkZXItbGVmdDo0cHggc29saWQgdmFyKC0tc29tYnJhKTtiYWNrZ3JvdW5kOiNmMmY4ZmM7cGFkZGluZzouN2VtIDEuMWVtIC4yZW07bWFyZ2luOjEuMWVtIDA7Zm9udC1zaXplOi45NWVtO2JvcmRlci1yYWRpdXM6MCA4cHggOHB4IDA7fQ0KLmNhbGxvdXQgcHttYXgtd2lkdGg6bm9uZTt9DQoud2Fybntib3JkZXItbGVmdDo0cHggc29saWQgdmFyKC0tc29sKTtiYWNrZ3JvdW5kOiNmZmY4ZWE7cGFkZGluZzouNmVtIDFlbTttYXJnaW46MWVtIDA7Zm9udC1zaXplOi45M2VtO2JvcmRlci1yYWRpdXM6MCA4cHggOHB4IDA7fQ0KZGV0YWlscy5kZXRhbGxle2JvcmRlcjoxcHggc29saWQgdmFyKC0tcnVsZSk7Ym9yZGVyLWxlZnQ6NHB4IHNvbGlkIHZhcigtLWFjY2VudCk7Ym9yZGVyLXJhZGl1czo4cHg7YmFja2dyb3VuZDp2YXIoLS1wYW5lbCk7cGFkZGluZzouMWVtIDEuMWVtO21hcmdpbjoxZW0gMCAxLjNlbTt9DQpkZXRhaWxzLmRldGFsbGUgc3VtbWFyeXtjdXJzb3I6cG9pbnRlcjtmb250LXdlaWdodDo3MDA7Y29sb3I6dmFyKC0tYWNjZW50LWQpO3BhZGRpbmc6LjU1ZW0gMDtmb250LXNpemU6LjkyZW07fQ0KZGV0YWlscy5kZXRhbGxlW29wZW5dIHN1bW1hcnl7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgdmFyKC0tcnVsZSk7bWFyZ2luLWJvdHRvbTouN2VtO30NCmRldGFpbHMuZGV0YWxsZSBwe2ZvbnQtc2l6ZTouOTRlbTttYXgtd2lkdGg6bm9uZTt9DQouZmlndXJle2JhY2tncm91bmQ6I2ZmZjtib3JkZXI6MXB4IHNvbGlkIHZhcigtLXJ1bGUpO2JvcmRlci1yYWRpdXM6MTJweDtwYWRkaW5nOjFlbSAxZW0gLjRlbTttYXJnaW46MS42ZW0gMDtib3gtc2hhZG93OjAgMXB4IDEwcHggcmdiYSgyMCw0MCw1MCwuMDUpO30NCi5maWd1cmUgaW1nLGltZ3ttYXgtd2lkdGg6MTAwJTt9DQpwLmNhcHRpb24sLmNhcHRpb24sLmZpZ2NhcHtmb250LXNpemU6Ljg0ZW07bGluZS1oZWlnaHQ6MS41O2NvbG9yOiMzMzQwNGM7dGV4dC1hbGlnbjpsZWZ0O2JvcmRlci10b3A6MXB4IHNvbGlkIHZhcigtLXJ1bGUpO3BhZGRpbmctdG9wOi42ZW07bWFyZ2luLXRvcDouN2VtO21heC13aWR0aDpub25lO30NCi5maWdjYXB7bWFyZ2luOi42ZW0gMCAxLjhlbTt9DQpwLmNhcHRpb24gc3Ryb25nOmZpcnN0LWNoaWxkLC5maWdjYXAgYjpmaXJzdC1jaGlsZHtjb2xvcjp2YXIoLS1hY2NlbnQtZCk7fQ0KLmxlYWZsZXQtY29udGFpbmVye2JvcmRlci1yYWRpdXM6MTJweDtib3JkZXI6MXB4IHNvbGlkIHZhcigtLXJ1bGUpO30NCi5odG1sLXdpZGdldHttYXJnaW46MWVtIDAgMDt9DQovKiAtLS0tIHRhYmxhcyBlc3RpbG8gcGFwZXI6IHTDrXR1bG8gYXJyaWJhLCB0cmVzIGzDrW5lYXMsIG5vdGEgYWJham8gLS0tLSAqLw0KLnRjYXB7Zm9udC1mYW1pbHk6dmFyKC0tc2VyaWYpO2ZvbnQtc2l6ZTouOThlbTttYXJnaW46MmVtIDAgLjQ1ZW07bWF4LXdpZHRoOm5vbmU7fQ0KLnRjYXAgLnRue2NvbG9yOnZhcigtLWFjY2VudC1kKTtmb250LXdlaWdodDo4MDA7bWFyZ2luLXJpZ2h0Oi4zNWVtO30NCi50d3tvdmVyZmxvdy14OmF1dG87bWFyZ2luOi4yZW0gMCAuMmVtO30NCnRhYmxlLm50e2ZvbnQtZmFtaWx5OnZhcigtLXNlcmlmKTtib3JkZXItY29sbGFwc2U6Y29sbGFwc2U7d2lkdGg6MTAwJTtmb250LXNpemU6Ljg4ZW07bGluZS1oZWlnaHQ6MS4zNTtib3JkZXItdG9wOjJweCBzb2xpZCAjMTExO2JvcmRlci1ib3R0b206MnB4IHNvbGlkICMxMTE7fQ0KdGFibGUubnQgdGhlYWQgdGh7Zm9udC13ZWlnaHQ6NzAwO3RleHQtYWxpZ246bGVmdDtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMTExO3BhZGRpbmc6LjQ1ZW0gLjdlbTtiYWNrZ3JvdW5kOiNmZmY7fQ0KdGFibGUubnQgdGR7cGFkZGluZzouMzZlbSAuN2VtO3ZlcnRpY2FsLWFsaWduOnRvcDtib3JkZXI6bm9uZTt9DQp0YWJsZS5udCB0Ym9keSB0cjpudGgtY2hpbGQoZXZlbil7YmFja2dyb3VuZDojZjhmOWZhO30NCnRhYmxlLm50IHRib2R5IHRyOmhvdmVye2JhY2tncm91bmQ6I2YxZjZmNDt9DQp0YWJsZS5udCB0ZDpmaXJzdC1jaGlsZHtmb250LXdlaWdodDo2MDA7fQ0KLnRub3Rhe2ZvbnQtZmFtaWx5OnZhcigtLXNlcmlmKTtmb250LXNpemU6LjhlbTtjb2xvcjp2YXIoLS1tdXRlZCk7bWFyZ2luOi4zZW0gMCAxLjhlbTttYXgtd2lkdGg6bm9uZTt9DQoudDF3IHRhYmxle3dpZHRoOjEwMCU7Zm9udC1zaXplOi44OGVtO30NCi50MXcgLlJ0YWJsZTEtdGltZXMgdGgsLnQxdyAuUnRhYmxlMS10aW1lcyB0ZHtwYWRkaW5nOi4zZW0gLjZlbTt9DQoudDF3IC5yb3dsYWJlbHtmb250LXdlaWdodDo2MDA7fQ0KLnQxdyB0aHtmb250LXdlaWdodDo3MDA7Y29sb3I6dmFyKC0taW5rKTtiYWNrZ3JvdW5kOiNmZmY7dGV4dC1hbGlnbjpjZW50ZXI7fQ0KLnQxdyB0aC5yb3dsYWJlbHt0ZXh0LWFsaWduOmxlZnQ7fQ0KLnQxdyB0aGVhZCB0aHtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMTExO30NCi8qIC0tLS0gZ2FsZXLDrWEgZGUgZm90b3MgY29uIG1hcmNvIC0tLS0gKi8NCi5nYWxlcmlhLWZpbHRyb3N7ZGlzcGxheTpmbGV4O2dhcDouNWVtO21hcmdpbjouNGVtIDAgMWVtO2ZsZXgtd3JhcDp3cmFwO30NCi5nYWxlcmlhLWZpbHRyb3MgYnV0dG9ue2JvcmRlcjoxcHggc29saWQgdmFyKC0tcnVsZSk7YmFja2dyb3VuZDojZmZmO2JvcmRlci1yYWRpdXM6OTk5cHg7cGFkZGluZzouM2VtIDEuMDVlbTtmb250LXNpemU6Ljg1ZW07Y3Vyc29yOnBvaW50ZXI7Y29sb3I6dmFyKC0taW5rKTt9DQouZ2FsZXJpYS1maWx0cm9zIGJ1dHRvbi5vbntiYWNrZ3JvdW5kOnZhcigtLWFjY2VudCk7Y29sb3I6I2ZmZjtib3JkZXItY29sb3I6dmFyKC0tYWNjZW50KTt9DQouZ2FsZXJpYXtkaXNwbGF5OmdyaWQ7Z3JpZC10ZW1wbGF0ZS1jb2x1bW5zOnJlcGVhdChhdXRvLWZpbGwsbWlubWF4KDIzMHB4LDFmcikpO2dhcDoyMnB4O21hcmdpbjoxZW0gMCAuNGVtO30NCi5nYWxlcmlhIGZpZ3VyZXttYXJnaW46MDtiYWNrZ3JvdW5kOiNmZmY7cGFkZGluZzoxMHB4IDEwcHggMTJweDtib3JkZXI6MXB4IHNvbGlkIHZhcigtLXJ1bGUpO2JvcmRlci1yYWRpdXM6NHB4O2JveC1zaGFkb3c6MCA2cHggMThweCByZ2JhKDIwLDQwLDUwLC4xMyk7dHJhbnNpdGlvbjp0cmFuc2Zvcm0gLjJzO30NCi5nYWxlcmlhIGZpZ3VyZTpob3Zlcnt0cmFuc2Zvcm06dHJhbnNsYXRlWSgtM3B4KSByb3RhdGUoLS40ZGVnKTt9DQouZ2FsZXJpYSBmaWd1cmUub2N1bHRve2Rpc3BsYXk6bm9uZTt9DQouZ2FsZXJpYSAubWFyY297cG9zaXRpb246cmVsYXRpdmU7YXNwZWN0LXJhdGlvOjQvMztvdmVyZmxvdzpoaWRkZW47YmFja2dyb3VuZDojZTllZGYwO291dGxpbmU6MXB4IHNvbGlkIHJnYmEoMCwwLDAsLjA4KTt9DQouZ2FsZXJpYSAubWFyY28gaW1ne3dpZHRoOjEwMCU7aGVpZ2h0OjEwMCU7b2JqZWN0LWZpdDpjb3ZlcjtjdXJzb3I6em9vbS1pbjtkaXNwbGF5OmJsb2NrO30NCi5nYWxlcmlhIC5iYWRnZXtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6OHB4O2xlZnQ6OHB4O2NvbG9yOiNmZmY7Zm9udC1zaXplOi43ZW07Zm9udC13ZWlnaHQ6ODAwO3BhZGRpbmc6LjE1ZW0gLjY1ZW07Ym9yZGVyLXJhZGl1czo5OTlweDtsZXR0ZXItc3BhY2luZzouMDVlbTt9DQouYmFkZ2Uuc29se2JhY2tncm91bmQ6dmFyKC0tc29sKTt9LmJhZGdlLnNvbWJyYXtiYWNrZ3JvdW5kOnZhcigtLXNvbWJyYSk7fQ0KLmdhbGVyaWEgZmlnY2FwdGlvbntmb250LXNpemU6Ljg2ZW07bWFyZ2luLXRvcDouNmVtO2xpbmUtaGVpZ2h0OjEuMzU7fQ0KLmdhbGVyaWEgLm1ldGF7Y29sb3I6dmFyKC0tbXV0ZWQpO2ZvbnQtc2l6ZTouOWVtO30NCi5nYWxlcmlhIC52YWNpb3tkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2p1c3RpZnktY29udGVudDpjZW50ZXI7Ym9yZGVyOjJweCBkYXNoZWQgI2I5YzJjOTt0ZXh0LWFsaWduOmNlbnRlcjtjb2xvcjp2YXIoLS1tdXRlZCk7Zm9udC1zaXplOi44ZW07YmFja2dyb3VuZDpyZXBlYXRpbmctbGluZWFyLWdyYWRpZW50KDQ1ZGVnLCNmNGY2ZjcsI2Y0ZjZmNyA4cHgsI2VlZjFmMyA4cHgsI2VlZjFmMyAxNnB4KTt9DQoubGJ7cG9zaXRpb246Zml4ZWQ7aW5zZXQ6MDtiYWNrZ3JvdW5kOnJnYmEoMTAsMTgsMjQsLjkpO2Rpc3BsYXk6bm9uZTthbGlnbi1pdGVtczpjZW50ZXI7anVzdGlmeS1jb250ZW50OmNlbnRlcjtmbGV4LWRpcmVjdGlvbjpjb2x1bW47ei1pbmRleDo5OTk5O2N1cnNvcjp6b29tLW91dDt9DQoubGIub257ZGlzcGxheTpmbGV4O30NCi5sYiBpbWd7bWF4LXdpZHRoOjkydnc7bWF4LWhlaWdodDo4NHZoO2JvcmRlcjoxMHB4IHNvbGlkICNmZmY7Ym9yZGVyLXJhZGl1czozcHg7fQ0KLmxiIC5sYmNhcHtjb2xvcjojZmZmO21hcmdpbi10b3A6LjhlbTtmb250LXNpemU6Ljk1ZW07fQ0Kb2wucmVmc3tmb250LXNpemU6LjgyZW07bGluZS1oZWlnaHQ6MS41O3BhZGRpbmctbGVmdDoyZW07bWF4LXdpZHRoOm5vbmU7fQ0Kb2wucmVmcyBsaXttYXJnaW4tYm90dG9tOi40NWVtO30NCiNUT0MsLnRvY2lmeXtmb250LXNpemU6LjgyZW07fQ0KLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmUsLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmU6aG92ZXIsLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmU6Zm9jdXN7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1hY2NlbnQpO2JvcmRlci1jb2xvcjp2YXIoLS1hY2NlbnQpO30NCnByZXtmb250LXNpemU6Ljc4ZW07YmFja2dyb3VuZDojZmFmYmZiO2JvcmRlcjoxcHggc29saWQgdmFyKC0tcnVsZSk7Ym9yZGVyLXJhZGl1czo2cHg7fQ0KQG1lZGlhIHByaW50eyNUT0MsLnRvY2lmeS13cmFwcGVye2Rpc3BsYXk6bm9uZX0ubWFpbi1jb250YWluZXJ7bWF4LXdpZHRoOjEwMCU7Ym94LXNoYWRvdzpub25lfWRldGFpbHMuZGV0YWxsZXtkaXNwbGF5OmJsb2NrfX0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIDAuIFBhcXVldGVzLCBvcGNpb25lcyBnbG9iYWxlcyB5IHV0aWxpZGFkZXMNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGVycm9yID0gaXNUUlVFKHBhcmFtcyR0b2xlcmFyX2Vycm9yZXMpLCBjb21tZW50ID0gTkEsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIGZpZy53aWR0aCA9IDcuMiwgZmlnLmhlaWdodCA9IDQuNiwNCiAgICAgICAgICAgICAgICAgICAgICBkcGkgPSAxMTAsIG91dC53aWR0aCA9ICIxMDAlIikNCm9wdGlvbnMoT3V0RGVjID0gcGFyYW1zJGRlY2ltYWwsIHNjaXBlbiA9IDk5OSwgdGltZW91dCA9IDIwKQ0Kc2V0LnNlZWQocGFyYW1zJHNlbWlsbGEpDQpwYXF1ZXRlc19yZXEgPC0gYygiZ2dwbG90MiIsICJwYXRjaHdvcmsiLCAic2NhbGVzIikNCnBhcXVldGVzX29wYyA8LSBjKCJsbWU0IiwgImxtZXJUZXN0IiwgImxlYWZsZXQiLCAianNvbmxpdGUiLCAidGFibGUxIiwgIm1hZ2ljayIpDQppZiAoaXNUUlVFKHBhcmFtcyRpbnN0YWxhcl9wYXF1ZXRlcykpIHsNCiAgZmFsdCA8LSBjKHBhcXVldGVzX3JlcSwgcGFxdWV0ZXNfb3BjKVshdmFwcGx5KGMocGFxdWV0ZXNfcmVxLCBwYXF1ZXRlc19vcGMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1aXJlTmFtZXNwYWNlLCBsb2dpY2FsKDEpLCBxdWlldGx5ID0gVFJVRSldDQogIGlmIChsZW5ndGgoZmFsdCkgPiAwKSB0cnkoaW5zdGFsbC5wYWNrYWdlcyhmYWx0LCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKSwgc2lsZW50ID0gVFJVRSkNCn0NCmxpYnJhcnkoZ2dwbG90Mik7IGxpYnJhcnkocGF0Y2h3b3JrKTsgbGlicmFyeShzY2FsZXMpDQpIQVNfTE1FUiA8LSByZXF1aXJlTmFtZXNwYWNlKCJsbWU0IiwgcXVpZXRseSA9IFRSVUUpICYmIHJlcXVpcmVOYW1lc3BhY2UoImxtZXJUZXN0IiwgcXVpZXRseSA9IFRSVUUpDQpIQVNfTEVBRkxFVCA8LSByZXF1aXJlTmFtZXNwYWNlKCJsZWFmbGV0IiwgcXVpZXRseSA9IFRSVUUpDQpIQVNfSlNPTiA8LSByZXF1aXJlTmFtZXNwYWNlKCJqc29ubGl0ZSIsIHF1aWV0bHkgPSBUUlVFKQ0KSEFTX1QxIDwtIHJlcXVpcmVOYW1lc3BhY2UoInRhYmxlMSIsIHF1aWV0bHkgPSBUUlVFKQ0KSEFTX01BR0lDSyA8LSByZXF1aXJlTmFtZXNwYWNlKCJtYWdpY2siLCBxdWlldGx5ID0gVFJVRSkNCg0KIyAtLS0tIEZvcm1hdG8gbnVtw6lyaWNvIChjb21hIGRlY2ltYWwgcG9yIGRlZmVjdG8pIC0tLS0NCmZ4IDwtIGZ1bmN0aW9uKHgsIGQgPSAxKSB7DQogIGlmIChpcy5udWxsKHgpIHx8IGxlbmd0aCh4KSA9PSAwKSByZXR1cm4oIm4vZCIpDQogIHZhcHBseSh4LCBmdW5jdGlvbih2KSBpZiAoaXMubmEodikgfHwgIWlzLmZpbml0ZSh2KSkgIm4vZCIgZWxzZQ0KICAgIGZvcm1hdEModiwgZm9ybWF0ID0gImYiLCBkaWdpdHMgPSBkLCBkZWNpbWFsLm1hcmsgPSBwYXJhbXMkZGVjaW1hbCksIGNoYXJhY3RlcigxKSkNCn0NCmZwIDwtIGZ1bmN0aW9uKHAsIGQgPSAzKSB7DQogIGlmIChpcy5udWxsKHApIHx8IGxlbmd0aChwKSA9PSAwKSByZXR1cm4oIm4vZCIpDQogIHZhcHBseShwLCBmdW5jdGlvbih2KSBpZiAoaXMubmEodikpICJuL2QiIGVsc2UgaWYgKHYgPCAxMF4tZCkgcGFzdGUwKCI8IDAiLCBwYXJhbXMkZGVjaW1hbCwgc3RycmVwKCIwIiwgZCAtIDEpLCAiMSIpIGVsc2UNCiAgICBmb3JtYXRDKHYsIGZvcm1hdCA9ICJmIiwgZGlnaXRzID0gZCwgZGVjaW1hbC5tYXJrID0gcGFyYW1zJGRlY2ltYWwpLCBjaGFyYWN0ZXIoMSkpDQp9DQpmcHAgPC0gZnVuY3Rpb24ocCwgZCA9IDMpIHsgcyA8LSBmcChwLCBkKTsgaWZlbHNlKGdyZXBsKCJePCIsIHMpLCBwYXN0ZTAoIipwKiAiLCBzKSwgaWZlbHNlKHMgPT0gIm4vZCIsICIqcCogbi9kIiwgcGFzdGUwKCIqcCogPSAiLCBzKSkpIH0NCmZjaSA8LSBmdW5jdGlvbihsLCB1LCBkID0gMikgcGFzdGUwKCJbIiwgZngobCwgZCksICI7ICIsIGZ4KHUsIGQpLCAiXSIpDQpjdiAgPC0gZnVuY3Rpb24oeCkgMTAwICogc2QoeCkgLyBtZWFuKHgpDQpzYWZlIDwtIGZ1bmN0aW9uKGV4cHIpIHRyeUNhdGNoKGV4cHIsIGVycm9yID0gZnVuY3Rpb24oZSkgTlVMTCkNCmAlfHwlYCA8LSBmdW5jdGlvbihhLCBiKSBpZiAoaXMubnVsbChhKSB8fCBsZW5ndGgoYSkgPT0gMCB8fCAobGVuZ3RoKGEpID09IDEgJiYgaXMubmEoYSkpKSBiIGVsc2UgYQ0KDQojIC0tLS0gVGFibGFzIGVzdGlsbyBwYXBlcjogdMOtdHVsbyBhcnJpYmEsIHRyZXMgbMOtbmVhcywgbm90YSBhbCBwaWUgLS0tLQ0KLm5vdGEgPC0gbmV3LmVudigpOyAubm90YSR0eHQgPC0gIiINCm5vdGFfaHRtbCA8LSBmdW5jdGlvbigpIHsNCiAgaWYgKCFuemNoYXIoLm5vdGEkdHh0KSkgcmV0dXJuKCIiKQ0KICBoIDwtIHBhc3RlMCgnPHAgY2xhc3M9InRub3RhIj48Yj5Ob3RhLjwvYj4gJywgLm5vdGEkdHh0LCAnPC9wPlxuXG4nKTsgLm5vdGEkdHh0IDwtICIiOyBoDQp9DQp0YWJsYSA8LSBmdW5jdGlvbihkZiwgYWxpZ24gPSBOVUxMLCBjb2wubmFtZXMgPSBOVUxMKSB7DQogICMgVGFibGEgSFRNTCBwcm9waWEgY29uIGVuY2FiZXphZG8gZXhwbMOtY2l0byAoPHRoZWFkPiksIGVtaXRpZGEgY29tbyBibG9xdWUgSFRNTCBjcnVkbw0KICBpZiAobnJvdyhkZikgPT0gMCkgcmV0dXJuKGludmlzaWJsZSgpKQ0KICBubSA8LSBpZiAoaXMubnVsbChjb2wubmFtZXMpKSBuYW1lcyhkZikgZWxzZSBjb2wubmFtZXMNCiAgYWwgPC0gaWYgKGlzLm51bGwoYWxpZ24pKSByZXAoImwiLCBuY29sKGRmKSkgZWxzZSByZXBfbGVuKHN0cnNwbGl0KGFsaWduLCAiIilbWzFdXSwgbmNvbChkZikpDQogIGFtYXAgPC0gYyhsID0gImxlZnQiLCByID0gInJpZ2h0IiwgYyA9ICJjZW50ZXIiKQ0KICBjZWxkYSA8LSBmdW5jdGlvbih4KSB7DQogICAgeCA8LSBhcy5jaGFyYWN0ZXIoeCk7IHhbaXMubmEoeCkgfCB4ID09ICJOQSJdIDwtICLigJQiDQogICAgeCA8LSBnc3ViKCI8ICIsICImbHQ7ICIsIHgsIGZpeGVkID0gVFJVRSkNCiAgICBnc3ViKCJcXCooW14qXSspXFwqIiwgIjxpPlxcMTwvaT4iLCB4KQ0KICB9DQogIG0gPC0gZG8uY2FsbChjYmluZCwgbGFwcGx5KGRmLCBmdW5jdGlvbih6KSBjZWxkYSh6KSkpDQogIHRoIDwtIHBhc3RlMCgnPHRoIHN0eWxlPSJ0ZXh0LWFsaWduOicsIGFtYXBbYWxdLCAnIj4nLCBjZWxkYShubSksICc8L3RoPicsIGNvbGxhcHNlID0gIiIpDQogIGZpbGFzIDwtIHZhcHBseShzZXFfbGVuKG5yb3cobSkpLCBmdW5jdGlvbihpKQ0KICAgIHBhc3RlMCgnPHRyPicsIHBhc3RlMCgnPHRkIHN0eWxlPSJ0ZXh0LWFsaWduOicsIGFtYXBbYWxdLCAnIj4nLCBtW2ksIF0sICc8L3RkPicsIGNvbGxhcHNlID0gIiIpLCAnPC90cj4nKSwgY2hhcmFjdGVyKDEpKQ0KICBodG1sIDwtIHBhc3RlMCgnPHRhYmxlIGNsYXNzPSJudCI+PHRoZWFkPjx0cj4nLCB0aCwgJzwvdHI+PC90aGVhZD48dGJvZHk+XG4nLCBwYXN0ZShmaWxhcywgY29sbGFwc2UgPSAiXG4iKSwgJ1xuPC90Ym9keT48L3RhYmxlPicpDQogIGNhdCgnXG5gYGB7PWh0bWx9XG48ZGl2IGNsYXNzPSJ0dyI+XG4nLCBodG1sLCAnXG48L2Rpdj5cbmBgYFxuXG4nLCBub3RhX2h0bWwoKSwgc2VwID0gIiIpDQp9DQojIFRhYmxhIGdlbmVyYWRhIGNvbiB7dGFibGUxfSAoZXN0w6l0aWNhIGRlIFRhYmxlIDEgZGUgYXJ0w61jdWxvKTsgc2kgZmFsbGEsIGNhZSBhIGthYmxlDQp0MV9vdXQgPC0gZnVuY3Rpb24odDEpIHsNCiAgaCA8LSB0cnlDYXRjaChwYXN0ZShhcy5jaGFyYWN0ZXIoa25pdHI6OmtuaXRfcHJpbnQodDEpKSwgY29sbGFwc2UgPSAiXG4iKSwgZXJyb3IgPSBmdW5jdGlvbihlKSAiIikNCiAgaWYgKCFuemNoYXIoaCkpIHsNCiAgICBkZiA8LSB0cnlDYXRjaChhcy5kYXRhLmZyYW1lKHQxKSwgZXJyb3IgPSBmdW5jdGlvbihlKSBOVUxMKQ0KICAgIGlmICghaXMubnVsbChkZikpIHsgdGFibGEoZGYpOyByZXR1cm4oaW52aXNpYmxlKCkpIH0NCiAgICBjYXQoIjxwPjxpPk5vIHNlIHB1ZG8gZ2VuZXJhciBsYSB0YWJsYS48L2k+PC9wPlxuIik7IHJldHVybihpbnZpc2libGUoKSkNCiAgfQ0KICBjYXQoJ1xuYGBgez1odG1sfVxuPGRpdiBjbGFzcz0idHcgdDF3Ij5cbicsIGgsICdcbjwvZGl2PlxuYGBgXG5cbicsIG5vdGFfaHRtbCgpLCBzZXAgPSAiIikNCn0NCg0KIyAtLS0tIE51bWVyYWNpw7NuIGF1dG9tw6F0aWNhIGRlIGZpZ3VyYXMgeSB0YWJsYXMgKHNlIGZpamEgYXF1w60gZWwgb3JkZW4pIC0tLS0NCkZJRyA8LSBjKCJkaXNlbm8iLCAiY29tcGxldGl0dWQiLCAibWFwYV9pbnQiLCAibWFwYSIsICJmb3RvcyIsICJwcm94eSIsICJwb3JhcmJvbCIsICJ2YXJpYW56YSIsICJhdGlwaWNvcyIsDQogICAgICAgICAiZXhwb3NpY2lvbiIsICJwZXJtIiwgImZvcmVzdCIsICJkaWFnIiwgInR1a2V5IiwgInNlbnNpYiIsICJqYWNrIiwgInBvdGVuY2lhIiwNCiAgICAgICAgICJmb3JtYSIsICJsaXRlcmF0dXJhIikNClRBQiA8LSBjKCJjYXIiLCAidmFycyIsICJxYyIsICJkZXNjIiwgImF0aXAiLCAicHNldWRvIiwgImJhdGVyaWEiLCAibWl4dG8iLCAiYW5vdmEiLCAidHVrZXkiLCAic2VucyIsICJsaXQiLCAicHJvdG9jb2xvIiwgImRhdG9zIiwgImRvaSIpDQpmbiAgIDwtIGZ1bmN0aW9uKGspIHsgaSA8LSBtYXRjaChrLCBGSUcpOyBpZiAoaXMubmEoaSkpIHN0b3AoIkZpZ3VyYSBubyByZWdpc3RyYWRhOiAiLCBrKTsgaSB9DQp0biAgIDwtIGZ1bmN0aW9uKGspIHsgaSA8LSBtYXRjaChrLCBUQUIpOyBpZiAoaXMubmEoaSkpIHN0b3AoIlRhYmxhIG5vIHJlZ2lzdHJhZGE6ICIsIGspOyBpIH0NCmZyZWYgPC0gZnVuY3Rpb24oaykgcGFzdGUwKCIqKkZpZy4gIiwgZm4oayksICIqKiIpDQp0cmVmIDwtIGZ1bmN0aW9uKGspIHBhc3RlMCgiKipUYWJsYSAiLCB0bihrKSwgIioqIikNCmZjYXAgPC0gZnVuY3Rpb24oaywgdGl0dWxvLCB0ZXh0byA9ICIiKSBwYXN0ZTAoIioqRmlnLiAiLCBmbihrKSwgIiB8ICIsIHRpdHVsbywgIi4qKiAiLCB0ZXh0bykNCnRjYXAgPC0gZnVuY3Rpb24oaywgdGl0dWxvLCB0ZXh0byA9ICIiKSB7ICAgICAgICAgICMgdMOtdHVsbyBhcnJpYmE7IGxhIG5vdGEgc2UgaW1wcmltZSBiYWpvIGxhIHRhYmxhDQogIC5ub3RhJHR4dCA8LSB0ZXh0bw0KICBwYXN0ZTAoJzxkaXYgY2xhc3M9InRjYXAiPjxzcGFuIGNsYXNzPSJ0biI+VGFibGEgJywgdG4oayksICcuPC9zcGFuPiA8Yj4nLCB0aXR1bG8sICc8L2I+PC9kaXY+XG5cbicpDQp9DQpmY2FwX2h0bWwgPC0gZnVuY3Rpb24oaywgdGl0dWxvLCB0ZXh0byA9ICIiKSBwYXN0ZTAoJzxkaXYgY2xhc3M9ImZpZ2NhcCI+PGI+RmlnLiAnLCBmbihrKSwgJyB8ICcsIHRpdHVsbywgJy48L2I+ICcsIHRleHRvLCAnPC9kaXY+XG4nKQ0KDQojIC0tLS0gU2lzdGVtYSBkZSBjaXRhcyBjb24gc3VwZXLDrW5kaWNlIG51bcOpcmljbyAob3JkZW4gZGUgcHJpbWVyYSBhcGFyaWNpw7NuKSAtLS0tDQpSRUYgPC0gbGlzdCgpDQpyZWYgPC0gZnVuY3Rpb24oa2V5LCB0ZXh0bywgdGl0LCBhbmlvLCBkb2kgPSBOQSwgdXJsID0gTkEpIFJFRltba2V5XV0gPDwtIGxpc3QodGV4dG8gPSB0ZXh0bywgdGl0ID0gdGl0LCBhbmlvID0gYW5pbywgZG9pID0gZG9pLCB1cmwgPSB1cmwpDQouY2l0IDwtIG5ldy5lbnYoKTsgLmNpdCRvcmRlbiA8LSBjaGFyYWN0ZXIoMCkNCnJlZyA8LSBmdW5jdGlvbihrZXlzKSB7DQogIGZvciAoayBpbiBrZXlzKSB7DQogICAgaWYgKGlzLm51bGwoUkVGW1trXV0pKSBzdG9wKCJSZWZlcmVuY2lhIG5vIGRlZmluaWRhOiAiLCBrKQ0KICAgIGlmICghKGsgJWluJSAuY2l0JG9yZGVuKSkgLmNpdCRvcmRlbiA8LSBjKC5jaXQkb3JkZW4sIGspDQogIH0NCiAgbWF0Y2goa2V5cywgLmNpdCRvcmRlbikNCn0NCnJhbmdvIDwtIGZ1bmN0aW9uKG4pIHsNCiAgbiA8LSBzb3J0KHVuaXF1ZShuKSk7IGlmIChsZW5ndGgobikgPT0gMSkgcmV0dXJuKGFzLmNoYXJhY3RlcihuKSkNCiAgZ3JwIDwtIHNwbGl0KG4sIGN1bXN1bShjKDEsIGRpZmYobikgIT0gMSkpKQ0KICBwYXN0ZSh2YXBwbHkoZ3JwLCBmdW5jdGlvbihnKSBpZiAobGVuZ3RoKGcpID49IDMpIHBhc3RlMChtaW4oZyksICJcdTIwMTMiLCBtYXgoZykpIGVsc2UgcGFzdGUoZywgY29sbGFwc2UgPSAiLCIpLCBjaGFyYWN0ZXIoMSkpLCBjb2xsYXBzZSA9ICIsIikNCn0NCmNpdGUgPC0gZnVuY3Rpb24oLi4uKSBwYXN0ZTAoIjxzdXA+IiwgcmFuZ28ocmVnKGMoLi4uKSkpLCAiPC9zdXA+IikNCmNuICAgPC0gZnVuY3Rpb24oLi4uKSByYW5nbyhyZWcoYyguLi4pKSkNCg0KIyAtLS0tIFRlbWEgZ3LDoWZpY28geSBwYWxldGFzIChPa2FiZS1JdG8sIGFwdGEgcGFyYSBkYWx0b25pc21vKSAtLS0tDQpDT0wgPC0gYyhzb2wgPSAiI0U2OUYwMCIsIHNvbWJyYSA9ICIjMDA3MkIyIikNCnRoZW1lX25hdCA8LSBmdW5jdGlvbihiYXNlID0gMTAuNSkgew0KICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IGJhc2UpICsNCiAgICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkyMCIsIGxpbmV3aWR0aCA9IC40KSwNCiAgICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5MjAiLCBsaW5ld2lkdGggPSAuNCksDQogICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJncmV5MTUiKSwNCiAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXk5MyIsIGxpbmV3aWR0aCA9IC4zKSwNCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSBiYXNlIC0gMSksDQogICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCguOSwgImxpbmVzIiksDQogICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gYmFzZSArIDEpLA0KICAgICAgICAgIHBsb3QudGFnID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSBiYXNlICsgMyksDQogICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkNCn0NCnRoZW1lX3NldCh0aGVtZV9uYXQoKSkNClIgPC0gbGlzdCgpICAgIyBjb250ZW5lZG9yIGRlIHRvZG9zIGxvcyByZXN1bHRhZG9zIG51bcOpcmljb3MgdXNhZG9zIGVuIGVsIHRleHRvDQpgYGANCg0KYGBge3IgcmVmZXJlbmNpYXMsIGluY2x1ZGU9RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBCYXNlIGRlIHJlZmVyZW5jaWFzLiBDYWRhIERPSSBzZSBjb250cmFzdGEgY29uIENyb3NzcmVmIGFsIGNvbXBpbGFyIChBcMOpbmRpY2UpLg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnJlZigid3JpZ2h0MjAxNyIsICJXcmlnaHQsIEkuIEouIDxpPmV0IGFsLjwvaT4gR2xvYmFsIGNsaW1hdGljIGRyaXZlcnMgb2YgbGVhZiBzaXplLiA8aT5TY2llbmNlPC9pPiA8Yj4zNTc8L2I+LCA5MTdcdTIwMTM5MjEgKDIwMTcpLiIsDQogICAgIkdsb2JhbCBjbGltYXRpYyBkcml2ZXJzIG9mIGxlYWYgc2l6ZSIsIDIwMTcsICIxMC4xMTI2L3NjaWVuY2UuYWFsNDc2MCIpDQpyZWYoInBhcmtodXJzdDE5NzIiLCAiUGFya2h1cnN0LCBELiBGLiAmIExvdWNrcywgTy4gTC4gT3B0aW1hbCBsZWFmIHNpemUgaW4gcmVsYXRpb24gdG8gZW52aXJvbm1lbnQuIDxpPkouIEVjb2wuPC9pPiA8Yj42MDwvYj4sIDUwNVx1MjAxMzUzNyAoMTk3MikuIiwNCiAgICAiT3B0aW1hbCBsZWFmIHNpemUgaW4gcmVsYXRpb24gdG8gZW52aXJvbm1lbnQiLCAxOTcyLCAiMTAuMjMwNy8yMjU4MzU5IikNCnJlZigibWljaGFsZXR6MjAxNSIsICJNaWNoYWxldHosIFMuIFQuIDxpPmV0IGFsLjwvaT4gUGxhbnQgdGhlcm1vcmVndWxhdGlvbjogZW5lcmdldGljcywgdHJhaXRcdTIwMTNlbnZpcm9ubWVudCBpbnRlcmFjdGlvbnMsIGFuZCBjYXJib24gZWNvbm9taWNzLiA8aT5UcmVuZHMgRWNvbC4gRXZvbC48L2k+IDxiPjMwPC9iPiwgNzE0XHUyMDEzNzI0ICgyMDE1KS4iLA0KICAgICJQbGFudCB0aGVybW9yZWd1bGF0aW9uOiBlbmVyZ2V0aWNzLCB0cmFpdC1lbnZpcm9ubWVudCBpbnRlcmFjdGlvbnMsIGFuZCBjYXJib24gZWNvbm9taWNzIiwgMjAxNSwgIjEwLjEwMTYvai50cmVlLjIwMTUuMDkuMDA2IikNCnJlZigiZ2l2bmlzaDE5ODgiLCAiR2l2bmlzaCwgVC4gSi4gQWRhcHRhdGlvbiB0byBzdW4gYW5kIHNoYWRlOiBhIHdob2xlLXBsYW50IHBlcnNwZWN0aXZlLiA8aT5BdXN0LiBKLiBQbGFudCBQaHlzaW9sLjwvaT4gPGI+MTU8L2I+LCA2M1x1MjAxMzkyICgxOTg4KS4iLA0KICAgICJBZGFwdGF0aW9uIHRvIHN1biBhbmQgc2hhZGU6IGEgd2hvbGUtcGxhbnQgcGVyc3BlY3RpdmUiLCAxOTg4LCAiMTAuMTA3MS9QUDk4ODAwNjMiKQ0KcmVmKCJ2YWxsYWRhcmVzMjAwOCIsICJWYWxsYWRhcmVzLCBGLiAmIE5paW5lbWV0cywgXHUwMGRjLiBTaGFkZSB0b2xlcmFuY2UsIGEga2V5IHBsYW50IGZlYXR1cmUgb2YgY29tcGxleCBuYXR1cmUgYW5kIGNvbnNlcXVlbmNlcy4gPGk+QW5udS4gUmV2LiBFY29sLiBFdm9sLiBTeXN0LjwvaT4gPGI+Mzk8L2I+LCAyMzdcdTIwMTMyNTcgKDIwMDgpLiIsDQogICAgIlNoYWRlIHRvbGVyYW5jZSwgYSBrZXkgcGxhbnQgZmVhdHVyZSBvZiBjb21wbGV4IG5hdHVyZSBhbmQgY29uc2VxdWVuY2VzIiwgMjAwOCwgIjEwLjExNDYvYW5udXJldi5lY29sc3lzLjM5LjExMDcwNy4xNzM1MDYiKQ0KcmVmKCJwb29ydGVyMjAwOSIsICJQb29ydGVyLCBILiwgTmlpbmVtZXRzLCBcdTAwZGMuLCBQb29ydGVyLCBMLiwgV3JpZ2h0LCBJLiBKLiAmIFZpbGxhciwgUi4gQ2F1c2VzIGFuZCBjb25zZXF1ZW5jZXMgb2YgdmFyaWF0aW9uIGluIGxlYWYgbWFzcyBwZXIgYXJlYSAoTE1BKTogYSBtZXRhLWFuYWx5c2lzLiA8aT5OZXcgUGh5dG9sLjwvaT4gPGI+MTgyPC9iPiwgNTY1XHUyMDEzNTg4ICgyMDA5KS4iLA0KICAgICJDYXVzZXMgYW5kIGNvbnNlcXVlbmNlcyBvZiB2YXJpYXRpb24gaW4gbGVhZiBtYXNzIHBlciBhcmVhIChMTUEpOiBhIG1ldGEtYW5hbHlzaXMiLCAyMDA5LCAiMTAuMTExMS9qLjE0NjktODEzNy4yMDA5LjAyODMwLngiKQ0KcmVmKCJwb29ydGVyMjAxOSIsICJQb29ydGVyLCBILiA8aT5ldCBhbC48L2k+IEEgbWV0YS1hbmFseXNpcyBvZiBwbGFudCByZXNwb25zZXMgdG8gbGlnaHQgaW50ZW5zaXR5IGZvciA3MCB0cmFpdHMgcmFuZ2luZyBmcm9tIG1vbGVjdWxlcyB0byB3aG9sZSBwbGFudCBwZXJmb3JtYW5jZS4gPGk+TmV3IFBoeXRvbC48L2k+IDxiPjIyMzwvYj4sIDEwNzNcdTIwMTMxMTA1ICgyMDE5KS4iLA0KICAgICJBIG1ldGEtYW5hbHlzaXMgb2YgcGxhbnQgcmVzcG9uc2VzIHRvIGxpZ2h0IGludGVuc2l0eSBmb3IgNzAgdHJhaXRzIHJhbmdpbmcgZnJvbSBtb2xlY3VsZXMgdG8gd2hvbGUgcGxhbnQgcGVyZm9ybWFuY2UiLCAyMDE5LCAiMTAuMTExMS9ucGguMTU3NTQiKQ0KcmVmKCJ3cmlnaHQyMDA0IiwgIldyaWdodCwgSS4gSi4gPGk+ZXQgYWwuPC9pPiBUaGUgd29ybGR3aWRlIGxlYWYgZWNvbm9taWNzIHNwZWN0cnVtLiA8aT5OYXR1cmU8L2k+IDxiPjQyODwvYj4sIDgyMVx1MjAxMzgyNyAoMjAwNCkuIiwNCiAgICAiVGhlIHdvcmxkd2lkZSBsZWFmIGVjb25vbWljcyBzcGVjdHJ1bSIsIDIwMDQsICIxMC4xMDM4L25hdHVyZTAyNDAzIikNCnJlZigicGVyZXoyMDEzIiwgIlBcdTAwZTlyZXotSGFyZ3VpbmRlZ3V5LCBOLiA8aT5ldCBhbC48L2k+IE5ldyBoYW5kYm9vayBmb3Igc3RhbmRhcmRpc2VkIG1lYXN1cmVtZW50IG9mIHBsYW50IGZ1bmN0aW9uYWwgdHJhaXRzIHdvcmxkd2lkZS4gPGk+QXVzdC4gSi4gQm90LjwvaT4gPGI+NjE8L2I+LCAxNjdcdTIwMTMyMzQgKDIwMTMpLiIsDQogICAgIk5ldyBoYW5kYm9vayBmb3Igc3RhbmRhcmRpc2VkIG1lYXN1cmVtZW50IG9mIHBsYW50IGZ1bmN0aW9uYWwgdHJhaXRzIHdvcmxkd2lkZSIsIDIwMTMsICIxMC4xMDcxL0JUMTIyMjUiKQ0KcmVmKCJ2aW9sbGUyMDA3IiwgIlZpb2xsZSwgQy4gPGk+ZXQgYWwuPC9pPiBMZXQgdGhlIGNvbmNlcHQgb2YgdHJhaXQgYmUgZnVuY3Rpb25hbCEgPGk+T2lrb3M8L2k+IDxiPjExNjwvYj4sIDg4Mlx1MjAxMzg5MiAoMjAwNykuIiwNCiAgICAiTGV0IHRoZSBjb25jZXB0IG9mIHRyYWl0IGJlIGZ1bmN0aW9uYWwhIiwgMjAwNywgIjEwLjExMTEvai4wMDMwLTEyOTkuMjAwNy4xNTU1OS54IikNCnJlZigic2NobmVpZGVyMjAxMiIsICJTY2huZWlkZXIsIEMuIEEuLCBSYXNiYW5kLCBXLiBTLiAmIEVsaWNlaXJpLCBLLiBXLiBOSUggSW1hZ2UgdG8gSW1hZ2VKOiAyNSB5ZWFycyBvZiBpbWFnZSBhbmFseXNpcy4gPGk+TmF0LiBNZXRob2RzPC9pPiA8Yj45PC9iPiwgNjcxXHUyMDEzNjc1ICgyMDEyKS4iLA0KICAgICJOSUggSW1hZ2UgdG8gSW1hZ2VKOiAyNSB5ZWFycyBvZiBpbWFnZSBhbmFseXNpcyIsIDIwMTIsICIxMC4xMDM4L25tZXRoLjIwODkiKQ0KcmVmKCJodXJsYmVydDE5ODQiLCAiSHVybGJlcnQsIFMuIEguIFBzZXVkb3JlcGxpY2F0aW9uIGFuZCB0aGUgZGVzaWduIG9mIGVjb2xvZ2ljYWwgZmllbGQgZXhwZXJpbWVudHMuIDxpPkVjb2wuIE1vbm9nci48L2k+IDxiPjU0PC9iPiwgMTg3XHUyMDEzMjExICgxOTg0KS4iLA0KICAgICJQc2V1ZG9yZXBsaWNhdGlvbiBhbmQgdGhlIGRlc2lnbiBvZiBlY29sb2dpY2FsIGZpZWxkIGV4cGVyaW1lbnRzIiwgMTk4NCwgIjEwLjIzMDcvMTk0MjY2MSIpDQpyZWYoImJhdGVzMjAxNSIsICJCYXRlcywgRC4sIE1cdTAwZTRjaGxlciwgTS4sIEJvbGtlciwgQi4gJiBXYWxrZXIsIFMuIEZpdHRpbmcgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWxzIHVzaW5nIGxtZTQuIDxpPkouIFN0YXQuIFNvZnR3LjwvaT4gPGI+Njc8L2I+LCAxXHUyMDEzNDggKDIwMTUpLiIsDQogICAgIkZpdHRpbmcgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWxzIHVzaW5nIGxtZTQiLCAyMDE1LCAiMTAuMTg2MzcvanNzLnYwNjcuaTAxIikNCnJlZigia3V6bmV0c292YTIwMTciLCAiS3V6bmV0c292YSwgQS4sIEJyb2NraG9mZiwgUC4gQi4gJiBDaHJpc3RlbnNlbiwgUi4gSC4gQi4gbG1lclRlc3QgcGFja2FnZTogdGVzdHMgaW4gbGluZWFyIG1peGVkIGVmZmVjdHMgbW9kZWxzLiA8aT5KLiBTdGF0LiBTb2Z0dy48L2k+IDxiPjgyPC9iPiwgMVx1MjAxMzI2ICgyMDE3KS4iLA0KICAgICJsbWVyVGVzdCBwYWNrYWdlOiB0ZXN0cyBpbiBsaW5lYXIgbWl4ZWQgZWZmZWN0cyBtb2RlbHMiLCAyMDE3LCAiMTAuMTg2MzcvanNzLnYwODIuaTEzIikNCnJlZigic2F0dGVydGh3YWl0ZTE5NDYiLCAiU2F0dGVydGh3YWl0ZSwgRi4gRS4gQW4gYXBwcm94aW1hdGUgZGlzdHJpYnV0aW9uIG9mIGVzdGltYXRlcyBvZiB2YXJpYW5jZSBjb21wb25lbnRzLiA8aT5CaW9tZXRyaWNzIEJ1bGwuPC9pPiA8Yj4yPC9iPiwgMTEwXHUyMDEzMTE0ICgxOTQ2KS4iLA0KICAgICJBbiBhcHByb3hpbWF0ZSBkaXN0cmlidXRpb24gb2YgZXN0aW1hdGVzIG9mIHZhcmlhbmNlIGNvbXBvbmVudHMiLCAxOTQ2LCAiMTAuMjMwNy8zMDAyMDE5IikNCnJlZigibmFrYWdhd2EyMDEzIiwgIk5ha2FnYXdhLCBTLiAmIFNjaGllbHpldGgsIEguIEEgZ2VuZXJhbCBhbmQgc2ltcGxlIG1ldGhvZCBmb3Igb2J0YWluaW5nIFI8c3VwPjI8L3N1cD4gZnJvbSBnZW5lcmFsaXplZCBsaW5lYXIgbWl4ZWQtZWZmZWN0cyBtb2RlbHMuIDxpPk1ldGhvZHMgRWNvbC4gRXZvbC48L2k+IDxiPjQ8L2I+LCAxMzNcdTIwMTMxNDIgKDIwMTMpLiIsDQogICAgIkEgZ2VuZXJhbCBhbmQgc2ltcGxlIG1ldGhvZCBmb3Igb2J0YWluaW5nIFIyIGZyb20gZ2VuZXJhbGl6ZWQgbGluZWFyIG1peGVkLWVmZmVjdHMgbW9kZWxzIiwgMjAxMywgIjEwLjExMTEvai4yMDQxLTIxMHguMjAxMi4wMDI2MS54IikNCnJlZigibWNncmF3MTk5NiIsICJNY0dyYXcsIEsuIE8uICYgV29uZywgUy4gUC4gRm9ybWluZyBpbmZlcmVuY2VzIGFib3V0IHNvbWUgaW50cmFjbGFzcyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMuIDxpPlBzeWNob2wuIE1ldGhvZHM8L2k+IDxiPjE8L2I+LCAzMFx1MjAxMzQ2ICgxOTk2KS4iLA0KICAgICJGb3JtaW5nIGluZmVyZW5jZXMgYWJvdXQgc29tZSBpbnRyYWNsYXNzIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyIsIDE5OTYsICIxMC4xMDM3LzEwODItOTg5WC4xLjEuMzAiKQ0KcmVmKCJzaGFwaXJvMTk2NSIsICJTaGFwaXJvLCBTLiBTLiAmIFdpbGssIE0uIEIuIEFuIGFuYWx5c2lzIG9mIHZhcmlhbmNlIHRlc3QgZm9yIG5vcm1hbGl0eSAoY29tcGxldGUgc2FtcGxlcykuIDxpPkJpb21ldHJpa2E8L2k+IDxiPjUyPC9iPiwgNTkxXHUyMDEzNjExICgxOTY1KS4iLA0KICAgICJBbiBhbmFseXNpcyBvZiB2YXJpYW5jZSB0ZXN0IGZvciBub3JtYWxpdHkgKGNvbXBsZXRlIHNhbXBsZXMpIiwgMTk2NSwgIjEwLjEwOTMvYmlvbWV0LzUyLjMtNC41OTEiKQ0KcmVmKCJ3ZWxjaDE5NDciLCAiV2VsY2gsIEIuIEwuIFRoZSBnZW5lcmFsaXphdGlvbiBvZiBcdTIwMThTdHVkZW50XHUyMDE5c1x1MjAxOSBwcm9ibGVtIHdoZW4gc2V2ZXJhbCBkaWZmZXJlbnQgcG9wdWxhdGlvbiB2YXJpYW5jZXMgYXJlIGludm9sdmVkLiA8aT5CaW9tZXRyaWthPC9pPiA8Yj4zNDwvYj4sIDI4XHUyMDEzMzUgKDE5NDcpLiIsDQogICAgIlRoZSBnZW5lcmFsaXphdGlvbiBvZiBTdHVkZW50J3MgcHJvYmxlbSB3aGVuIHNldmVyYWwgZGlmZmVyZW50IHBvcHVsYXRpb24gdmFyaWFuY2VzIGFyZSBpbnZvbHZlZCIsIDE5NDcsICIxMC4xMDkzL2Jpb21ldC8zNC4xLTIuMjgiKQ0KcmVmKCJ3aWxjb3hvbjE5NDUiLCAiV2lsY294b24sIEYuIEluZGl2aWR1YWwgY29tcGFyaXNvbnMgYnkgcmFua2luZyBtZXRob2RzLiA8aT5CaW9tZXRyaWNzIEJ1bGwuPC9pPiA8Yj4xPC9iPiwgODBcdTIwMTM4MyAoMTk0NSkuIiwNCiAgICAiSW5kaXZpZHVhbCBjb21wYXJpc29ucyBieSByYW5raW5nIG1ldGhvZHMiLCAxOTQ1LCAiMTAuMjMwNy8zMDAxOTY4IikNCnJlZigia3J1c2thbDE5NTIiLCAiS3J1c2thbCwgVy4gSC4gJiBXYWxsaXMsIFcuIEEuIFVzZSBvZiByYW5rcyBpbiBvbmUtY3JpdGVyaW9uIHZhcmlhbmNlIGFuYWx5c2lzLiA8aT5KLiBBbS4gU3RhdC4gQXNzb2MuPC9pPiA8Yj40NzwvYj4sIDU4M1x1MjAxMzYyMSAoMTk1MikuIiwNCiAgICAiVXNlIG9mIHJhbmtzIGluIG9uZS1jcml0ZXJpb24gdmFyaWFuY2UgYW5hbHlzaXMiLCAxOTUyLCAiMTAuMTA4MC8wMTYyMTQ1OS4xOTUyLjEwNDgzNDQxIikNCnJlZigidHVrZXkxOTQ5IiwgIlR1a2V5LCBKLiBXLiBDb21wYXJpbmcgaW5kaXZpZHVhbCBtZWFucyBpbiB0aGUgYW5hbHlzaXMgb2YgdmFyaWFuY2UuIDxpPkJpb21ldHJpY3M8L2k+IDxiPjU8L2I+LCA5OVx1MjAxMzExNCAoMTk0OSkuIiwNCiAgICAiQ29tcGFyaW5nIGluZGl2aWR1YWwgbWVhbnMgaW4gdGhlIGFuYWx5c2lzIG9mIHZhcmlhbmNlIiwgMTk0OSwgIjEwLjIzMDcvMzAwMTkxMyIpDQpyZWYoImhvbG0xOTc5IiwgIkhvbG0sIFMuIEEgc2ltcGxlIHNlcXVlbnRpYWxseSByZWplY3RpdmUgbXVsdGlwbGUgdGVzdCBwcm9jZWR1cmUuIDxpPlNjYW5kLiBKLiBTdGF0LjwvaT4gPGI+NjwvYj4sIDY1XHUyMDEzNzAgKDE5NzkpLiIsDQogICAgIkEgc2ltcGxlIHNlcXVlbnRpYWxseSByZWplY3RpdmUgbXVsdGlwbGUgdGVzdCBwcm9jZWR1cmUiLCAxOTc5LCBOQSwgImh0dHBzOi8vd3d3LmpzdG9yLm9yZy9zdGFibGUvNDYxNTczMyIpDQpyZWYoImZsaWduZXIxOTc2IiwgIkZsaWduZXIsIE0uIEEuICYgS2lsbGVlbiwgVC4gSi4gRGlzdHJpYnV0aW9uLWZyZWUgdHdvLXNhbXBsZSB0ZXN0cyBmb3Igc2NhbGUuIDxpPkouIEFtLiBTdGF0LiBBc3NvYy48L2k+IDxiPjcxPC9iPiwgMjEwXHUyMDEzMjEzICgxOTc2KS4iLA0KICAgICJEaXN0cmlidXRpb24tZnJlZSB0d28tc2FtcGxlIHRlc3RzIGZvciBzY2FsZSIsIDE5NzYsICIxMC4xMDgwLzAxNjIxNDU5LjE5NzYuMTA0ODE1MTciKQ0KcmVmKCJicm93bjE5NzQiLCAiQnJvd24sIE0uIEIuICYgRm9yc3l0aGUsIEEuIEIuIFJvYnVzdCB0ZXN0cyBmb3IgdGhlIGVxdWFsaXR5IG9mIHZhcmlhbmNlcy4gPGk+Si4gQW0uIFN0YXQuIEFzc29jLjwvaT4gPGI+Njk8L2I+LCAzNjRcdTIwMTMzNjcgKDE5NzQpLiIsDQogICAgIlJvYnVzdCB0ZXN0cyBmb3IgdGhlIGVxdWFsaXR5IG9mIHZhcmlhbmNlcyIsIDE5NzQsICIxMC4xMDgwLzAxNjIxNDU5LjE5NzQuMTA0ODI5NTUiKQ0KcmVmKCJlZnJvbjE5NzkiLCAiRWZyb24sIEIuIEJvb3RzdHJhcCBtZXRob2RzOiBhbm90aGVyIGxvb2sgYXQgdGhlIGphY2trbmlmZS4gPGk+QW5uLiBTdGF0LjwvaT4gPGI+NzwvYj4sIDFcdTIwMTMyNiAoMTk3OSkuIiwNCiAgICAiQm9vdHN0cmFwIG1ldGhvZHM6IGFub3RoZXIgbG9vayBhdCB0aGUgamFja2tuaWZlIiwgMTk3OSwgIjEwLjEyMTQvYW9zLzExNzYzNDQ1NTIiKQ0KcmVmKCJoZWRnZXMxOTgxIiwgIkhlZGdlcywgTC4gVi4gRGlzdHJpYnV0aW9uIHRoZW9yeSBmb3IgR2xhc3NcdTIwMTlzIGVzdGltYXRvciBvZiBlZmZlY3Qgc2l6ZSBhbmQgcmVsYXRlZCBlc3RpbWF0b3JzLiA8aT5KLiBFZHVjLiBTdGF0LjwvaT4gPGI+NjwvYj4sIDEwN1x1MjAxMzEyOCAoMTk4MSkuIiwNCiAgICAiRGlzdHJpYnV0aW9uIHRoZW9yeSBmb3IgR2xhc3MncyBlc3RpbWF0b3Igb2YgZWZmZWN0IHNpemUgYW5kIHJlbGF0ZWQgZXN0aW1hdG9ycyIsIDE5ODEsICIxMC4zMTAyLzEwNzY5OTg2MDA2MDAyMTA3IikNCnJlZigibGFrZW5zMjAxMyIsICJMYWtlbnMsIEQuIENhbGN1bGF0aW5nIGFuZCByZXBvcnRpbmcgZWZmZWN0IHNpemVzIHRvIGZhY2lsaXRhdGUgY3VtdWxhdGl2ZSBzY2llbmNlOiBhIHByYWN0aWNhbCBwcmltZXIgZm9yIHQtdGVzdHMgYW5kIEFOT1ZBcy4gPGk+RnJvbnQuIFBzeWNob2wuPC9pPiA8Yj40PC9iPiwgODYzICgyMDEzKS4iLA0KICAgICJDYWxjdWxhdGluZyBhbmQgcmVwb3J0aW5nIGVmZmVjdCBzaXplcyB0byBmYWNpbGl0YXRlIGN1bXVsYXRpdmUgc2NpZW5jZTogYSBwcmFjdGljYWwgcHJpbWVyIGZvciB0LXRlc3RzIGFuZCBBTk9WQXMiLCAyMDEzLCAiMTAuMzM4OS9mcHN5Zy4yMDEzLjAwODYzIikNCnJlZigid2Fzc2Vyc3RlaW4yMDE2IiwgIldhc3NlcnN0ZWluLCBSLiBMLiAmIExhemFyLCBOLiBBLiBUaGUgQVNBIHN0YXRlbWVudCBvbiBwLXZhbHVlczogY29udGV4dCwgcHJvY2VzcywgYW5kIHB1cnBvc2UuIDxpPkFtLiBTdGF0LjwvaT4gPGI+NzA8L2I+LCAxMjlcdTIwMTMxMzMgKDIwMTYpLiIsDQogICAgIlRoZSBBU0EncyBzdGF0ZW1lbnQgb24gcC12YWx1ZXM6IGNvbnRleHQsIHByb2Nlc3MsIGFuZCBwdXJwb3NlIiwgMjAxNiwgIjEwLjEwODAvMDAwMzEzMDUuMjAxNi4xMTU0MTA4IikNCnJlZigiYW1yaGVpbjIwMTkiLCAiQW1yaGVpbiwgVi4sIEdyZWVubGFuZCwgUy4gJiBNY1NoYW5lLCBCLiBTY2llbnRpc3RzIHJpc2UgdXAgYWdhaW5zdCBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuIDxpPk5hdHVyZTwvaT4gPGI+NTY3PC9iPiwgMzA1XHUyMDEzMzA3ICgyMDE5KS4iLA0KICAgICJTY2llbnRpc3RzIHJpc2UgdXAgYWdhaW5zdCBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UiLCAyMDE5LCAiMTAuMTAzOC9kNDE1ODYtMDE5LTAwODU3LTkiKQ0KcmVmKCJnZWxtYW4yMDA2IiwgIkdlbG1hbiwgQS4gJiBTdGVybiwgSC4gVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBcdTIwMThzaWduaWZpY2FudFx1MjAxOSBhbmQgXHUyMDE4bm90IHNpZ25pZmljYW50XHUyMDE5IGlzIG5vdCBpdHNlbGYgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gPGk+QW0uIFN0YXQuPC9pPiA8Yj42MDwvYj4sIDMyOFx1MjAxMzMzMSAoMjAwNikuIiwNCiAgICAiVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBzaWduaWZpY2FudCBhbmQgbm90IHNpZ25pZmljYW50IGlzIG5vdCBpdHNlbGYgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCIsIDIwMDYsICIxMC4xMTk4LzAwMDMxMzAwNlgxNTI2NDkiKQ0KcmVmKCJ3aWNraGFtMjAxNiIsICJXaWNraGFtLCBILiA8aT5nZ3Bsb3QyOiBFbGVnYW50IEdyYXBoaWNzIGZvciBEYXRhIEFuYWx5c2lzPC9pPiAoU3ByaW5nZXIsIDIwMTYpLiIsDQogICAgImdncGxvdDI6IEVsZWdhbnQgR3JhcGhpY3MgZm9yIERhdGEgQW5hbHlzaXMiLCAyMDE2LCAiMTAuMTAwNy85NzgtMy0zMTktMjQyNzctNCIpDQpyZWYoInVlaWEyMDE0IiwgIkFycm95YXZlLCBNLiBQLiwgUG9zYWRhLCBNLiBJLiAmIEd1dGlcdTAwZTlycmV6LCBNLiBFLiA8aT5DYXRcdTAwZTFsb2dvIHZpcnR1YWwgZGUgZmxvcmEgZGVsIFZhbGxlIGRlIEFidXJyXHUwMGUxPC9pPiAoVW5pdmVyc2lkYWQgRUlBLCAyMDE0KS4iLA0KICAgICJDYXRcdTAwZTFsb2dvIHZpcnR1YWwgZGUgZmxvcmEgZGVsIFZhbGxlIGRlIEFidXJyXHUwMGUxIiwgMjAxNCwgTkEsICJodHRwOi8vY2F0YWxvZ29mbG9yYXZhbGxlYWJ1cnJhLmVpYS5lZHUuY28iKQ0KcmVmKCJyY29yZSIsICJSIENvcmUgVGVhbS4gPGk+UjogQSBMYW5ndWFnZSBhbmQgRW52aXJvbm1lbnQgZm9yIFN0YXRpc3RpY2FsIENvbXB1dGluZzwvaT4gKFIgRm91bmRhdGlvbiBmb3IgU3RhdGlzdGljYWwgQ29tcHV0aW5nLCBWaWVubmEpLiIsDQogICAgIlI6IEEgTGFuZ3VhZ2UgYW5kIEVudmlyb25tZW50IGZvciBTdGF0aXN0aWNhbCBDb21wdXRpbmciLCAyMDI0LCBOQSwgImh0dHBzOi8vd3d3LlItcHJvamVjdC5vcmcvIikNCmBgYA0KDQpgYGB7ciBjYWxjX2RhdG9zLCBpbmNsdWRlPUZBTFNFfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgMS4gTEVDVFVSQSwgTk9STUFMSVpBQ0nDk04gWSBSRVZJU0nDk04gREUgQ0FMSURBRA0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCnJ1dGEgPC0gcGFyYW1zJGFyY2hpdm8NCmlmICghZmlsZS5leGlzdHMocnV0YSkpIHsNCiAgY2FuZCA8LSBsaXN0LmZpbGVzKHBhdHRlcm4gPSAiXFwuY3N2JCIsIGlnbm9yZS5jYXNlID0gVFJVRSkNCiAgY2FuZCA8LSBjYW5kWyFncmVwbCgibGltcGl8cmVzdWx0YWRvIiwgY2FuZCwgaWdub3JlLmNhc2UgPSBUUlVFKV0NCiAgaWYgKGxlbmd0aChjYW5kKSA9PSAwKSBzdG9wKCJObyBzZSBlbmNvbnRyw7MgZWwgYXJjaGl2byBkZSBkYXRvczogIiwgcGFyYW1zJGFyY2hpdm8pDQogIHJ1dGEgPC0gY2FuZFsxXQ0KfQ0KUiRhcmNoaXZvIDwtIGJhc2VuYW1lKHJ1dGEpDQpsZWVyIDwtIGZ1bmN0aW9uKHN0cmlwKSByZWFkLmNzdihydXRhLCBjb2xDbGFzc2VzID0gImNoYXJhY3RlciIsIG5hLnN0cmluZ3MgPSBjKCIiLCAiTkEiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UsIHN0cmlwLndoaXRlID0gc3RyaXAsIGZpbGVFbmNvZGluZyA9ICJVVEYtOC1CT00iKQ0KY3J1ZG8wIDwtIGxlZXIoRkFMU0UpOyBjcnVkbyA8LSBsZWVyKFRSVUUpDQpub3JtX25tIDwtIGZ1bmN0aW9uKHgpIHsgeCA8LSB0b2xvd2VyKGljb252KHgsIHRvID0gIkFTQ0lJLy9UUkFOU0xJVCIpKTsgeCA8LSBnc3ViKCJbXmEtejAtOV0rIiwgIl8iLCB4KTsgZ3N1YigiXl8rfF8rJCIsICIiLCB4KSB9DQpuYW1lcyhjcnVkbykgPC0gbm9ybV9ubShuYW1lcyhjcnVkbykpOyBuYW1lcyhjcnVkbzApIDwtIG5vcm1fbm0obmFtZXMoY3J1ZG8wKSkNCnJlcSA8LSBjKCJhcmNoaXZvIiwgImFyYm9sIiwgImxhZG9fMV9tbSIsICJsYWRvXzJfbW0iLCAiYXJlYV9yZWFsX2NtMiIsICJleHBvc2ljaW9uIiwgImxhdGl0dWQiLCAibG9uZ2l0dWQiKQ0KaWYgKGxlbmd0aChzZXRkaWZmKHJlcSwgbmFtZXMoY3J1ZG8pKSkgPiAwKSBzdG9wKCJGYWx0YW4gY29sdW1uYXMgZW4gbGEgYmFzZTogIiwgcGFzdGUoc2V0ZGlmZihyZXEsIG5hbWVzKGNydWRvKSksIGNvbGxhcHNlID0gIiwgIikpDQpjb2wgPC0gZnVuY3Rpb24obm0pIGlmIChubSAlaW4lIG5hbWVzKGNydWRvKSkgY3J1ZG9bW25tXV0gZWxzZSByZXAoTkFfY2hhcmFjdGVyXywgbnJvdyhjcnVkbykpDQoNCnBhcnNlX251bSA8LSBmdW5jdGlvbih4KSB7DQogIHggPC0gdHJpbXdzKGFzLmNoYXJhY3Rlcih4KSk7IHhbeCAlaW4lIGMoIiIsICJOQSIsICJuYSIsICJOL0EiLCAiLSIpXSA8LSBOQQ0KICBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoZ3N1YigiLCIsICIuIiwgeCwgZml4ZWQgPSBUUlVFKSkpDQp9DQojIENvb3JkZW5hZGFzIGVzY3JpdGFzIGNvbiBwdW50b3MgY29tbyBzZXBhcmFkb3IgZGUgbWlsZXMgKCIzLjM3OS40ODAiID0gMywzNzk0ODApDQpwYXJzZV9jb29yZCA8LSBmdW5jdGlvbih4KSB7DQogIHZhcHBseShhcy5jaGFyYWN0ZXIoeCksIGZ1bmN0aW9uKHMpIHsNCiAgICBpZiAoaXMubmEocykgfHwgdHJpbXdzKHMpID09ICIiKSByZXR1cm4oTkFfcmVhbF8pDQogICAgcyA8LSBnc3ViKCIsIiwgIi4iLCB0cmltd3MocyksIGZpeGVkID0gVFJVRSk7IG5lZyA8LSBncmVwbCgiXi0iLCBzKTsgczIgPC0gc3ViKCJeWy0rXSIsICIiLCBzKQ0KICAgIHAgPC0gc3Ryc3BsaXQoczIsICIuIiwgZml4ZWQgPSBUUlVFKVtbMV1dDQogICAgdiA8LSBpZiAobGVuZ3RoKHApID49IDMpIHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyhwYXN0ZTAocFsxXSwgIi4iLCBwYXN0ZShwWy0xXSwgY29sbGFwc2UgPSAiIikpKSkgZWxzZSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoczIpKQ0KICAgIGlmIChuZWcpIC12IGVsc2Ugdg0KICB9LCBudW1lcmljKDEpLCBVU0UuTkFNRVMgPSBGQUxTRSkNCn0NCmhhdmVyc2luZSA8LSBmdW5jdGlvbihsYXQxLCBsb24xLCBsYXQyLCBsb24yKSB7DQogIHJhZCA8LSBwaSAvIDE4MA0KICBhIDwtIHNpbigobGF0MiAtIGxhdDEpICogcmFkIC8gMileMiArIGNvcyhsYXQxICogcmFkKSAqIGNvcyhsYXQyICogcmFkKSAqIHNpbigobG9uMiAtIGxvbjEpICogcmFkIC8gMileMg0KICAyICogNjM3MTAwMCAqIGFzaW4oc3FydChhKSkNCn0NCg0KZGF0b3MgPC0gZGF0YS5mcmFtZShmaWxhID0gc2VxX2xlbihucm93KGNydWRvKSksIGFyY2hpdm8gPSBjcnVkbyRhcmNoaXZvLCBhcmJvbF9yYXcgPSBjcnVkbyRhcmJvbCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KbnVtIDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihnc3ViKCJcXEQiLCAiIiwgZGF0b3MkYXJib2xfcmF3KSkpDQpkYXRvcyRhcmJvbCA8LSBpZmVsc2UoaXMubmEobnVtKSwgdG91cHBlcih0cmltd3MoZGF0b3MkYXJib2xfcmF3KSksIHBhc3RlMCgiVCIsIG51bSkpDQpkYXRvcyRhcmJvbF9uIDwtIG51bQ0KZGF0b3Mkbl9ob2phIDwtIGF2ZShzZXFfbGVuKG5yb3coZGF0b3MpKSwgZGF0b3MkYXJib2wsIEZVTiA9IHNlcV9hbG9uZykNCmUgPC0gdG9sb3dlcih0cmltd3MoaWNvbnYoY3J1ZG8kZXhwb3NpY2lvbiwgdG8gPSAiQVNDSUkvL1RSQU5TTElUIikpKQ0KZGF0b3MkZXhwb3NpY2lvbiA8LSBmYWN0b3IoaWZlbHNlKGdyZXBsKCJec29sIiwgZSksICJzb2wiLCBpZmVsc2UoZ3JlcGwoIl5zb21iIiwgZSksICJzb21icmEiLCBOQSkpLCBsZXZlbHMgPSBjKCJzb2wiLCAic29tYnJhIikpDQpkYXRvcyRsYWRvMSA8LSBwYXJzZV9udW0oY3J1ZG8kbGFkb18xX21tKTsgZGF0b3MkbGFkbzIgPC0gcGFyc2VfbnVtKGNydWRvJGxhZG9fMl9tbSkNCmRhdG9zJG1hcmNvX2NtMiA8LSBkYXRvcyRsYWRvMSAqIGRhdG9zJGxhZG8yIC8gMTAwICAgICAgICAgICAgIyBtbSB4IG1tIC0+IGNtMg0KZGF0b3MkYXNwZWN0byA8LSBwbWF4KGRhdG9zJGxhZG8xLCBkYXRvcyRsYWRvMikgLyBwbWluKGRhdG9zJGxhZG8xLCBkYXRvcyRsYWRvMikNCmRhdG9zJGFyZWFfb3JpZyA8LSBwYXJzZV9udW0oY3J1ZG8kYXJlYV9yZWFsX2NtMikNCmRhdG9zJGxhdCA8LSBwYXJzZV9jb29yZChjcnVkbyRsYXRpdHVkKTsgZGF0b3MkbG9uIDwtIHBhcnNlX2Nvb3JkKGNydWRvJGxvbmdpdHVkKQ0KZGF0b3MkYWx0aXR1ZCA8LSBwYXJzZV9udW0oY29sKCJhbHRpdHVkX20iKSk7IGRhdG9zJGVzcGVjaWUgPC0gY29sKCJlc3BlY2llIik7IGRhdG9zJGdlbmVybyA8LSBjb2woImdlbmVybyIpDQpkYXRvcyRkZXNjcmlwY2lvbiA8LSBjb2woImRlc2NyaXBjaW9uIikNCmRhdG9zJHJhem9uX21hcmNvIDwtIGRhdG9zJGFyZWFfb3JpZyAvIGRhdG9zJG1hcmNvX2NtMg0KDQojIC0tLS0gRGVjaXNpb25lcyBleHBsw61jaXRhcyBmaWxhIHBvciBmaWxhIC0tLS0NCmRhdG9zJGVzdGFkbyA8LSAib2siDQpkYXRvcyRlc3RhZG9baXMubmEoZGF0b3MkYXJlYV9vcmlnKV0gPC0gInNpbiDDoXJlYSAocGVuZGllbnRlKSINCmRhdG9zJGVzdGFkb1shaXMubmEoZGF0b3MkYXJlYV9vcmlnKSAmIGRhdG9zJGFyZWFfb3JpZyA8PSAwXSA8LSAiw6FyZWEgbm8gdsOhbGlkYSAoPD0gMCkiDQppbXBvc2libGUgPC0gIWlzLm5hKGRhdG9zJHJhem9uX21hcmNvKSAmIGRhdG9zJHJhem9uX21hcmNvID4gMQ0KcjEwMCA8LSBkYXRvcyRyYXpvbl9tYXJjbyAvIDEwMA0KY29ycmVnaWJsZSA8LSBpbXBvc2libGUgJiAhaXMubmEocjEwMCkgJiByMTAwID4gMC4yICYgcjEwMCA8PSAxDQpkYXRvcyRhcmVhIDwtIGRhdG9zJGFyZWFfb3JpZw0KZGF0b3MkYXJlYVtjb3JyZWdpYmxlXSA8LSBkYXRvcyRhcmVhX29yaWdbY29ycmVnaWJsZV0gLyAxMDANCmRhdG9zJGVzdGFkb1tjb3JyZWdpYmxlXSA8LSAiY29ycmVnaWRhIChtbcKyIOKGkiBjbcKyKSINCmRhdG9zJGVzdGFkb1tpbXBvc2libGUgJiAhY29ycmVnaWJsZV0gPC0gIsOhcmVhIG1heW9yIHF1ZSBlbCBtYXJjbyINCmRhdG9zJHVzYXIgPC0gZGF0b3MkZXN0YWRvICVpbiUgYygib2siLCAiY29ycmVnaWRhIChtbcKyIOKGkiBjbcKyKSIpDQpkYXRvcyRsbl9hcmVhIDwtIGlmZWxzZShkYXRvcyR1c2FyLCBsb2coZGF0b3MkYXJlYSksIE5BX3JlYWxfKQ0KZGF0b3MkbG5fbWFyY28gPC0gbG9nKGRhdG9zJG1hcmNvX2NtMikNCg0KbGltIDwtIGRhdG9zW2RhdG9zJHVzYXIsIF0gICAgICAgICAgICAgICAgICAgICAgICMgYmFzZSBhbmFsw610aWNhIHByaW1hcmlhICjDoXJlYXMgbWVkaWRhcykNCmFyYm9sZXNfYWxsIDwtIHNvcnQodW5pcXVlKGRhdG9zJGFyYm9sKSkNClIkbl9maWxhcyA8LSBucm93KGRhdG9zKTsgUiRuX2FyYiA8LSBsZW5ndGgoYXJib2xlc19hbGwpDQpSJG5fbWVkIDwtIHN1bShkYXRvcyR1c2FyKTsgUiRuX2ZhbHRhIDwtIHN1bShkYXRvcyRlc3RhZG8gPT0gInNpbiDDoXJlYSAocGVuZGllbnRlKSIpDQpSJHBjdF9mYWx0YSA8LSAxMDAgKiBSJG5fZmFsdGEgLyBSJG5fZmlsYXMNClIkZXNwZWNpZSA8LSB1bmlxdWUobmEub21pdChkYXRvcyRlc3BlY2llKSk7IFIkZXNwZWNpZSA8LSBpZiAobGVuZ3RoKFIkZXNwZWNpZSkpIHBhc3RlKFIkZXNwZWNpZSwgY29sbGFwc2UgPSAiIC8gIikgZWxzZSAiZXNwZWNpZSBubyBpbmRpY2FkYSINClIkYWx0aXR1ZCA8LSB1bmlxdWUobmEub21pdChkYXRvcyRhbHRpdHVkKSkNCg0KIyAtLS0tIFJlc3VtZW4gcG9yIMOhcmJvbCBkZSBsYSBjb21wbGV0aXR1ZCAtLS0tDQpjb21wIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShzcGxpdChkYXRvcywgZGF0b3MkYXJib2wpLCBmdW5jdGlvbihkKQ0KICBkYXRhLmZyYW1lKGFyYm9sID0gZCRhcmJvbFsxXSwgZXhwb3NpY2lvbiA9IGFzLmNoYXJhY3RlcihkJGV4cG9zaWNpb25bMV0pLCBuX3RvdGFsID0gbnJvdyhkKSwgbl9tZWRpZGEgPSBzdW0oZCR1c2FyKSwNCiAgICAgICAgICAgICBuX2ZhbHRhID0gc3VtKGQkZXN0YWRvID09ICJzaW4gw6FyZWEgKHBlbmRpZW50ZSkiKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSkpDQpjb21wIDwtIGNvbXBbb3JkZXIoYXMuaW50ZWdlcihnc3ViKCJcXEQiLCAiIiwgY29tcCRhcmJvbCkpKSwgXQ0KY29tcCRwY3QgPC0gMTAwICogY29tcCRuX21lZGlkYSAvIGNvbXAkbl90b3RhbA0KUiRhcmJfc2luX21lZGlkYSA8LSBjb21wJGFyYm9sW2NvbXAkbl9tZWRpZGEgPT0gMF0NClIkYXJiX3BvY2FzIDwtIGNvbXAkYXJib2xbY29tcCRuX21lZGlkYSA+IDAgJiBjb21wJG5fbWVkaWRhIDwgcGFyYW1zJG1pbl9ob2phc19hcmJvbF0NCg0KIyAtLS0tIENvb3JkZW5hZGFzIHBvciDDoXJib2wgeSBkaXN0YW5jaWFzIC0tLS0NCmdlbyA8LSBhZ2dyZWdhdGUoY2JpbmQobGF0LCBsb24pIH4gYXJib2wgKyBleHBvc2ljaW9uLCBkYXRhID0gZGF0b3MsIEZVTiA9IG1lYW4pDQpnZW8gPC0gZ2VvW29yZGVyKGFzLmludGVnZXIoZ3N1YigiXFxEIiwgIiIsIGdlbyRhcmJvbCkpKSwgXQ0KcGFyZXMgPC0gdChjb21ibihucm93KGdlbyksIDIpKQ0KZGlzdF9wYXIgPC0gZGF0YS5mcmFtZShhID0gZ2VvJGFyYm9sW3BhcmVzWywgMV1dLCBiID0gZ2VvJGFyYm9sW3BhcmVzWywgMl1dLA0KICAgICAgICAgICAgICAgICAgICAgICBkX20gPSBoYXZlcnNpbmUoZ2VvJGxhdFtwYXJlc1ssIDFdXSwgZ2VvJGxvbltwYXJlc1ssIDFdXSwgZ2VvJGxhdFtwYXJlc1ssIDJdXSwgZ2VvJGxvbltwYXJlc1ssIDJdXSkpDQpSJGRpc3RfbWluIDwtIG1pbihkaXN0X3BhciRkX20pOyBSJGRpc3RfbWF4IDwtIG1heChkaXN0X3BhciRkX20pDQpSJGR1cF9hcmJvbCA8LSBkaXN0X3BhcltkaXN0X3BhciRkX20gPCBwYXJhbXMkZGlzdF9kdXBsaWNhZG9fbSwgXQ0KbGF0MCA8LSBtZWFuKGdlbyRsYXQpOyBsb24wIDwtIG1lYW4oZ2VvJGxvbikNCmdlbyR4X20gPC0gKGdlbyRsb24gLSBsb24wKSAqIDExMTMyMCAqIGNvcyhsYXQwICogcGkgLyAxODApDQpnZW8keV9tIDwtIChnZW8kbGF0IC0gbGF0MCkgKiAxMTA1NzQNClIkbGVqYW5vIDwtIGdlbyRhcmJvbFt3aGljaC5tYXgoc3FydChnZW8keF9tXjIgKyBnZW8keV9tXjIpKV0NClIkZGlzdF9sZWphbm8gPC0gbWF4KHNxcnQoZ2VvJHhfbV4yICsgZ2VvJHlfbV4yKSkNCg0KIyAtLS0tIEJhbmRlcmFzIGRlIGNhbGlkYWQgLS0tLQ0KUiRuX3dzIDwtIHN1bShncmVwbCgiXlxccyt8XFxzKyQiLCBjcnVkbzAkYXJlYV9yZWFsX2NtMiksIG5hLnJtID0gVFJVRSkNClIkbl9jb29yZF9taWxlcyA8LSBzdW0oZ3JlcGwoIl4tP1swLTldKyhcXC5bMC05XXszfSl7Mix9JCIsIHRyaW13cyhjcnVkbyRsYXRpdHVkKSksIG5hLnJtID0gVFJVRSkNClIkbl9leHBvX25hIDwtIHN1bShpcy5uYShkYXRvcyRleHBvc2ljaW9uKSkNCmluY19leHBvIDwtIHRhcHBseShhcy5jaGFyYWN0ZXIoZGF0b3MkZXhwb3NpY2lvbiksIGRhdG9zJGFyYm9sLCBmdW5jdGlvbih6KSBsZW5ndGgodW5pcXVlKHopKSkNCmluY194eSA8LSB0YXBwbHkocGFzdGUoZGF0b3MkbGF0LCBkYXRvcyRsb24pLCBkYXRvcyRhcmJvbCwgZnVuY3Rpb24oeikgbGVuZ3RoKHVuaXF1ZSh6KSkpDQpSJGluY29ucyA8LSBzdW0oaW5jX2V4cG8gPiAxKSArIHN1bShpbmNfeHkgPiAxKQ0KUiRuX2R1cF9hcmNoIDwtIHN1bShkdXBsaWNhdGVkKGRhdG9zJGFyY2hpdm8pKQ0KUiRuX2Nlcm8gPC0gc3VtKGRhdG9zJGVzdGFkbyA9PSAiw6FyZWEgbm8gdsOhbGlkYSAoPD0gMCkiKTsgUiRuX21heW9yIDwtIHN1bShkYXRvcyRlc3RhZG8gPT0gIsOhcmVhIG1heW9yIHF1ZSBlbCBtYXJjbyIpDQpSJG5fY29yciA8LSBzdW0oZGF0b3MkZXN0YWRvID09ICJjb3JyZWdpZGEgKG1twrIg4oaSIGNtwrIpIikNClIkY29sc19wbGFudGlsbGFfZmFsdGFuIDwtIHNldGRpZmYoYygiZ3J1cG8iLCAiaWRfYXJib2wiLCAiZmVjaGEiLCAib2JzZXJ2YWNpb25lcyIpLCBuYW1lcyhjcnVkbykpDQpSJHJhdGlvX29rIDwtIHJhbmdlKGRhdG9zJHJhem9uX21hcmNvW2RhdG9zJHVzYXJdLCBuYS5ybSA9IFRSVUUpDQpubV9ob2phIDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihnc3ViKCJcXEQiLCAiIiwgZGF0b3MkYXJjaGl2bykpKQ0KUiRhcmNoaXZvX3NlcSA8LSAhYW55KGlzLm5hKG5tX2hvamEpKSAmJiBhbGwoZGlmZihubV9ob2phKSA9PSAxKQ0KUiRob2phc194X2FyYm9sIDwtIHJhbmdlKHRhYmxlKGRhdG9zJGFyYm9sKSkNCg0KcWNfdGFiIDwtIGRhdGEuZnJhbWUoDQogIFZlcmlmaWNhY2nDs24gPSBjKCJFc3RydWN0dXJhIGRlIGxhIGJhc2UiLCAiSG9qYXMgcG9yIMOhcmJvbCIsICLDgXJlYXMgZW4gYmxhbmNvIChwZW5kaWVudGVzKSIsICLDgXJib2xlcyBzaW4gbmluZ3VuYSDDoXJlYSBtZWRpZGEiLA0KICAgICAgICAgICAgICAgICAgICJFc3BhY2lvcyBzb2JyYW50ZXMgZW4gZWwgw6FyZWEiLCAiQ29vcmRlbmFkYXMgY29uIHNlcGFyYWRvciBkZSBtaWxlcyIsICJFeHBvc2ljacOzbiB2w6FsaWRhIHkgY29uc3RhbnRlIHBvciDDoXJib2wiLA0KICAgICAgICAgICAgICAgICAgICLDgXJlYSDiiaQgMCBvIG1heW9yIHF1ZSBlbCBtYXJjbyIsICJBcmNoaXZvcyBkZSBmb3RvIHJlcGV0aWRvcyIsICLDgXJib2wgbWVkaWRvIGRvcyB2ZWNlcyAoPCB1bWJyYWwgZGUgZGlzdGFuY2lhKSIsDQogICAgICAgICAgICAgICAgICAgIkNvbHVtbmFzIGRlIGxhIHBsYW50aWxsYSBhdXNlbnRlcyIpLA0KICBSZXN1bHRhZG8gPSBjKHBhc3RlMChSJG5fZmlsYXMsICIgZmlsYXMgw5cgIiwgbmNvbChjcnVkbyksICIgY29sdW1uYXM7ICIsIFIkbl9hcmIsICIgw6FyYm9sZXMiKSwNCiAgICAgICAgICAgICAgICBwYXN0ZTAoUiRob2phc194X2FyYm9sWzFdLCBpZiAoUiRob2phc194X2FyYm9sWzFdICE9IFIkaG9qYXNfeF9hcmJvbFsyXSkgcGFzdGUwKCLigJMiLCBSJGhvamFzX3hfYXJib2xbMl0pIGVsc2UgIiIsICIgKHByb3RvY29sbzogMTApIiksDQogICAgICAgICAgICAgICAgcGFzdGUwKFIkbl9mYWx0YSwgIiBkZSAiLCBSJG5fZmlsYXMsICIgKCIsIGZ4KFIkcGN0X2ZhbHRhLCAxKSwgIiAlKSIpLA0KICAgICAgICAgICAgICAgIGlmIChsZW5ndGgoUiRhcmJfc2luX21lZGlkYSkpIHBhc3RlKFIkYXJiX3Npbl9tZWRpZGEsIGNvbGxhcHNlID0gIiwgIikgZWxzZSAibmluZ3VubyIsDQogICAgICAgICAgICAgICAgcGFzdGUwKFIkbl93cywgIiBjZWxkYXMiKSwgcGFzdGUwKFIkbl9jb29yZF9taWxlcywgIiBmaWxhcyIpLA0KICAgICAgICAgICAgICAgIHBhc3RlMChSJG5fZXhwb19uYSwgIiB2YWxvcmVzIG5vIHJlY29ub2NpZG9zOyAiLCBSJGluY29ucywgIiBpbmNvbnNpc3RlbmNpYXMiKSwNCiAgICAgICAgICAgICAgICBwYXN0ZTAoUiRuX2Nlcm8gKyBSJG5fbWF5b3IsICIgZmlsYXMgKCIsIFIkbl9jb3JyLCAiIGNvcnJlZ2lkYXMgcG9yIHVuaWRhZCkiKSwNCiAgICAgICAgICAgICAgICBwYXN0ZTAoUiRuX2R1cF9hcmNoKSwgcGFzdGUwKG5yb3coUiRkdXBfYXJib2wpLCAiIHBhcmVzIiksDQogICAgICAgICAgICAgICAgaWYgKGxlbmd0aChSJGNvbHNfcGxhbnRpbGxhX2ZhbHRhbikpIHBhc3RlKFIkY29sc19wbGFudGlsbGFfZmFsdGFuLCBjb2xsYXBzZSA9ICIsICIpIGVsc2UgIm5pbmd1bmEiKSwNCiAgRGVjaXNpw7NuID0gYygiU2Ugbm9ybWFsaXphbiBub21icmVzIGRlIGNvbHVtbmEgeSB0aXBvcyIsICJTZSBjb25zZXJ2YSBlbCBuIHJlYWwgZGUgY2FkYSDDoXJib2wiLA0KICAgICAgICAgICAgICAgIlNlIGV4Y2x1eWVuIGRlbCBhbsOhbGlzaXMgcHJpbWFyaW87IHNlIGVzdGltYW4gYXBhcnRlIChzZW5zaWJpbGlkYWQpIiwgIlNlIGV4Y2x1eWVuIGRlbCBuaXZlbCBkZSDDoXJib2w7IHNlIHVzYW4gZW4gZWwgYW7DoWxpc2lzIGRlbCBtYXJjbyIsDQogICAgICAgICAgICAgICAiU2UgZWxpbWluYW4gYWwgbGVlciAoc3RyaXApIiwgIlNlIHJlY29uc3RydXllIGVsIHZhbG9yIGRlY2ltYWwgKDMuMzc5LjQ4MCDihpIgMywzNzk0ODApIiwNCiAgICAgICAgICAgICAgICJTZSB2ZXJpZmljYTsgbG9zIG5vIHbDoWxpZG9zIHNlIGV4Y2x1aXLDrWFuIiwgIlNlIGNvcnJpZ2VuIHNpIGVsIGNvY2llbnRlIC8xMDAgZXMgcGxhdXNpYmxlOyBzaSBubywgc2UgZXhjbHV5ZW4iLA0KICAgICAgICAgICAgICAgIlNlIGVsaW1pbmFuIGR1cGxpY2Fkb3MiLCAiU2UgdW5pZmljYXLDrWFuIGJham8gdW4gc29sbyDDoXJib2wiLCAiU2UgYWR2aWVydGU7IG5vIGFmZWN0YSBhbCBhbsOhbGlzaXMiKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KYGBgDQoNCmBgYHtyIGNhbGNfcHJveHksIGluY2x1ZGU9RkFMU0V9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAyLiBWQUxJREFDScOTTiBERUwgTUFSQ08gQ09NTyBQUk9YWSBERUwgw4FSRUEgWSBNT0RFTE8gREUgQ09NUExFVEFETw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NClIkcHJveHlfb2sgPC0gbnJvdyhsaW0pID49IDUgJiYgbGVuZ3RoKHVuaXF1ZShsaW0kYXJib2wpKSA+PSAxDQppZiAoUiRwcm94eV9vaykgew0KICBtX3B4IDwtIGxtKGxuX2FyZWEgfiBsbl9tYXJjbywgZGF0YSA9IGxpbSkNCiAgc214IDwtIHN1bW1hcnkobV9weCkNCiAgUiRweF9yMiA8LSBzbXgkci5zcXVhcmVkOyBSJHB4X3NpZ21hIDwtIHNteCRzaWdtYQ0KICBSJHB4X2IgPC0gY29lZihtX3B4KVtbImxuX21hcmNvIl1dOyBSJHB4X2JfaWMgPC0gY29uZmludChtX3B4KVsibG5fbWFyY28iLCBdDQogIFIkcHhfYSA8LSBjb2VmKG1fcHgpW1siKEludGVyY2VwdCkiXV0NCiAgbG9vIDwtIHJlc2lkKG1fcHgpIC8gKDEgLSBoYXR2YWx1ZXMobV9weCkpOyBSJHB4X2xvb19ybXNlIDwtIHNxcnQobWVhbihsb29eMikpDQogIFIkZmlsbF9tZWFuIDwtIG1lYW4obGltJHJhem9uX21hcmNvKTsgUiRmaWxsX3NkIDwtIHNkKGxpbSRyYXpvbl9tYXJjbyk7IFIkZmlsbF9jdiA8LSBjdihsaW0kcmF6b25fbWFyY28pDQogIFIkZmlsbF9yYW5nZSA8LSByYW5nZShsaW0kcmF6b25fbWFyY28pDQogICMgwr9lbCBjb2NpZW50ZSDDoXJlYS9tYXJjbyBkZXBlbmRlIGRlbCDDoXJib2wgbyBkZSBsYSBleHBvc2ljacOzbj8NCiAgbGltJGxuX2ZpbGwgPC0gbG9nKGxpbSRyYXpvbl9tYXJjbykNCiAgYW5fZmlsbF90IDwtIGlmIChsZW5ndGgodW5pcXVlKGxpbSRhcmJvbCkpID49IDIpIHNhZmUoYW5vdmEobG0obG5fZmlsbCB+IGFyYm9sLCBkYXRhID0gbGltKSkpIGVsc2UgTlVMTA0KICBhbl9maWxsX2UgPC0gaWYgKGxlbmd0aCh1bmlxdWUobGltJGV4cG9zaWNpb24pKSA+PSAyKSBzYWZlKGFub3ZhKGxtKGxuX2ZpbGwgfiBleHBvc2ljaW9uLCBkYXRhID0gbGltKSkpIGVsc2UgTlVMTA0KICBSJGZpbGxfcF9hcmJvbCA8LSBpZiAoIWlzLm51bGwoYW5fZmlsbF90KSkgYW5fZmlsbF90JGBQcig+RilgWzFdIGVsc2UgTkENCiAgUiRmaWxsX3BfZXhwbyA8LSBpZiAoIWlzLm51bGwoYW5fZmlsbF9lKSkgYW5fZmlsbF9lJGBQcig+RilgWzFdIGVsc2UgTkENCiAgbV9weF9lIDwtIHNhZmUobG0obG5fYXJlYSB+IGxuX21hcmNvICsgZXhwb3NpY2lvbiwgZGF0YSA9IGxpbSkpDQogIFIkcHhfZXhwb19wIDwtIGlmICghaXMubnVsbChtX3B4X2UpICYmICJleHBvc2ljaW9uc29tYnJhIiAlaW4lIHJvd25hbWVzKHN1bW1hcnkobV9weF9lKSRjb2VmZmljaWVudHMpKSBzdW1tYXJ5KG1fcHhfZSkkY29lZmZpY2llbnRzWyJleHBvc2ljaW9uc29tYnJhIiwgNF0gZWxzZSBOQQ0KfQ0KIyBjb21wbGV0YWRvIGRldGVybWluaXN0YSAoY29uIGNvcnJlY2Npw7NuIGRlIHJldHJhbnNmb3JtYWNpw7NuKSB5IGVzdG9jw6FzdGljbw0KZGF0b3MkYXJlYV9mIDwtIGlmZWxzZShkYXRvcyR1c2FyLCBkYXRvcyRhcmVhLCBOQV9yZWFsXykNCmRhdG9zJG9yaWdlbiA8LSBpZmVsc2UoZGF0b3MkdXNhciwgIm1lZGlkYSIsIE5BX2NoYXJhY3Rlcl8pDQppZHhfZmFsdGEgPC0gd2hpY2goIWRhdG9zJHVzYXIgJiAhaXMubmEoZGF0b3MkbWFyY29fY20yKSkNClIkbl9pbXAgPC0gbGVuZ3RoKGlkeF9mYWx0YSkNCmlmIChSJHByb3h5X29rICYmIFIkbl9pbXAgPiAwKSB7DQogIHByIDwtIHByZWRpY3QobV9weCwgbmV3ZGF0YSA9IGRhdG9zW2lkeF9mYWx0YSwgXSwgc2UuZml0ID0gVFJVRSkNCiAgZGF0b3MkYXJlYV9mW2lkeF9mYWx0YV0gPC0gZXhwKHByJGZpdCArIFIkcHhfc2lnbWFeMiAvIDIpDQogIGRhdG9zJG9yaWdlbltpZHhfZmFsdGFdIDwtICJjb21wbGV0YWRhIChtb2RlbG8pIg0KICBwcmkgPC0gcHJlZGljdChtX3B4LCBuZXdkYXRhID0gZGF0b3NbaWR4X2ZhbHRhLCBdLCBpbnRlcnZhbCA9ICJwcmVkaWN0aW9uIikNCiAgUiRpbXBfcGlfcmVsIDwtIG1lYW4oKGV4cChwcmlbLCAidXByIl0pIC0gZXhwKHByaVssICJsd3IiXSkpIC8gMiAvIGV4cChwcmlbLCAiZml0Il0pKQ0KfQ0KZGF0b3MkbG5fYXJlYV9mIDwtIGxvZyhkYXRvcyRhcmVhX2YpDQpgYGANCg0KYGBge3IgY2FsY19kZXNjLCBpbmNsdWRlPUZBTFNFfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgMy4gRVNUQUTDjVNUSUNBIERFU0NSSVBUSVZBLCDDgVJCT0wgQ09NTyBVTklEQUQsIEFUw41QSUNPUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCnJlc3VtZW5fYXJib2wgPC0gZnVuY3Rpb24oZCkgew0KICBuIDwtIG5yb3coZCk7IHggPC0gZCRhcmVhDQogIHRjcml0IDwtIGlmIChuID4gMSkgcXQoMC45NzUsIG4gLSAxKSBlbHNlIE5BDQogIGRhdGEuZnJhbWUoYXJib2wgPSBkJGFyYm9sWzFdLCBleHBvc2ljaW9uID0gYXMuY2hhcmFjdGVyKGQkZXhwb3NpY2lvblsxXSksIG4gPSBuLA0KICAgICAgICAgICAgIG1lZGlhID0gbWVhbih4KSwgbWVkaWFuYSA9IG1lZGlhbih4KSwgZGUgPSBpZiAobiA+IDEpIHNkKHgpIGVsc2UgTkEsIGN2ID0gaWYgKG4gPiAxKSBjdih4KSBlbHNlIE5BLA0KICAgICAgICAgICAgIGVlID0gaWYgKG4gPiAxKSBzZCh4KSAvIHNxcnQobikgZWxzZSBOQSwgbGkgPSBpZiAobiA+IDEpIG1lYW4oeCkgLSB0Y3JpdCAqIHNkKHgpIC8gc3FydChuKSBlbHNlIE5BLA0KICAgICAgICAgICAgIGxzID0gaWYgKG4gPiAxKSBtZWFuKHgpICsgdGNyaXQgKiBzZCh4KSAvIHNxcnQobikgZWxzZSBOQSwgbWluID0gbWluKHgpLCBtYXggPSBtYXgoeCksDQogICAgICAgICAgICAgcmljID0gSVFSKHgpLCBtZWRpYV9sbiA9IG1lYW4oZCRsbl9hcmVhKSwgZGVfbG4gPSBpZiAobiA+IDEpIHNkKGQkbG5fYXJlYSkgZWxzZSBOQSwNCiAgICAgICAgICAgICBnZW9tID0gZXhwKG1lYW4oZCRsbl9hcmVhKSksIGxhdCA9IGQkbGF0WzFdLCBsb24gPSBkJGxvblsxXSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KfQ0KZGVzY19hbGwgPC0gZG8uY2FsbChyYmluZCwgbGFwcGx5KHNwbGl0KGxpbSwgbGltJGFyYm9sKSwgcmVzdW1lbl9hcmJvbCkpDQpkZXNjX2FsbCA8LSBkZXNjX2FsbFtvcmRlcihhcy5pbnRlZ2VyKGdzdWIoIlxcRCIsICIiLCBkZXNjX2FsbCRhcmJvbCkpKSwgXQ0KYXJiIDwtIGRlc2NfYWxsW2Rlc2NfYWxsJG4gPj0gcGFyYW1zJG1pbl9ob2phc19hcmJvbCwgXSAgICAgICAgICAjIMOhcmJvbGVzIHF1ZSBlbnRyYW4gYSBsYSBpbmZlcmVuY2lhDQphcmIkZXhwb3NpY2lvbiA8LSBmYWN0b3IoYXJiJGV4cG9zaWNpb24sIGxldmVscyA9IGMoInNvbCIsICJzb21icmEiKSkNCmxpbSRhcmJvbF9mIDwtIGZhY3RvcihsaW0kYXJib2wpDQpsaW1BIDwtIGxpbVtsaW0kYXJib2wgJWluJSBhcmIkYXJib2wsIF07IGxpbUEkYXJib2xfZiA8LSBmYWN0b3IobGltQSRhcmJvbCkNCmxpbUEkZXhwb3NpY2lvbiA8LSBkcm9wbGV2ZWxzKGxpbUEkZXhwb3NpY2lvbikNClIkbl9hcmJfaW5mIDwtIG5yb3coYXJiKTsgUiRuX3NvbCA8LSBzdW0oYXJiJGV4cG9zaWNpb24gPT0gInNvbCIpOyBSJG5fc29tIDwtIHN1bShhcmIkZXhwb3NpY2lvbiA9PSAic29tYnJhIikNClIkYXJiX3NvbCA8LSBhcmIkYXJib2xbYXJiJGV4cG9zaWNpb24gPT0gInNvbCJdOyBSJGFyYl9zb20gPC0gYXJiJGFyYm9sW2FyYiRleHBvc2ljaW9uID09ICJzb21icmEiXQ0KUiRhcmJfZXhjbCA8LSBzZXRkaWZmKGFyYm9sZXNfYWxsLCBhcmIkYXJib2wpDQpSJG1fc29sIDwtIG1lYW4oYXJiJG1lZGlhW2FyYiRleHBvc2ljaW9uID09ICJzb2wiXSk7IFIkbV9zb20gPC0gbWVhbihhcmIkbWVkaWFbYXJiJGV4cG9zaWNpb24gPT0gInNvbWJyYSJdKQ0KUiRnX3NvbCA8LSBleHAobWVhbihhcmIkbWVkaWFfbG5bYXJiJGV4cG9zaWNpb24gPT0gInNvbCJdKSk7IFIkZ19zb20gPC0gZXhwKG1lYW4oYXJiJG1lZGlhX2xuW2FyYiRleHBvc2ljaW9uID09ICJzb21icmEiXSkpDQpSJGN2X3JhbmdvIDwtIHJhbmdlKGRlc2NfYWxsJGN2LCBuYS5ybSA9IFRSVUUpOyBSJG1lZGlhX3JhbmdvIDwtIHJhbmdlKGRlc2NfYWxsJG1lZGlhKQ0KUiRhcmJfbWF4IDwtIGRlc2NfYWxsJGFyYm9sW3doaWNoLm1heChkZXNjX2FsbCRtZWRpYSldOyBSJGFyYl9taW4gPC0gZGVzY19hbGwkYXJib2xbd2hpY2gubWluKGRlc2NfYWxsJG1lZGlhKV0NCg0KIyAtLS0tIFZhbG9yZXMgYXTDrXBpY29zOiBUdWtleSBwb3Igw6FyYm9sLCB6IHJvYnVzdG8gKE1BRCkgeSByZXNpZHVvcyBzdHVkZW50aXphZG9zIC0tLS0NCmF0aXAgPC0gZG8uY2FsbChyYmluZCwgbGFwcGx5KHNwbGl0KGxpbSwgbGltJGFyYm9sKSwgZnVuY3Rpb24oZCkgew0KICBpZiAobnJvdyhkKSA8IDQpIHJldHVybihOVUxMKQ0KICB4IDwtIGQkYXJlYTsgcSA8LSBxdWFudGlsZSh4LCBjKC4yNSwgLjc1KSk7IGlxciA8LSBkaWZmKHEpDQogIG1lZCA8LSBtZWRpYW4oeCk7IG1hZHYgPC0gbWFkKHgsIGNvbnN0YW50ID0gMSkNCiAgeiA8LSBpZiAobWFkdiA+IDApIDAuNjc0NSAqICh4IC0gbWVkKSAvIG1hZHYgZWxzZSByZXAoMCwgbGVuZ3RoKHgpKQ0KICBvdXRfdCA8LSB4IDwgcVsxXSAtIDEuNSAqIGlxciB8IHggPiBxWzJdICsgMS41ICogaXFyDQogIGRhdGEuZnJhbWUoYXJib2wgPSBkJGFyYm9sLCBuX2hvamEgPSBkJG5faG9qYSwgYXJlYSA9IHgsIHpfcm9idXN0byA9IHosIGZ1ZXJhX3R1a2V5ID0gb3V0X3QsIGZ1ZXJhX3ogPSBhYnMoeikgPiAzLjUsDQogICAgICAgICAgICAgcmF6b25fbWVkaWFuYSA9IHggLyBtZWQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCn0pKQ0KaWYgKGlzLm51bGwoYXRpcCkpIGF0aXAgPC0gZGF0YS5mcmFtZShhcmJvbCA9IGNoYXJhY3RlcigpLCBuX2hvamEgPSBpbnRlZ2VyKCksIGFyZWEgPSBudW1lcmljKCksIHpfcm9idXN0byA9IG51bWVyaWMoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVlcmFfdHVrZXkgPSBsb2dpY2FsKCksIGZ1ZXJhX3ogPSBsb2dpY2FsKCksIHJhem9uX21lZGlhbmEgPSBudW1lcmljKCkpDQphdGlwX21hcmNhZGFzIDwtIGF0aXBbYXRpcCRmdWVyYV90dWtleSB8IGF0aXAkZnVlcmFfeiwgXQ0KUiRuX2F0aXAgPC0gbnJvdyhhdGlwX21hcmNhZGFzKQ0KbV9yZXMgPC0gaWYgKGxlbmd0aCh1bmlxdWUobGltQSRhcmJvbCkpID49IDIpIHNhZmUobG0obG5fYXJlYSB+IGFyYm9sX2YsIGRhdGEgPSBsaW1BKSkgZWxzZSBOVUxMDQppZiAoIWlzLm51bGwobV9yZXMpKSB7DQogIGxpbUEkcnN0dWQgPC0gcnN0dWRlbnQobV9yZXMpOyBsaW1BJGNvb2sgPC0gY29va3MuZGlzdGFuY2UobV9yZXMpDQogIFIkbl9yc3R1ZCA8LSBzdW0oYWJzKGxpbUEkcnN0dWQpID4gMywgbmEucm0gPSBUUlVFKTsgUiRuX2Nvb2sgPC0gc3VtKGxpbUEkY29vayA+IDQgLyBucm93KGxpbUEpLCBuYS5ybSA9IFRSVUUpDQp9IGVsc2UgeyBsaW1BJHJzdHVkIDwtIE5BOyBsaW1BJGNvb2sgPC0gTkE7IFIkbl9yc3R1ZCA8LSBOQTsgUiRuX2Nvb2sgPC0gTkEgfQ0KIyBzZW5zaWJpbGlkYWQgYWwgdHJhdGFtaWVudG8gZGUgYXTDrXBpY29zIChkaWZlcmVuY2lhIHNvbWJyYSAtIHNvbCBlbnRyZSBtZWRpYXMgZGUgw6FyYm9sKQ0Kc2Vuc19lc3QgPC0gZnVuY3Rpb24oZCwgdGlwbykgew0KICBpZiAodGlwbyA9PSAibWVkaWEiKSBmIDwtIGZ1bmN0aW9uKHgpIG1lYW4oeCkNCiAgaWYgKHRpcG8gPT0gIm1lZGlhbmEiKSBmIDwtIGZ1bmN0aW9uKHgpIG1lZGlhbih4KQ0KICBpZiAodGlwbyA9PSAic2luX2F0aXAiKSB7IGYgPC0gZnVuY3Rpb24oeCkgeyBpZiAobGVuZ3RoKHgpIDwgNCkgcmV0dXJuKG1lYW4oeCkpOyBvIDwtIGJveHBsb3Quc3RhdHMoeCkkb3V0OyBtZWFuKHhbIXggJWluJSBvXSkgfSB9DQogIGlmICh0aXBvID09ICJyZWNvcnRhZGEiKSBmIDwtIGZ1bmN0aW9uKHgpIG1lYW4oeCwgdHJpbSA9IDAuMikNCiAgbXQgPC0gdGFwcGx5KGQkYXJlYSwgZCRhcmJvbCwgZik7IHRlIDwtIHRhcHBseShhcy5jaGFyYWN0ZXIoZCRleHBvc2ljaW9uKSwgZCRhcmJvbCwgZnVuY3Rpb24oeikgelsxXSkNCiAgbWVhbihtdFt0ZSA9PSAic29tYnJhIl0pIC0gbWVhbihtdFt0ZSA9PSAic29sIl0pDQp9DQpzZW5zX3RhYiA8LSBkYXRhLmZyYW1lKFJlc3VtZW4gPSBjKCJNZWRpYSBhcml0bcOpdGljYSBwb3Igw6FyYm9sIiwgIk1lZGlhbmEgcG9yIMOhcmJvbCIsICJNZWRpYSBzaW4gaG9qYXMgYXTDrXBpY2FzIChUdWtleSkiLCAiTWVkaWEgcmVjb3J0YWRhIDIwICUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgZGlmID0gdmFwcGx5KGMoIm1lZGlhIiwgIm1lZGlhbmEiLCAic2luX2F0aXAiLCAicmVjb3J0YWRhIiksIGZ1bmN0aW9uKHQpIHNlbnNfZXN0KGxpbUEsIHQpLCBudW1lcmljKDEpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KUiRzZW5zX3JhbmdvIDwtIHJhbmdlKHNlbnNfdGFiJGRpZiwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCmBgYHtyIGNhbGNfaW5mZXJlbmNpYSwgaW5jbHVkZT1GQUxTRX0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDQuIElORkVSRU5DSUEgU09CUkUgTEEgRVhQT1NJQ0nDk04gKFVOSURBRCA9IMOBUkJPTCkNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpwZXJtX2V4YWN0IDwtIGZ1bmN0aW9uKHksIGcpIHsNCiAgbiA8LSBsZW5ndGgoeSk7IGsgPC0gc3VtKGcpDQogIGlmIChrIDwgMSB8fCBrID49IG4pIHJldHVybihOVUxMKQ0KICBpZiAoY2hvb3NlKG4sIGspID4gMmU1KSByZXR1cm4oTlVMTCkgICAgICAgICAgIyBkZW1hc2lhZGFzIGNvbWJpbmFjaW9uZXM6IHNlIG9taXRlDQogIGlkeCA8LSBjb21ibihuLCBrKQ0KICBkIDwtIGFwcGx5KGlkeCwgMiwgZnVuY3Rpb24oaSkgbWVhbih5W2ldKSAtIG1lYW4oeVstaV0pKQ0KICBvYnMgPC0gbWVhbih5W2ddKSAtIG1lYW4oeVshZ10pDQogIHBtaW5fIDwtIG1lYW4oYWJzKGQpID49IG1heChhYnMoZCkpIC0gMWUtOSkNCiAgbGlzdChkID0gZCwgb2JzID0gb2JzLCBwID0gbWVhbihhYnMoZCkgPj0gYWJzKG9icykgLSAxZS05KSwgbl9yZXAgPSBuY29sKGlkeCksIHBfbWluID0gcG1pbl8pDQp9DQpiYXRlcmlhIDwtIGZ1bmN0aW9uKGEsIGNvbCA9ICJtZWRpYV9sbiIpIHsNCiAgYSA8LSBhW2lzLmZpbml0ZShhW1tjb2xdXSksIF0NCiAgeSA8LSBhW1tjb2xdXTsgZyA8LSBhcy5jaGFyYWN0ZXIoYSRleHBvc2ljaW9uKSA9PSAic29tYnJhIg0KICBucyA8LSBzdW0oIWcpOyBubSA8LSBzdW0oZykNCiAgbyA8LSBsaXN0KG5fc29sID0gbnMsIG5fc29tID0gbm0sIGRpZiA9IE5BX3JlYWxfLCByYXpvbiA9IE5BX3JlYWxfLCBsaSA9IE5BX3JlYWxfLCBscyA9IE5BX3JlYWxfLCBwX3dlbGNoID0gTkFfcmVhbF8sDQogICAgICAgICAgICBkZiA9IE5BX3JlYWxfLCBwX3dpbGNveCA9IE5BX3JlYWxfLCBwX3Blcm0gPSBOQV9yZWFsXywgcF9taW4gPSBOQV9yZWFsXywgZyA9IE5BX3JlYWxfLCBnX2xpID0gTkFfcmVhbF8sIGdfbHMgPSBOQV9yZWFsXywgcGVybSA9IE5VTEwpDQogIGlmIChucyA8IDEgfHwgbm0gPCAxKSByZXR1cm4obykNCiAgbyRkaWYgPC0gbWVhbih5W2ddKSAtIG1lYW4oeVshZ10pOyBvJHJhem9uIDwtIGV4cChvJGRpZikNCiAgaWYgKG5zID49IDIgJiYgbm0gPj0gMikgew0KICAgIHR0IDwtIHQudGVzdCh5W2ddLCB5WyFnXSk7IG8kbGkgPC0gZXhwKHR0JGNvbmYuaW50WzFdKTsgbyRscyA8LSBleHAodHQkY29uZi5pbnRbMl0pOyBvJHBfd2VsY2ggPC0gdHQkcC52YWx1ZTsgbyRkZiA8LSB1bm5hbWUodHQkcGFyYW1ldGVyKQ0KICAgIHNwIDwtIHNxcnQoKChubSAtIDEpICogdmFyKHlbZ10pICsgKG5zIC0gMSkgKiB2YXIoeVshZ10pKSAvIChucyArIG5tIC0gMikpDQogICAgSiA8LSAxIC0gMyAvICg0ICogKG5zICsgbm0gLSAyKSAtIDEpOyBvJGcgPC0gSiAqIG8kZGlmIC8gc3ANCiAgICBzZV9nIDwtIHNxcnQoKG5zICsgbm0pIC8gKG5zICogbm0pICsgbyRnXjIgLyAoMiAqIChucyArIG5tIC0gMikpKTsgbyRnX2xpIDwtIG8kZyAtIDEuOTYgKiBzZV9nOyBvJGdfbHMgPC0gbyRnICsgMS45NiAqIHNlX2cNCiAgICBvJHBfd2lsY294IDwtIHN1cHByZXNzV2FybmluZ3Mod2lsY294LnRlc3QoeVtnXSwgeVshZ10sIGV4YWN0ID0gVFJVRSkkcC52YWx1ZSkNCiAgfQ0KICBpZiAobGVuZ3RoKHkpID49IDMpIHsgcGUgPC0gcGVybV9leGFjdCh5LCBnKTsgaWYgKCFpcy5udWxsKHBlKSkgeyBvJHBfcGVybSA8LSBwZSRwOyBvJHBfbWluIDwtIHBlJHBfbWluOyBvJHBlcm0gPC0gcGUgfSB9DQogIG8NCn0NCiMgQSkgw6FyZWEgbWVkaWRhLCBsbiBkZWwgw6FyZWEgcG9yIMOhcmJvbA0KYkEgPC0gYmF0ZXJpYShhcmIsICJtZWRpYV9sbiIpOyBSJGJBIDwtIGJBDQojIEEnKSBlbiBjbTIgKGRpZmVyZW5jaWEgYXJpdG3DqXRpY2EgZGUgbWVkaWFzIGRlIMOhcmJvbCkNCmJjbSA8LSBOVUxMDQppZiAoUiRuX3NvbCA+PSAyICYmIFIkbl9zb20gPj0gMikgew0KICB0dF9jbSA8LSB0LnRlc3QoYXJiJG1lZGlhW2FyYiRleHBvc2ljaW9uID09ICJzb21icmEiXSwgYXJiJG1lZGlhW2FyYiRleHBvc2ljaW9uID09ICJzb2wiXSkNCiAgYmNtIDwtIGxpc3QoZGlmID0gdW5uYW1lKHR0X2NtJGVzdGltYXRlWzFdIC0gdHRfY20kZXN0aW1hdGVbMl0pLCBsaSA9IHR0X2NtJGNvbmYuaW50WzFdLCBscyA9IHR0X2NtJGNvbmYuaW50WzJdLCBwID0gdHRfY20kcC52YWx1ZSkNCn0NClIkYmNtIDwtIGJjbQ0KUiRkaWZfY20gPC0gUiRtX3NvbSAtIFIkbV9zb2wNCiMgQikgcHJveHk6IG1hcmNvIGRlIHRvZGFzIGxhcyBob2phcw0KcHJveCA8LSBkby5jYWxsKHJiaW5kLCBsYXBwbHkoc3BsaXQoZGF0b3NbIWlzLm5hKGRhdG9zJGxuX21hcmNvKSAmICFpcy5uYShkYXRvcyRleHBvc2ljaW9uKSwgXSwgZGF0b3MkYXJib2xbIWlzLm5hKGRhdG9zJGxuX21hcmNvKSAmICFpcy5uYShkYXRvcyRleHBvc2ljaW9uKV0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oZCkgZGF0YS5mcmFtZShhcmJvbCA9IGQkYXJib2xbMV0sIGV4cG9zaWNpb24gPSBhcy5jaGFyYWN0ZXIoZCRleHBvc2ljaW9uWzFdKSwgbWVkaWFfbG4gPSBtZWFuKGQkbG5fbWFyY28pLCBuID0gbnJvdyhkKSkpKQ0KcHJveCRleHBvc2ljaW9uIDwtIGZhY3Rvcihwcm94JGV4cG9zaWNpb24sIGxldmVscyA9IGMoInNvbCIsICJzb21icmEiKSkNCmJCIDwtIGJhdGVyaWEocHJveCwgIm1lZGlhX2xuIik7IFIkYkIgPC0gYkINCiMgQykgw6FyZWFzIG1lZGlkYXMgKyBjb21wbGV0YWRhcyBwb3IgZWwgbW9kZWxvIGRlbCBtYXJjbw0KY29tcF9hcmIgPC0gZG8uY2FsbChyYmluZCwgbGFwcGx5KHNwbGl0KGRhdG9zWyFpcy5uYShkYXRvcyRsbl9hcmVhX2YpICYgIWlzLm5hKGRhdG9zJGV4cG9zaWNpb24pLCBdLCBkYXRvcyRhcmJvbFshaXMubmEoZGF0b3MkbG5fYXJlYV9mKSAmICFpcy5uYShkYXRvcyRleHBvc2ljaW9uKV0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGQpIGRhdGEuZnJhbWUoYXJib2wgPSBkJGFyYm9sWzFdLCBleHBvc2ljaW9uID0gYXMuY2hhcmFjdGVyKGQkZXhwb3NpY2lvblsxXSksIG1lZGlhX2xuID0gbWVhbihkJGxuX2FyZWFfZiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYSA9IG1lYW4oZCRhcmVhX2YpLCBuID0gbnJvdyhkKSwgbl9pbXAgPSBzdW0oZCRvcmlnZW4gPT0gImNvbXBsZXRhZGEgKG1vZGVsbykiKSkpKQ0KY29tcF9hcmIkZXhwb3NpY2lvbiA8LSBmYWN0b3IoY29tcF9hcmIkZXhwb3NpY2lvbiwgbGV2ZWxzID0gYygic29sIiwgInNvbWJyYSIpKQ0KYkMgPC0gYmF0ZXJpYShjb21wX2FyYiwgIm1lZGlhX2xuIik7IFIkYkMgPC0gYkMNCiMgQycpIGluY2VydGlkdW1icmUgZGVsIGNvbXBsZXRhZG8gKHNpbXVsYWNpw7NuKQ0KUiRzaW0gPC0gTlVMTA0KaWYgKFIkcHJveHlfb2sgJiYgUiRuX2ltcCA+IDApIHsNCiAgcHJfcyA8LSBwcmVkaWN0KG1fcHgsIG5ld2RhdGEgPSBkYXRvc1tpZHhfZmFsdGEsIF0sIHNlLmZpdCA9IFRSVUUpDQogIHNkX3MgPC0gc3FydChSJHB4X3NpZ21hXjIgKyBwcl9zJHNlLmZpdF4yKQ0KICB0ZSA8LSB0YXBwbHkoYXMuY2hhcmFjdGVyKGRhdG9zJGV4cG9zaWNpb24pLCBkYXRvcyRhcmJvbCwgZnVuY3Rpb24oeikgelsxXSkNCiAgbG5fYmFzZSA8LSBkYXRvcyRsbl9hcmVhX2Y7IGxuX2Jhc2VbaWR4X2ZhbHRhXSA8LSBOQQ0KICBzaW0gPC0gcmVwbGljYXRlKHBhcmFtcyRNX2ltcCwgew0KICAgIHggPC0gbG5fYmFzZTsgeFtpZHhfZmFsdGFdIDwtIHByX3MkZml0ICsgcm5vcm0obGVuZ3RoKGlkeF9mYWx0YSksIDAsIHNkX3MpDQogICAgbXQgPC0gdGFwcGx5KHgsIGRhdG9zJGFyYm9sLCBtZWFuLCBuYS5ybSA9IFRSVUUpOyBtdCA8LSBtdFtuYW1lcyh0ZSldDQogICAgbWVhbihtdFt0ZSA9PSAic29tYnJhIl0sIG5hLnJtID0gVFJVRSkgLSBtZWFuKG10W3RlID09ICJzb2wiXSwgbmEucm0gPSBUUlVFKQ0KICB9KQ0KICBSJHNpbSA8LSBzaW07IFIkc2ltX3EgPC0gcXVhbnRpbGUoZXhwKHNpbSksIGMoLjAyNSwgLjUsIC45NzUpLCBuYS5ybSA9IFRSVUUpDQp9DQojIEQpIHBzZXVkb3JyZXBsaWNhY2nDs246IGhvamFzIGNvbW8gZGF0b3MgaW5kZXBlbmRpZW50ZXMgKMKhaW5jb3JyZWN0byEpDQpSJHBzZXVkbyA8LSBOVUxMDQppZiAobGVuZ3RoKHVuaXF1ZShsaW1BJGV4cG9zaWNpb24pKSA9PSAyKSB7DQogIHRwIDwtIHQudGVzdChsbl9hcmVhIH4gZXhwb3NpY2lvbiwgZGF0YSA9IGxpbUEpDQogIFIkcHNldWRvIDwtIGxpc3QocmF6b24gPSBleHAodW5uYW1lKHRwJGVzdGltYXRlWzJdIC0gdHAkZXN0aW1hdGVbMV0pKSwgbGkgPSBleHAoLXRwJGNvbmYuaW50WzJdKSwgbHMgPSBleHAoLXRwJGNvbmYuaW50WzFdKSwNCiAgICAgICAgICAgICAgICAgICBwID0gdHAkcC52YWx1ZSwgbiA9IG5yb3cobGltQSkpDQp9DQojIEUpIGJvb3RzdHJhcCBqZXLDoXJxdWljbyBlbiBkb3MgZXRhcGFzDQpib290X2RvcyA8LSBmdW5jdGlvbihkLCBCKSB7DQogIHRyIDwtIHVuaXF1ZShkWywgYygiYXJib2wiLCAiZXhwb3NpY2lvbiIpXSk7IHYgPC0gc3BsaXQoZCRsbl9hcmVhLCBkJGFyYm9sKQ0KICB0ciRleHBvc2ljaW9uIDwtIGFzLmNoYXJhY3Rlcih0ciRleHBvc2ljaW9uKQ0KICBvdXQgPC0gbnVtZXJpYyhCKQ0KICBmb3IgKGIgaW4gc2VxX2xlbihCKSkgew0KICAgIG0gPC0gdmFwcGx5KGMoInNvbCIsICJzb21icmEiKSwgZnVuY3Rpb24oZXgpIHsNCiAgICAgIGlkcyA8LSB0ciRhcmJvbFt0ciRleHBvc2ljaW9uID09IGV4XQ0KICAgICAgcyA8LSBpZHNbc2FtcGxlLmludChsZW5ndGgoaWRzKSwgbGVuZ3RoKGlkcyksIHJlcGxhY2UgPSBUUlVFKV0NCiAgICAgIG1lYW4odmFwcGx5KHMsIGZ1bmN0aW9uKGEpIHsgeCA8LSB2W1thXV07IG1lYW4oeFtzYW1wbGUuaW50KGxlbmd0aCh4KSwgbGVuZ3RoKHgpLCByZXBsYWNlID0gVFJVRSldKSB9LCBudW1lcmljKDEpKSkNCiAgICB9LCBudW1lcmljKDEpKQ0KICAgIG91dFtiXSA8LSBtWyJzb21icmEiXSAtIG1bInNvbCJdDQogIH0NCiAgb3V0DQp9DQpSJGJvb3QgPC0gTlVMTA0KaWYgKFIkbl9zb2wgPj0gMSAmJiBSJG5fc29tID49IDEpIHsNCiAgYnQgPC0gYm9vdF9kb3MobGltQSwgcGFyYW1zJEJfYm9vdCk7IFIkYm9vdCA8LSBidA0KICBSJGJvb3RfY2kgPC0gZXhwKHF1YW50aWxlKGJ0LCBjKC4wMjUsIC45NzUpKSk7IFIkYm9vdF9wcm9iIDwtIG1lYW4oYnQgPiAwKQ0KICBSJGJvb3RfbnVuaXEgPC0gY2hvb3NlKDIgKiBSJG5fc29sIC0gMSwgUiRuX3NvbCkgKiBjaG9vc2UoMiAqIFIkbl9zb20gLSAxLCBSJG5fc29tKSAgICMgcmVtdWVzdHJhcyBkZSDDoXJib2xlcyBkaXN0aW50YXMNCn0NCiMgRikgbGVhdmUtb25lLXRyZWUtb3V0IChqYWNra25pZmUgcG9yIMOhcmJvbCkNCmprIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShhcmIkYXJib2wsIGZ1bmN0aW9uKGEpIHsNCiAgcyA8LSBhcmJbYXJiJGFyYm9sICE9IGEsIF0NCiAgZGF0YS5mcmFtZShvbWl0aWRvID0gYSwgZXhwb3NpY2lvbiA9IGFzLmNoYXJhY3RlcihhcmIkZXhwb3NpY2lvblthcmIkYXJib2wgPT0gYV0pLA0KICAgICAgICAgICAgIHJhem9uID0gaWYgKGFueShzJGV4cG9zaWNpb24gPT0gInNvbCIpICYmIGFueShzJGV4cG9zaWNpb24gPT0gInNvbWJyYSIpKQ0KICAgICAgICAgICAgICAgZXhwKG1lYW4ocyRtZWRpYV9sbltzJGV4cG9zaWNpb24gPT0gInNvbWJyYSJdKSAtIG1lYW4ocyRtZWRpYV9sbltzJGV4cG9zaWNpb24gPT0gInNvbCJdKSkgZWxzZSBOQV9yZWFsXykNCn0pKQ0KUiRqayA8LSBqazsgUiRqa19yYW5nbyA8LSByYW5nZShqayRyYXpvbiwgbmEucm0gPSBUUlVFKQ0KUiRqa19jcnV6YSA8LSAhaXMubmEoUiRqa19yYW5nb1sxXSkgJiYgUiRqa19yYW5nb1sxXSA8IDEgJiYgUiRqa19yYW5nb1syXSA+IDENCmBgYA0KDQpgYGB7ciBjYWxjX21vZGVsb3MsIGluY2x1ZGU9RkFMU0V9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyA1LiBNT0RFTE9TOiBBTk9WQSBBTklEQURPLCBNT0RFTE8gTUlYVE8sIEFOT1ZBIERFIFVOIEZBQ1RPUiBZIFRVS0VZDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KdHdvX2V4cG8gPC0gbGVuZ3RoKHVuaXF1ZShsaW1BJGV4cG9zaWNpb24pKSA9PSAyDQpSJG5lc3RlZCA8LSBOVUxMDQppZiAodHdvX2V4cG8gJiYgbGVuZ3RoKHVuaXF1ZShsaW1BJGFyYm9sKSkgPj0gMykgew0KICBtX25lc3QgPC0gbG0obG5fYXJlYSB+IGV4cG9zaWNpb24gKyBhcmJvbF9mLCBkYXRhID0gbGltQSkNCiAgYW4gPC0gYW5vdmEobV9uZXN0KQ0KICBpZiAobnJvdyhhbikgPj0gMykgew0KICAgIEZlIDwtIGFuJGBNZWFuIFNxYFsxXSAvIGFuJGBNZWFuIFNxYFsyXTsgcGUgPC0gcGYoRmUsIGFuJERmWzFdLCBhbiREZlsyXSwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KICAgIEZhIDwtIGFuJGBNZWFuIFNxYFsyXSAvIGFuJGBNZWFuIFNxYFszXTsgcGEgPC0gcGYoRmEsIGFuJERmWzJdLCBhbiREZlszXSwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KICAgIFIkbmVzdGVkIDwtIGxpc3QoYW4gPSBhbiwgRmUgPSBGZSwgcGUgPSBwZSwgRmEgPSBGYSwgcGEgPSBwYSkNCiAgfQ0KfQ0KUiRtaXggPC0gTlVMTA0KaWYgKEhBU19MTUVSICYmIHR3b19leHBvICYmIGxlbmd0aCh1bmlxdWUobGltQSRhcmJvbCkpID49IDMpIHsNCiAgbV9taXggPC0gbG1lclRlc3Q6OmxtZXIobG5fYXJlYSB+IGV4cG9zaWNpb24gKyAoMSB8IGFyYm9sKSwgZGF0YSA9IGxpbUEsIFJFTUwgPSBUUlVFKQ0KICBtX251bCA8LSBsbWVyVGVzdDo6bG1lcihsbl9hcmVhIH4gMSArICgxIHwgYXJib2wpLCBkYXRhID0gbGltQSwgUkVNTCA9IFRSVUUpDQogIGNmIDwtIHN1bW1hcnkobV9taXgpJGNvZWZmaWNpZW50cw0KICBiIDwtIGNmWyJleHBvc2ljaW9uc29tYnJhIiwgIkVzdGltYXRlIl07IHNlIDwtIGNmWyJleHBvc2ljaW9uc29tYnJhIiwgIlN0ZC4gRXJyb3IiXTsgZGZiIDwtIGNmWyJleHBvc2ljaW9uc29tYnJhIiwgImRmIl0NCiAgdmMgPC0gYXMuZGF0YS5mcmFtZShsbWU0OjpWYXJDb3JyKG1fbWl4KSk7IHZfdCA8LSB2YyR2Y292W3ZjJGdycCA9PSAiYXJib2wiXTsgdl9lIDwtIHZjJHZjb3ZbdmMkZ3JwID09ICJSZXNpZHVhbCJdDQogIHZjMCA8LSBhcy5kYXRhLmZyYW1lKGxtZTQ6OlZhckNvcnIobV9udWwpKTsgdl90MCA8LSB2YzAkdmNvdlt2YzAkZ3JwID09ICJhcmJvbCJdOyB2X2UwIDwtIHZjMCR2Y292W3ZjMCRncnAgPT0gIlJlc2lkdWFsIl0NCiAgWCA8LSBsbWU0OjpnZXRNRShtX21peCwgIlgiKTsgdmYgPC0gdmFyKGFzLm51bWVyaWMoWCAlKiUgbG1lNDo6Zml4ZWYobV9taXgpKSkNCiAgcm4gPC0gc2FmZShsbWVyVGVzdDo6cmFub3ZhKG1fbWl4KSkNCiAgUiRtaXggPC0gbGlzdChtID0gbV9taXgsIGIgPSBiLCBzZSA9IHNlLCBkZiA9IGRmYiwgdCA9IGNmWyJleHBvc2ljaW9uc29tYnJhIiwgInQgdmFsdWUiXSwgcCA9IGNmWyJleHBvc2ljaW9uc29tYnJhIiwgIlByKD58dHwpIl0sDQogICAgICAgICAgICAgICAgcmF6b24gPSBleHAoYiksIGxpID0gZXhwKGIgLSBxdCguOTc1LCBkZmIpICogc2UpLCBscyA9IGV4cChiICsgcXQoLjk3NSwgZGZiKSAqIHNlKSwNCiAgICAgICAgICAgICAgICB2X3QgPSB2X3QsIHZfZSA9IHZfZSwgaWNjX2FkaiA9IHZfdCAvICh2X3QgKyB2X2UpLCBpY2MwID0gdl90MCAvICh2X3QwICsgdl9lMCksIHZfdDAgPSB2X3QwLCB2X2UwID0gdl9lMCwNCiAgICAgICAgICAgICAgICByMm0gPSB2ZiAvICh2ZiArIHZfdCArIHZfZSksIHIyYyA9ICh2ZiArIHZfdCkgLyAodmYgKyB2X3QgKyB2X2UpLA0KICAgICAgICAgICAgICAgIHBfcmFuZWYgPSBpZiAoIWlzLm51bGwocm4pKSBybiRgUHIoPkNoaXNxKWBbMl0gZWxzZSBOQSwgc2luZ3VsYXIgPSBsbWU0Ojppc1Npbmd1bGFyKG1fbWl4KSkNCn0NCiMgSUNDIGRlIHVuIGZhY3RvciBwb3IgQU5PVkEgKG4wID0gdGFtYcOxbyBtZWRpbyBwb25kZXJhZG8pLCBjb24gSUMgZGUgTWNHcmF3LVdvbmcNClIkaWNjIDwtIE5VTEwNCmlmIChsZW5ndGgodW5pcXVlKGxpbUEkYXJib2wpKSA+PSAyKSB7DQogIGExIDwtIGFub3ZhKGxtKGxuX2FyZWEgfiBhcmJvbF9mLCBkYXRhID0gbGltQSkpOyBrIDwtIG5sZXZlbHMobGltQSRhcmJvbF9mKTsgTiA8LSBucm93KGxpbUEpOyBuaSA8LSB0YWJsZShsaW1BJGFyYm9sX2YpDQogIG4wIDwtIChOIC0gc3VtKG5pXjIpIC8gTikgLyAoayAtIDEpOyBGdiA8LSBhMSRgRiB2YWx1ZWBbMV07IGQxIDwtIGExJERmWzFdOyBkMiA8LSBhMSREZlsyXQ0KICBpY2MgPC0gKEZ2IC0gMSkgLyAoRnYgKyBuMCAtIDEpDQogIEZMIDwtIEZ2IC8gcWYoLjk3NSwgZDEsIGQyKTsgRlUgPC0gRnYgKiBxZiguOTc1LCBkMiwgZDEpDQogIFIkaWNjIDwtIGxpc3QoaWNjID0gaWNjLCBsaSA9IChGTCAtIDEpIC8gKEZMICsgbjAgLSAxKSwgbHMgPSAoRlUgLSAxKSAvIChGVSArIG4wIC0gMSksIG4wID0gbjAsIEYgPSBGdiwgZDEgPSBkMSwgZDIgPSBkMiwgcCA9IGExJGBQcig+RilgWzFdLCBhbiA9IGExKQ0KICBzcyA8LSBhMSRgU3VtIFNxYDsgUiRldGEyIDwtIHNzWzFdIC8gc3VtKHNzKTsgUiRvbWVnYTIgPC0gKHNzWzFdIC0gZDEgKiBhMSRgTWVhbiBTcWBbMl0pIC8gKHN1bShzcykgKyBhMSRgTWVhbiBTcWBbMl0pDQp9DQojIHN1cHVlc3RvcyB5IGFsdGVybmF0aXZhcyByb2J1c3RhcyBkZWwgQU5PVkEgZGUgdW4gZmFjdG9yDQpSJHN1cCA8LSBOVUxMDQppZiAoIWlzLm51bGwoUiRpY2MpKSB7DQogIG0xIDwtIGxtKGxuX2FyZWEgfiBhcmJvbF9mLCBkYXRhID0gbGltQSkNCiAgc2ggPC0gc2hhcGlyby50ZXN0KHJlc2lkKG0xKSk7IGZsIDwtIGZsaWduZXIudGVzdChsbl9hcmVhIH4gYXJib2xfZiwgZGF0YSA9IGxpbUEpDQogIGxpbUEkYWJzZGV2IDwtIGFicyhsaW1BJGxuX2FyZWEgLSBhdmUobGltQSRsbl9hcmVhLCBsaW1BJGFyYm9sX2YsIEZVTiA9IG1lZGlhbikpOyBiZiA8LSBhbm92YShsbShhYnNkZXYgfiBhcmJvbF9mLCBkYXRhID0gbGltQSkpDQogIHdhIDwtIG9uZXdheS50ZXN0KGxuX2FyZWEgfiBhcmJvbF9mLCBkYXRhID0gbGltQSwgdmFyLmVxdWFsID0gRkFMU0UpOyBrdyA8LSBrcnVza2FsLnRlc3QobG5fYXJlYSB+IGFyYm9sX2YsIGRhdGEgPSBsaW1BKQ0KICBSJHN1cCA8LSBsaXN0KG0xID0gbTEsIHNoX3AgPSBzaCRwLnZhbHVlLCBzaF9XID0gdW5uYW1lKHNoJHN0YXRpc3RpYyksIGZsX3AgPSBmbCRwLnZhbHVlLCBiZl9wID0gYmYkYFByKD5GKWBbMV0sDQogICAgICAgICAgICAgICAgd2VsY2hfRiA9IHVubmFtZSh3YSRzdGF0aXN0aWMpLCB3ZWxjaF9kZiA9IHVubmFtZSh3YSRwYXJhbWV0ZXIpLCB3ZWxjaF9wID0gd2EkcC52YWx1ZSwga3dfcCA9IGt3JHAudmFsdWUsIGt3X2NoaSA9IHVubmFtZShrdyRzdGF0aXN0aWMpKQ0KfQ0KIyBUdWtleSBIU0QgZW50cmUgw6FyYm9sZXMgKHJhem9uZXMgZGUgw6FyZWFzKQ0KUiR0ayA8LSBOVUxMDQppZiAoIWlzLm51bGwoUiRpY2MpICYmIG5sZXZlbHMobGltQSRhcmJvbF9mKSA+PSAzKSB7DQogIHRrIDwtIFR1a2V5SFNEKGFvdihsbl9hcmVhIH4gYXJib2xfZiwgZGF0YSA9IGxpbUEpKSRhcmJvbF9mDQogIHRrdCA8LSBkYXRhLmZyYW1lKGNvbXBhcmFjaW9uID0gcm93bmFtZXModGspLCByYXpvbiA9IGV4cCh0a1ssICJkaWZmIl0pLCBsaSA9IGV4cCh0a1ssICJsd3IiXSksIGxzID0gZXhwKHRrWywgInVwciJdKSwgcCA9IHRrWywgInAgYWRqIl0sIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCiAgcHAgPC0gc3Ryc3BsaXQodGt0JGNvbXBhcmFjaW9uLCAiLSIpDQogIHRlMiA8LSB0YXBwbHkoYXMuY2hhcmFjdGVyKGxpbUEkZXhwb3NpY2lvbiksIGFzLmNoYXJhY3RlcihsaW1BJGFyYm9sKSwgZnVuY3Rpb24oeikgelsxXSkNCiAgdGt0JG1pc21hIDwtIHZhcHBseShwcCwgZnVuY3Rpb24oeCkgbGVuZ3RoKHVuaXF1ZSh0ZTJbeF0pKSA9PSAxLCBsb2dpY2FsKDEpKQ0KICB0a3QkY29tcGFyYWNpb24gPC0gdmFwcGx5KHBwLCBmdW5jdGlvbih4KSBwYXN0ZTAoeFsxXSwgIiAvICIsIHhbMl0pLCBjaGFyYWN0ZXIoMSkpDQogIHRrdCA8LSB0a3Rbb3JkZXIodGt0JHApLCBdDQogIHB3IDwtIHBhaXJ3aXNlLnQudGVzdChsaW1BJGxuX2FyZWEsIGxpbUEkYXJib2xfZiwgcG9vbC5zZCA9IEZBTFNFLCBwLmFkanVzdC5tZXRob2QgPSAiaG9sbSIpJHAudmFsdWUNCiAgZ2V0cCA8LSBmdW5jdGlvbihhLCBiKSB7DQogICAgaWYgKGEgJWluJSByb3duYW1lcyhwdykgJiYgYiAlaW4lIGNvbG5hbWVzKHB3KSkgcHdbYSwgYl0gZWxzZSBpZiAoYiAlaW4lIHJvd25hbWVzKHB3KSAmJiBhICVpbiUgY29sbmFtZXMocHcpKSBwd1tiLCBhXSBlbHNlIE5BX3JlYWxfDQogIH0NCiAgdGt0JHBfd2VsY2hfaG9sbSA8LSB2YXBwbHkoc3Ryc3BsaXQodGt0JGNvbXBhcmFjaW9uLCAiIC8gIiksIGZ1bmN0aW9uKHgpIGdldHAoeFsxXSwgeFsyXSksIG51bWVyaWMoMSkpDQogIFIkdGsgPC0gdGt0OyBSJHRrX25zaWcgPC0gc3VtKHRrdCRwIDwgMC4wNSk7IFIkdGtfbiA8LSBucm93KHRrdCkNCiAgUiR0a19taXNtYV9zaWcgPC0gc3VtKHRrdCRtaXNtYSAmIHRrdCRwIDwgMC4wNSk7IFIkdGtfbWlzbWFfbiA8LSBzdW0odGt0JG1pc21hKQ0KfQ0KIyBQb3RlbmNpYSAvIGRpZmVyZW5jaWEgbcOtbmltYSBkZXRlY3RhYmxlIGNvbiBsYSBTRCBlbnRyZSDDoXJib2xlcyBvYnNlcnZhZGENClIkcG90IDwtIE5VTEwNCnNkX3QgPC0gTkENCmlmIChucm93KGFyYikgPj0gMyAmJiBSJG5fc29sICsgUiRuX3NvbSAtIDIgPj0gMSkgew0KICByZXNfdCA8LSBjKGFyYiRtZWRpYV9sblthcmIkZXhwb3NpY2lvbiA9PSAic29sIl0gLSBtZWFuKGFyYiRtZWRpYV9sblthcmIkZXhwb3NpY2lvbiA9PSAic29sIl0pLA0KICAgICAgICAgICAgIGFyYiRtZWRpYV9sblthcmIkZXhwb3NpY2lvbiA9PSAic29tYnJhIl0gLSBtZWFuKGFyYiRtZWRpYV9sblthcmIkZXhwb3NpY2lvbiA9PSAic29tYnJhIl0pKQ0KICBnbF90IDwtIFIkbl9zb2wgKyBSJG5fc29tIC0gMjsgc2RfdCA8LSBzcXJ0KHN1bShyZXNfdF4yKSAvIGdsX3QpDQogIHNkX2ljIDwtIHNkX3QgKiBzcXJ0KGdsX3QgLyBxY2hpc3EoYyguOTc1LCAuMDI1KSwgZ2xfdCkpDQogIG5zIDwtIDI6MjUNCiAgbWRlIDwtIHZhcHBseShucywgZnVuY3Rpb24obikgZXhwKHBvd2VyLnQudGVzdChuID0gbiwgcG93ZXIgPSAuOCwgc2QgPSBzZF90LCBzaWcubGV2ZWwgPSAuMDUpJGRlbHRhKSwgbnVtZXJpYygxKSkNCiAgcmVxX24gPC0gdmFwcGx5KGMoMS4yLCAxLjMsIDEuNSwgMiksIGZ1bmN0aW9uKHIpIGNlaWxpbmcocG93ZXIudC50ZXN0KGRlbHRhID0gbG9nKHIpLCBwb3dlciA9IC44LCBzZCA9IHNkX3QsIHNpZy5sZXZlbCA9IC4wNSkkbiksIG51bWVyaWMoMSkpDQogIFIkcG90IDwtIGxpc3Qoc2RfdCA9IHNkX3QsIHNkX2ljID0gc2RfaWMsIGdsID0gZ2xfdCwgbnMgPSBucywgbWRlID0gbWRlLCByZXEgPSBkYXRhLmZyYW1lKHJhem9uID0gYygxLjIsIDEuMywgMS41LCAyKSwgbiA9IHJlcV9uKSkNCn0NCiMgRm9ybWEgZGUgbGEgaG9qYSAocmVsYWNpw7NuIGRlIGFzcGVjdG8gZGVsIG1hcmNvKQ0KYXNwIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShzcGxpdChkYXRvc1shaXMubmEoZGF0b3MkYXNwZWN0bykgJiAhaXMubmEoZGF0b3MkZXhwb3NpY2lvbiksIF0sIGRhdG9zJGFyYm9sWyFpcy5uYShkYXRvcyRhc3BlY3RvKSAmICFpcy5uYShkYXRvcyRleHBvc2ljaW9uKV0pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbihkKSBkYXRhLmZyYW1lKGFyYm9sID0gZCRhcmJvbFsxXSwgZXhwb3NpY2lvbiA9IGFzLmNoYXJhY3RlcihkJGV4cG9zaWNpb25bMV0pLCBtZWRpYV9sbiA9IG1lYW4obG9nKGQkYXNwZWN0bykpLCBhc3AgPSBtZWFuKGQkYXNwZWN0bykpKSkNCmFzcCRleHBvc2ljaW9uIDwtIGZhY3Rvcihhc3AkZXhwb3NpY2lvbiwgbGV2ZWxzID0gYygic29sIiwgInNvbWJyYSIpKQ0KYkFzcCA8LSBiYXRlcmlhKGFzcCwgIm1lZGlhX2xuIik7IFIkYkFzcCA8LSBiQXNwOyBSJGFzcF9yYW5nbyA8LSByYW5nZShkYXRvcyRhc3BlY3RvLCBuYS5ybSA9IFRSVUUpDQpSJGFzcF9tZWRpYSA8LSBtZWFuKGRhdG9zJGFzcGVjdG8sIG5hLnJtID0gVFJVRSkNCmlmIChpc1RSVUUocGFyYW1zJGd1YXJkYXJfbGltcGlvcykpIHdyaXRlLmNzdihkYXRvc1ssIGMoImZpbGEiLCAiYXJjaGl2byIsICJhcmJvbCIsICJleHBvc2ljaW9uIiwgIm5faG9qYSIsICJsYWRvMSIsICJsYWRvMiIsICJtYXJjb19jbTIiLCAiYXJlYV9vcmlnIiwgImFyZWEiLCAiZXN0YWRvIiwgImFyZWFfZiIsICJvcmlnZW4iLCAibGF0IiwgImxvbiIpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0b3NfbGltcGlvc19hcmVhX2ZvbGlhci5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSwgbmEgPSAiIikNCmBgYA0KDQpgYGB7ciBjYWxjX2ZyYXNlcywgaW5jbHVkZT1GQUxTRX0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDYuIEZSQVNFUyBESU7DgU1JQ0FTIChzZSByZWNhbGN1bGFuIGN1YW5kbyBzZSBjb21wbGV0ZW4gbGFzIMOhcmVhcyBmYWx0YW50ZXMpDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KY2xhc2lmaWNhIDwtIGZ1bmN0aW9uKGIpIHsgICAgICAgICAgICAjIGI6IHNhbGlkYSBkZSBiYXRlcmlhKCkNCiAgaWYgKGlzLm5hKGIkcF93ZWxjaCkpIHJldHVybigibm8gZXZhbHVhYmxlIGNvbiB0YW4gcG9jb3Mgw6FyYm9sZXMiKQ0KICBpZiAoIWlzLm5hKGIkbGkpICYmIGIkbGkgPD0gMSAmJiBiJGxzID49IDEpIHJldHVybigibm8gY29uY2x1eWVudGUgKGVsIGludGVydmFsbyBpbmNsdXllIDEpIikNCiAgaWYgKGIkcmF6b24gPiAxKSAibWF5b3IgZW4gc29tYnJhIiBlbHNlICJtYXlvciBlbiBzb2wiDQp9DQpSJGRpcl9BIDwtIGlmIChpcy5uYShiQSRyYXpvbikpICJpbmRldGVybWluYWRhIiBlbHNlIGlmIChiQSRyYXpvbiA+IDEpICJtYXlvciBlbiBzb21icmEiIGVsc2UgIm1heW9yIGVuIHNvbCINClIkY29uY19BIDwtIGNsYXNpZmljYShiQSk7IFIkY29uY19CIDwtIGNsYXNpZmljYShiQik7IFIkY29uY19DIDwtIGNsYXNpZmljYShiQykNClIkaDFfYXBveWFkYSA8LSAhaXMubmEoYkEkcmF6b24pICYmIGJBJHJhem9uIDwgMSAmJiAhaXMubmEoYkEkbHMpICYmIGJBJGxzIDwgMSAgICAgIyBIMTogw6FyZWEgbWF5b3IgZW4gc29sIChyYXrDs24gc29tYnJhL3NvbCA8IDEpDQpSJGZyYXNlX2gxIDwtIHsNCiAgaWYgKGlzLm5hKGJBJHBfd2VsY2gpKSAiRWwgZGlzZcOxbyBhY3R1YWwgbm8gcGVybWl0ZSBldmFsdWFyIGxhcyBoaXDDs3Rlc2lzIGNvbiBsYSB1bmlkYWQgZGUgYW7DoWxpc2lzIGNvcnJlY3RhLiINCiAgZWxzZSBpZiAoUiRoMV9hcG95YWRhKSAiTGEgZGlyZWNjacOzbiB5IGVsIGludGVydmFsbyBkZSBjb25maWFuemEgc29uIGNvbXBhdGlibGVzIGNvbiBIMSAow6FyZWEgZm9saWFyIG1heW9yIGEgcGxlbm8gc29sKSB5IGNvbnRyYXJpb3MgYSBIMi4iDQogIGVsc2UgaWYgKGJBJHJhem9uIDwgMSkgIkxhIGRpcmVjY2nDs24gY29pbmNpZGUgY29uIEgxIChob2phcyBtYXlvcmVzIGEgcGxlbm8gc29sKSwgcGVybyBlbCBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGluY2x1eWUgbGEgYXVzZW5jaWEgZGUgZWZlY3RvOiBsYSBldmlkZW5jaWEgbm8gYmFzdGEgcGFyYSBhZmlybWFyIEgxIG5pIHBhcmEgZGVzY2FydGFyIEgyLiINCiAgZWxzZSBpZiAoIWlzLm5hKGJBJGxpKSAmJiBiQSRsaSA+IDEpICJFbCBlZmVjdG8gb2JzZXJ2YWRvIGVzIGVsIHF1ZSBwcm9wb25lIEgyOiBsYXMgaG9qYXMgZnVlcm9uIG1heW9yZXMgZW4gbG9zIMOhcmJvbGVzIGRlIHNvbWJyYSwgbG8gcXVlIHZhIGVuIGNvbnRyYSBkZSBIMS4iDQogIGVsc2UgIkxhIGRpcmVjY2nDs24gZXMgbGEgZGUgSDIgKGhvamFzIGFsZ28gbWF5b3JlcyBlbiBzb21icmEpLCBwZXJvIGVsIGludGVydmFsbyBkZSBjb25maWFuemEgaW5jbHV5ZSBsYSBhdXNlbmNpYSBkZSBlZmVjdG86IG5vIGhheSBldmlkZW5jaWEgc3VmaWNpZW50ZSBuaSBhIGZhdm9yIGRlIEgxIG5pIGEgZmF2b3IgZGUgSDIuIg0KfQ0KUiR2YWxfaDEgPC0gaWYgKGlzLm5hKGJBJHBfd2VsY2gpKSAibm8gZXZhbHVhYmxlIiBlbHNlIGlmICghaXMubmEoYkEkbGkpICYmIGJBJGxpIDw9IDEgJiYgYkEkbHMgPj0gMSkgIm5vIGNvbmNsdXllbnRlIChlbCBJQyBpbmNsdXllIDEpIiBlbHNlIGlmIChiQSRyYXpvbiA8IDEpICJjb21wYXRpYmxlIGNvbiBIMSIgZWxzZSAiY29udHJhcmlhIGEgSDEiDQpSJHZhbF9hbHQgPC0gaWYgKGlzLm5hKGJBJHBfd2VsY2gpKSAibm8gZXZhbHVhYmxlIiBlbHNlIGlmICghaXMubmEoYkEkbGkpICYmIGJBJGxpIDw9IDEgJiYgYkEkbHMgPj0gMSkgIm5vIGNvbmNsdXllbnRlIChlbCBJQyBpbmNsdXllIDEpIiBlbHNlIGlmIChiQSRyYXpvbiA+IDEpICJjb21wYXRpYmxlIiBlbHNlICJjb250cmFyaWEiDQpSJHBtaW5fdHh0IDwtIGlmIChpcy5uYShiQSRwX21pbikpICJuL2QiIGVsc2UgZnAoYkEkcF9taW4pDQpSJG5vX2FsY2FuemEgPC0gIWlzLm5hKGJBJHBfbWluKSAmJiBiQSRwX21pbiA+IDAuMDUNClIkcmVzcF90aXBvIDwtIGlmIChSJG5fZmFsdGEgPT0gMCkgImNvbXBsZXRhIiBlbHNlICJpbmNvbXBsZXRhIg0KYGBgDQoNCmBgYHtyIGNhbGNfdGV4dG9zLCBpbmNsdWRlPUZBTFNFfQ0Kbl9zb2xfdG90IDwtIHN1bShnZW8kZXhwb3NpY2lvbiA9PSAic29sIik7IG5fc29tX3RvdCA8LSBzdW0oZ2VvJGV4cG9zaWNpb24gPT0gInNvbWJyYSIpDQpSJG5fc29sX3RvdCA8LSBuX3NvbF90b3Q7IFIkbl9zb21fdG90IDwtIG5fc29tX3RvdA0KUiR0eHRfcGVuZCA8LSBpZiAoUiRuX2ZhbHRhID4gMCkgcGFzdGUwKCJEZSBsYXMgIiwgUiRuX2ZpbGFzLCAiIGhvamFzLCAiLCBSJG5fZmFsdGEsICIgKCIsIGZ4KFIkcGN0X2ZhbHRhLCAwKSwgIiAlKSB0aWVuZW4gZWwgw6FyZWEgcGVuZGllbnRlIiwNCiAgICBpZiAobGVuZ3RoKFIkYXJiX3Npbl9tZWRpZGEpKSBwYXN0ZTAoIiAoaW5jbHVpZG8gdG9kbyBlbCDDoXJib2wgIiwgcGFzdGUoUiRhcmJfc2luX21lZGlkYSwgY29sbGFwc2UgPSAiLCAiKSwgIikiKSBlbHNlICIiLA0KICAgICI7IHBvciBlbGxvIGVsIGFuw6FsaXNpcyBwcmltYXJpbyBzZSBjb21wbGVtZW50YSBjb24gdW5vIGJhc2FkbyBlbiBlbCBtYXJjbywgZGlzcG9uaWJsZSBwYXJhIHRvZGFzIGxhcyBob2phcy4iKSBlbHNlIHBhc3RlMCgiTGFzICIsIFIkbl9maWxhcywgIiBob2phcyB0aWVuZW4gw6FyZWEgbWVkaWRhLiIpDQpSJHR4dF9yZXMgPC0gaWYgKGlzLm5hKGJBJHBfd2VsY2gpKSBwYXN0ZTAoIkNvbiAiLCBSJG5fc29sLCAiIMOhcmJvbChlcykgZGUgc29sIHkgIiwgUiRuX3NvbSwgIiBkZSBzb21icmEgY29uIGRhdG9zLCBlbCBjb250cmFzdGUgaW5mZXJlbmNpYWwgbm8gZXMgZXN0aW1hYmxlLiIpIGVsc2UNCiAgcGFzdGUwKCJDb24gZWwgw6FyYm9sIGNvbW8gdW5pZGFkIGRlIGFuw6FsaXNpcyAoIiwgUiRuX3NvbCwgIiBkZSBzb2wgeSAiLCBSJG5fc29tLCAiIGRlIHNvbWJyYSksIGxhIHJhesOzbiBkZSDDoXJlYXMgc29tYnJhL3NvbCBmdWUgIiwgZngoYkEkcmF6b24sIDIpLA0KICAgICAgICAgIiAoSUMgOTUgJTogIiwgZngoYkEkbGksIDIpLCAi4oCTIiwgZngoYkEkbHMsIDIpLCAiOyAiLCBnc3ViKCJcXCoiLCAiIiwgZnBwKGJBJHBfd2VsY2gpKSwgIikuIikNClIkdHh0X2ljYyA8LSBpZiAoIWlzLm51bGwoUiRpY2MpKSBwYXN0ZTAoIkVsICIsIGZ4KDEwMCAqIFIkaWNjJGljYywgMCksICIgJSBkZSBsYSB2YXJpYWNpw7NuIGRlbCB0YW1hw7FvIGRlIGxhcyBob2phcyBzZSBkZWJpw7MgYSBkaWZlcmVuY2lhcyBlbnRyZSDDoXJib2xlcyAoQ0NJID0gIiwNCiAgICBmeChSJGljYyRpY2MsIDIpLCAiOyBJQyA5NSAlOiAiLCBmeChSJGljYyRsaSwgMiksICLigJMiLCBmeChSJGljYyRscywgMiksICIpLiIpIGVsc2UgIiINClIkdHh0X3Byb3h5IDwtIGlmIChSJHByb3h5X29rKSBwYXN0ZTAoIkVsIG1hcmNvIGV4cGxpY8OzIGVsICIsIGZ4KDEwMCAqIFIkcHhfcjIsIDApLCAiICUgZGUgbGEgdmFyaWFjacOzbiBkZWwgbG9nLcOhcmVhIGRlIGxhcyBob2phcyBtZWRpZGFzLCBsbyBxdWUgcGVybWl0acOzIHVuIGFuw6FsaXNpcyBkZSBzZW5zaWJpbGlkYWQgY29uIGxhcyAiLCBSJG5fZmlsYXMsICIgaG9qYXMuIikgZWxzZSAiIg0KUiR0eHRfYiA8LSBpZiAoIWlzLm5hKGJCJHJhem9uKSkgcGFzdGUwKCJyYXrDs24gIiwgZngoYkIkcmF6b24sIDIpLCAiLCBJQyA5NSAlICIsIGZ4KGJCJGxpLCAyKSwgIuKAkyIsIGZ4KGJCJGxzLCAyKSkgZWxzZSAibm8gZXN0aW1hYmxlIg0KUiR0eHRfYyA8LSBpZiAoIWlzLm5hKGJDJHJhem9uKSkgcGFzdGUwKCJyYXrDs24gIiwgZngoYkMkcmF6b24sIDIpLCAiLCBJQyA5NSAlICIsIGZ4KGJDJGxpLCAyKSwgIuKAkyIsIGZ4KGJDJGxzLCAyKSkgZWxzZSAibm8gZXN0aW1hYmxlIg0KUiR0eHRfYmMgPC0gaWYgKFIkbl9pbXAgPiAwKSBwYXN0ZTAoIkVsIGFuw6FsaXNpcyBjb24gZWwgbWFyY28gZGUgdG9kYXMgbGFzIGhvamFzIGRpbyAiLCBSJHR4dF9iLCAiLCB5IGVsIGNvbXBsZXRhZG8gZGUgbGFzIMOhcmVhcyBwZW5kaWVudGVzIGNvbiBlbCBtb2RlbG8gZGVsIG1hcmNvLCAiLCBSJHR4dF9jLCAiLiIpIGVsc2UNCiAgcGFzdGUwKCJVbiBhbsOhbGlzaXMgaW5kZXBlbmRpZW50ZSBiYXNhZG8gZW4gZWwgw6FyZWEgZGVsIG1hcmNvIGRlIGNhZGEgaG9qYSBkaW8gIiwgUiR0eHRfYiwgIi4iKQ0KUiR0eHRfcm9iIDwtIGlmIChSJG5faW1wID4gMCkgcGFzdGUwKCJDb21vICIsIFIkbl9mYWx0YSwgIiBkZSBsYXMgIiwgUiRuX2ZpbGFzLCAiIMOhcmVhcyBlc3TDoW4gcGVuZGllbnRlcywgY29tcGFyYW1vcyBlbCByZXN1bHRhZG8gcHJpbWFyaW8gKCoqQSoqKSBjb24gZG9zIGFuw6FsaXNpcyBhbHRlcm5hdGl2b3M6ICgqKkIqKikgZWwgw6FyZWEgZGVsIG1hcmNvIGRlIGxhcyAiLCBSJG5fZmlsYXMsDQogICIgaG9qYXMsIHkgKCoqQyoqKSBsYXMgw6FyZWFzIG1lZGlkYXMgbcOhcyBsYXMgcGVuZGllbnRlcyBjb21wbGV0YWRhcyBjb24gZWwgbW9kZWxvIG1hcmNvIOKGkiDDoXJlYSAoIiwgUiRuX2ltcCwgIiBob2phcykuIFBhcmEgKCoqQyoqKSBzZSBwcm9wYWfDsyBsYSBpbmNlcnRpZHVtYnJlIGRlbCBjb21wbGV0YWRvIGNvbiAiLCBwYXJhbXMkTV9pbXAsDQogICIgc2ltdWxhY2lvbmVzIHF1ZSBhw7FhZGVuIGVsIGVycm9yIHJlc2lkdWFsIGRlbCBtb2RlbG8gYSBjYWRhIHByZWRpY2Npw7NuLiIpIGVsc2UNCiAgcGFzdGUwKCJUb2RhcyBsYXMgaG9qYXMgdGllbmVuIMOhcmVhIG1lZGlkYSwgcG9yIGxvIHF1ZSBubyBoYXkgbmFkYSBxdWUgY29tcGxldGFyLiBFbCByZXN1bHRhZG8gcHJpbWFyaW8gKCoqQSoqKSBzZSBjb250cmFzdGEgY29uICgqKkIqKiksIGVsIGFuw6FsaXNpcyBkZWwgw6FyZWEgZGVsIG1hcmNvLCBxdWUgdXNhIHNvbG8gbG9zIGxhZG9zIG1lZGlkb3MgY29uIHJlZ2xhIHkgZXMgaW5kZXBlbmRpZW50ZSBkZWwgc2NyaXB0IGRlIGltYWdlbjsgeSBzZSByZXBpdGUgZWwgY29udHJhc3RlIG9taXRpZW5kbyB1biDDoXJib2wgYSBsYSB2ZXouIikNClIkdHh0X3BlbmQyIDwtIGlmIChSJG5fZmFsdGEgPiAwKSBwYXN0ZTAoIioqw4FyZWFzIHBlbmRpZW50ZXMuKiogSGF5ICIsIFIkbl9mYWx0YSwgIiDDoXJlYXMgZW4gYmxhbmNvICgiLCBmeChSJHBjdF9mYWx0YSwgMSksICIgJSksIHJlcGFydGlkYXMgZGUgZm9ybWEgbXV5IGRlc2lndWFsIGVudHJlIMOhcmJvbGVzICgiLCBmcmVmKCJjb21wbGV0aXR1ZCIpLCAiKTogIiwNCiAgICBwYXN0ZTAoY29tcCRhcmJvbCwgIiAoIiwgY29tcCRuX21lZGlkYSwgIi8iLCBjb21wJG5fdG90YWwsICIpIiwgY29sbGFwc2UgPSAiLCAiKSwgIi4gIiwNCiAgICBpZiAobGVuZ3RoKFIkYXJiX3Npbl9tZWRpZGEpKSBwYXN0ZTAoIkVsIMOhcmJvbCAiLCBwYXN0ZShSJGFyYl9zaW5fbWVkaWRhLCBjb2xsYXBzZSA9ICIsICIpLCAiIG5vIHRpZW5lIG5pbmd1bmEgbWVkaWRhIHkgcXVlZGEgZnVlcmEgZGVsIGFuw6FsaXNpcyBwcmltYXJpby4gIikgZWxzZSAiIiwNCiAgICBpZiAobGVuZ3RoKFIkYXJiX3BvY2FzKSkgcGFzdGUwKCJMb3Mgw6FyYm9sZXMgIiwgcGFzdGUoUiRhcmJfcG9jYXMsIGNvbGxhcHNlID0gIiwgIiksICIgdGllbmVuIG1lbm9zIGRlICIsIHBhcmFtcyRtaW5faG9qYXNfYXJib2wsICIgaG9qYXMgbWVkaWRhcyB5IHNlIGV4Y2x1eWVuIGRlbCBuaXZlbCBkZSDDoXJib2wuICIpIGVsc2UgIiIsDQogICAgIkVzdGUgaW5mb3JtZSBzZSByZWNhbGN1bGEgcG9yIGNvbXBsZXRvIGFsIHJlbGxlbmFyIGVzYXMgY2VsZGFzOiBuw7ptZXJvcywgdGFibGFzIHkgZ3LDoWZpY2FzIHNlIGFjdHVhbGl6YW4gYWwgY29tcGlsYXIgZGUgbnVldm8uIikgZWxzZSBwYXN0ZTAoIioqw4FyZWFzIGNvbXBsZXRhcy4qKiBUb2RhcyBsYXMgaG9qYXMgdGllbmVuIMOhcmVhIG1lZGlkYSAoIiwgZnJlZigiY29tcGxldGl0dWQiKSwgIikuIikNCg0KUiR0eHRfZmlsbCA8LSAiTm8gaGF5IHN1ZmljaWVudGVzIMOhcmVhcyBtZWRpZGFzIHBhcmEgdmFsaWRhciBlbCBtYXJjby4iDQppZiAoUiRwcm94eV9vaykgew0KICB0X2FyYiA8LSBpZiAoaXMubmEoUiRmaWxsX3BfYXJib2wpKSAiRWwgY29jaWVudGUgw6FyZWEvbWFyY28gbm8gcHVkbyBjb250cmFzdGFyc2UgZW50cmUgw6FyYm9sZXMiIGVsc2UgaWYgKFIkZmlsbF9wX2FyYm9sIDwgMC4wNSkNCiAgICBwYXN0ZTAoIkVsIGNvY2llbnRlIMOhcmVhL21hcmNvIGRpZmlyacOzIGVudHJlIMOhcmJvbGVzICgiLCBmcHAoUiRmaWxsX3BfYXJib2wpLCAiKSIpIGVsc2UgcGFzdGUwKCJFbCBjb2NpZW50ZSDDoXJlYS9tYXJjbyBubyBkaWZpcmnDsyBkZXRlY3RhYmxlbWVudGUgZW50cmUgw6FyYm9sZXMgKCIsIGZwcChSJGZpbGxfcF9hcmJvbCksICIpIikNCiAgdF9leHAgPC0gaWYgKGlzLm5hKFIkZmlsbF9wX2V4cG8pKSAiLiIgZWxzZSBpZiAoUiRmaWxsX3BfZXhwbyA8IDAuMDUpDQogICAgcGFzdGUwKCIgeSBzw60gZW50cmUgZXhwb3NpY2lvbmVzICgiLCBmcHAoUiRmaWxsX3BfZXhwbyksICIpOyBlbCBtYXJjbyBubyBlcywgcG9yIHRhbnRvLCB1biBpbmRpY2Fkb3IgbmV1dHJhbCByZXNwZWN0byBkZSBsYSBleHBvc2ljacOzbi4iKSBlbHNlIHBhc3RlMCgiIG5pIGVudHJlIGV4cG9zaWNpb25lcyAoIiwgZnBwKFIkZmlsbF9wX2V4cG8pLCAiKS4iKQ0KICBSJHR4dF9maWxsIDwtIHBhc3RlMCgiRW50cmUgbGFzICIsIFIkbl9tZWQsICIgaG9qYXMgY29uIGFtYmFzIG1lZGlkYXMsIGVsIMOhcmVhIGRlIGxhIGhvamEgZnVlIGVuIHByb21lZGlvIGVsICIsIGZ4KDEwMCAqIFIkZmlsbF9tZWFuLCAxKSwgIiAlIGRlbCDDoXJlYSBkZWwgbWFyY28gKHJhbmdvICIsIGZ4KDEwMCAqIFIkZmlsbF9yYW5nZVsxXSwgMCksICLigJMiLCBmeCgxMDAgKiBSJGZpbGxfcmFuZ2VbMl0sIDApLA0KICAgICIgJSksIHkgYW1iYXMgbWVkaWRhcyBzZSByZWxhY2lvbmFuIGRlIGZvcm1hIG11eSBlc3RyZWNoYSAoUsKyID0gIiwgZngoUiRweF9yMiwgMyksICI7ICIsIGZyZWYoInByb3h5IiksICIpLiBBbCBwcmVkZWNpciBlbCDDoXJlYSBkZSB1bmEgaG9qYSBjb24gc3UgbWFyY28sIGVsIGVycm9yIHTDrXBpY28gZXMgZGUg4omIICIsIGZ4KDEwMCAqIFIkcHhfbG9vX3Jtc2UsIDEpLCAiICUuICIsIHRfYXJiLCB0X2V4cCwNCiAgICAiIFBvciBlc28gZWwgbWFyY28gc2lydmUsIGNvbiBjYXV0ZWxhLCBwYXJhIHZhbGlkYXIgbGFzIMOhcmVhcyBtZWRpZGFzLCBkZXRlY3RhciBlcnJvcmVzIGRlIHVuaWRhZCB5IGVzdGltYXIgbGFzIMOhcmVhcyBwZW5kaWVudGVzLiIpDQp9DQpSJHR4dF9kZXNjIDwtIGlmIChucm93KGRlc2NfYWxsKSA+IDApIHBhc3RlMCgiTGFzIG1lZGlhcyBkZSDDoXJib2wgZnVlcm9uIGRlICIsIGZ4KFIkbWVkaWFfcmFuZ29bMV0sIDEpLCAiIGEgIiwgZngoUiRtZWRpYV9yYW5nb1syXSwgMSksICIgY23CsiAoIiwgUiRhcmJfbWluLCAiIHkgIiwgUiRhcmJfbWF4LA0KICAgICIsIHJlc3BlY3RpdmFtZW50ZSksIHkgZWwgQ1YgZGVudHJvIGRlIMOhcmJvbCBkZSAiLCBmeChSJGN2X3JhbmdvWzFdLCAxKSwgIiBhICIsIGZ4KFIkY3ZfcmFuZ29bMl0sIDEpLCAiICUgKCIsIHRyZWYoImRlc2MiKSwgIiwgIiwgZnJlZigicG9yYXJib2wiKSwNCiAgICAiKS4gTGFzIGRpZmVyZW5jaWFzIGVudHJlIMOhcmJvbGVzIHNvbiBjb21wYXJhYmxlcyBvIG1heW9yZXMgcXVlIGxhcyBxdWUgaGF5IGVudHJlIGhvamFzIGRlIHVuIG1pc21vIMOhcmJvbC4iKSBlbHNlICIiDQpgYGANCg0KYGBge3IgY2FsY19zaXRpb3MsIGluY2x1ZGU9RkFMU0V9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyA3LiBTSVRJT1MgKGNvb3JkZW5hZGFzIHBvciDDoXJib2wpIFkgRk9UT0dSQUbDjUFTICAoYXJib2wxLmpwZywgYXJib2wyLmpwZywgLi4uKQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmxhYl9leHBvIDwtIGMoc29sID0gIkEgcGxlbm8gc29sIiwgc29tYnJhID0gIkEgbGEgc29tYnJhIikNCmNvbF9leHBvIDwtIENPTDsgbml2ZWxlc19leHBvIDwtIGMoInNvbCIsICJzb21icmEiKQ0KIyAtLS0tIENhcnBldGFzIGRvbmRlIHNlIGJ1c2NhbiBsYXMgZm90b3MgKHNlIHBydWViYW4gdG9kYXMsIHNpbiBkZXBlbmRlciBkZSBkw7NuZGUgc2UgY29tcGlsZSkgLS0tLQ0KZGlyX3JtZCA8LSB0cnlDYXRjaChub3JtYWxpemVQYXRoKGtuaXRyOjpjdXJyZW50X2lucHV0KGRpciA9IFRSVUUpLCB3aW5zbGFzaCA9ICIvIiwgbXVzdFdvcmsgPSBGQUxTRSksIGVycm9yID0gZnVuY3Rpb24oZSkgTkFfY2hhcmFjdGVyXykNCmRpcl9ybWQgPC0gaWYgKGxlbmd0aChkaXJfcm1kKSAmJiAhaXMubmEoZGlyX3JtZCkgJiYgbnpjaGFyKGRpcl9ybWQpKSBkaXJuYW1lKGRpcl9ybWQpIGVsc2UgTkFfY2hhcmFjdGVyXw0KZGlyX2RhdCA8LSB0cnlDYXRjaChkaXJuYW1lKG5vcm1hbGl6ZVBhdGgocnV0YSwgd2luc2xhc2ggPSAiLyIsIG11c3RXb3JrID0gRkFMU0UpKSwgZXJyb3IgPSBmdW5jdGlvbihlKSBOQV9jaGFyYWN0ZXJfKQ0KZGlyc19mb3RvIDwtIGMocGFyYW1zJGNhcnBldGFfZm90b3MsIGZpbGUucGF0aChwYXJhbXMkY2FycGV0YV9mb3RvcywgImZvdG9zIiksIGdldHdkKCksIGZpbGUucGF0aChnZXR3ZCgpLCAiZm90b3MiKSwNCiAgICAgICAgICAgICAgIGRpcl9ybWQsIGlmICghaXMubmEoZGlyX3JtZCkpIGZpbGUucGF0aChkaXJfcm1kLCAiZm90b3MiKSwgZGlyX2RhdCwgaWYgKCFpcy5uYShkaXJfZGF0KSkgZmlsZS5wYXRoKGRpcl9kYXQsICJmb3RvcyIpKQ0KZGlyc19mb3RvIDwtIHVuaXF1ZShub3JtYWxpemVQYXRoKGRpcnNfZm90b1shaXMubmEoZGlyc19mb3RvKSAmIGRpci5leGlzdHMoZGlyc19mb3RvKV0sIHdpbnNsYXNoID0gIi8iKSkNCnF1aXRhX2FjZW50b3MgPC0gZnVuY3Rpb24oeCkgdG9sb3dlcihpY29udih4LCB0byA9ICJBU0NJSS8vVFJBTlNMSVQiKSkNCmJ1c2Nhcl9mb3RvIDwtIGZ1bmN0aW9uKG4pIHsNCiAgaWYgKGlzLm5hKG4pKSByZXR1cm4oTkFfY2hhcmFjdGVyXykNCiAgZm9yIChkIGluIGRpcnNfZm90bykgew0KICAgIGYgPC0gbGlzdC5maWxlcyhkLCBmdWxsLm5hbWVzID0gVFJVRSkNCiAgICBmIDwtIGZbIWRpci5leGlzdHMoZildDQogICAgaWYgKCFsZW5ndGgoZikpIG5leHQNCiAgICBubSA8LSBxdWl0YV9hY2VudG9zKGJhc2VuYW1lKGYpKQ0KICAgICMgYXJib2wxLmpwZywgQXJib2wxLkpQRywgYXJib2wgMS5qcGVnLCBhcmJvbDAxLnBuZywgYXJib2wxLmpwZy5qcGcgLi4uIChubyBjb25mdW5kZSBhcmJvbDEgY29uIGFyYm9sMTApDQogICAgb2sgPC0gZ3JlcGwocGFzdGUwKCJeYXJib2xbIF8tXSowKiIsIG4sICIoW14wLTldLiopP1xcLihqcGU/Z3xwbmd8d2VicHxqZmlmKSQiKSwgbm0pDQogICAgaWYgKGFueShvaykpIHJldHVybihmW29rXVsxXSkNCiAgfQ0KICBOQV9jaGFyYWN0ZXJfDQp9DQouaW1nX2NhY2hlIDwtIG5ldy5lbnYoKTsgLmZvdG9fZXJyIDwtIGNoYXJhY3RlcigwKQ0KTUFYX09SSUdJTkFMIDwtIDI1ICogMTAyNF4yICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG9wZSBwYXJhIGluY3J1c3RhciBlbCBhcmNoaXZvIG9yaWdpbmFsIHNpbiByZWR1Y2lyDQphbm90YV9lcnIgPC0gZnVuY3Rpb24ocGF0aCwgZSkgLmZvdG9fZXJyIDw8LSB1bmlxdWUoYyguZm90b19lcnIsIHBhc3RlMChiYXNlbmFtZShwYXRoKSwgIjogIiwgY29uZGl0aW9uTWVzc2FnZShlKSkpKQ0KZm90b191cmkgPC0gZnVuY3Rpb24ocGF0aCwgdykgeyAgICAgICAgICAgICAgICAgICAgICAjIHJlZHVjZSBsYSBmb3RvIGNvbiBtYWdpY2sgeSBsYSBpbmNydXN0YSBlbiBiYXNlNjQNCiAgaWYgKGlzLm5hKHBhdGgpKSByZXR1cm4oTkFfY2hhcmFjdGVyXykNCiAgaWYgKEhBU19NQUdJQ0spIHsNCiAgICBvdXQgPC0gdHJ5Q2F0Y2goew0KICAgICAgaWYgKGlzLm51bGwoLmltZ19jYWNoZVtbcGF0aF1dKSkgeyAgICAgICAgICAgICAgIyBzZSBsZWUgVU5BIHNvbGEgdmV6IHBvciBmb3RvDQogICAgICAgIGltMCA8LSBtYWdpY2s6OmltYWdlX3JlYWQocGF0aCkNCiAgICAgICAgaW0wIDwtIGltMFsxXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc29sbyBlbCBwcmltZXIgY3VhZHJvDQogICAgICAgIGltMCA8LSB0cnlDYXRjaChtYWdpY2s6OmltYWdlX29yaWVudChpbTApLCBlcnJvciA9IGZ1bmN0aW9uKGUpIGltMCkgICAjIHNpIGZhbGxhIGxhIG9yaWVudGFjacOzbiBFWElGLCBzZSBzaWd1ZSBzaW4gZWxsYQ0KICAgICAgICAuaW1nX2NhY2hlW1twYXRoXV0gPC0gbWFnaWNrOjppbWFnZV9yZXNpemUoaW0wLCAiMTAwMHgiKQ0KICAgICAgfQ0KICAgICAgaW0gPC0gbWFnaWNrOjppbWFnZV9yZXNpemUoLmltZ19jYWNoZVtbcGF0aF1dLCBwYXN0ZTAodywgIngiKSkNCiAgICAgIHRmIDwtIHRlbXBmaWxlKGZpbGVleHQgPSAiLmpwZyIpOyBvbi5leGl0KHVubGluayh0ZiksIGFkZCA9IFRSVUUpDQogICAgICBtYWdpY2s6OmltYWdlX3dyaXRlKGltLCB0ZiwgZm9ybWF0ID0gImpwZWciLCBxdWFsaXR5ID0gNzApDQogICAgICBrbml0cjo6aW1hZ2VfdXJpKHRmKQ0KICAgIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgeyBhbm90YV9lcnIocGF0aCwgZSk7IE5VTEwgfSkNCiAgICBpZiAoIWlzLm51bGwob3V0KSkgcmV0dXJuKG91dCkNCiAgfQ0KICAjIFJlc3BhbGRvOiBzZSBpbmNydXN0YSBlbCBhcmNoaXZvIG9yaWdpbmFsIChzaW4gcmVkdWNpcikgbWllbnRyYXMgbm8gc2VhIGdpZ2FudGVzY28NCiAgdHJ5Q2F0Y2goew0KICAgIGlmIChmaWxlLnNpemUocGF0aCkgPiBNQVhfT1JJR0lOQUwpIHN0b3AoImFyY2hpdm8gZGUgIiwgcm91bmQoZmlsZS5zaXplKHBhdGgpIC8gMTAyNF4yLCAxKSwgIiBNQiwgZGVtYXNpYWRvIGdyYW5kZSBwYXJhIGluY3J1c3RhcmxvIHNpbiByZWR1Y2lyIikNCiAgICBrbml0cjo6aW1hZ2VfdXJpKHBhdGgpDQogIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgeyBhbm90YV9lcnIocGF0aCwgZSk7IE5BX2NoYXJhY3Rlcl8gfSkNCn0NCnNpdGlvcyA8LSBtZXJnZShnZW9bLCBjKCJhcmJvbCIsICJleHBvc2ljaW9uIiwgImxhdCIsICJsb24iKV0sIGNvbXBbLCBjKCJhcmJvbCIsICJuX3RvdGFsIiwgIm5fbWVkaWRhIildLCBieSA9ICJhcmJvbCIpDQpzaXRpb3MgPC0gbWVyZ2Uoc2l0aW9zLCBkZXNjX2FsbFssIGMoImFyYm9sIiwgIm1lZGlhIildLCBieSA9ICJhcmJvbCIsIGFsbC54ID0gVFJVRSkNCnNpdGlvcyRleHBvc2ljaW9uIDwtIGFzLmNoYXJhY3RlcihzaXRpb3MkZXhwb3NpY2lvbikNCnNpdGlvcyRpZF9hcmJvbCA8LSBzaXRpb3MkYXJib2w7IHNpdGlvcyRob2phcyA8LSBzaXRpb3Mkbl90b3RhbA0Kc2l0aW9zJG51bSA8LSBhcy5pbnRlZ2VyKGdzdWIoIlxcRCIsICIiLCBzaXRpb3MkYXJib2wpKQ0Kc2l0aW9zIDwtIHNpdGlvc1tvcmRlcihzaXRpb3MkbnVtKSwgXQ0Kc2l0aW9zJGZvdG8gPC0gdmFwcGx5KHNpdGlvcyRudW0sIGJ1c2Nhcl9mb3RvLCBjaGFyYWN0ZXIoMSksIFVTRS5OQU1FUyA9IEZBTFNFKQ0Kc2l0aW9zJHVyaV9wb3AgPC0gdmFwcGx5KHNpdGlvcyRmb3RvLCBmb3RvX3VyaSwgY2hhcmFjdGVyKDEpLCB3ID0gMzIwLCBVU0UuTkFNRVMgPSBGQUxTRSkNCnNpdGlvcyR1cmlfZ2FsIDwtIHZhcHBseShzaXRpb3MkZm90bywgZm90b191cmksIGNoYXJhY3RlcigxKSwgdyA9IHBhcmFtcyRhbmNob19mb3RvLCBVU0UuTkFNRVMgPSBGQUxTRSkNClIkbl9mb3RvcyA8LSBzdW0oIWlzLm5hKHNpdGlvcyR1cmlfZ2FsKSk7IFIkc2luX2ZvdG8gPC0gc2l0aW9zJGFyYm9sW2lzLm5hKHNpdGlvcyR1cmlfZ2FsKV0NClIkZm90b19oYWxsYWRhX3Npbl91cmkgPC0gc2l0aW9zJGFyYm9sWyFpcy5uYShzaXRpb3MkZm90bykgJiBpcy5uYShzaXRpb3MkdXJpX2dhbCldDQpSJGRpYWdfZm90b3MgPC0gcGFzdGUwKCJDYXJwZXRhcyByZXZpc2FkYXM6ICIsIGlmIChsZW5ndGgoZGlyc19mb3RvKSkgcGFzdGUoZGlyc19mb3RvLCBjb2xsYXBzZSA9ICIgfCAiKSBlbHNlICJuaW5ndW5hIGV4aXN0ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICIuIEFyY2hpdm9zIGVuY29udHJhZG9zOiAiLCBpZiAoYW55KCFpcy5uYShzaXRpb3MkZm90bykpKSBwYXN0ZShiYXNlbmFtZShzaXRpb3MkZm90b1shaXMubmEoc2l0aW9zJGZvdG8pXSksIGNvbGxhcHNlID0gIiwgIikgZWxzZSAibmluZ3VubyIsDQogICAgICAgICAgICAgICAgICAgICAgICIuIG1hZ2ljayBpbnN0YWxhZG86ICIsIGlmIChIQVNfTUFHSUNLKSAic8OtIiBlbHNlICJubyIsICIuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlbmd0aCguZm90b19lcnIpKSBwYXN0ZTAoIiBFUlJPUkVTOiAiLCBwYXN0ZSguZm90b19lcnIsIGNvbGxhcHNlID0gIiB8fCAiKSkgZWxzZSAiIikNCnNpdGlvcyRwb3B1cCA8LSB2YXBwbHkoc2VxX2xlbihucm93KHNpdGlvcykpLCBmdW5jdGlvbihpKSB7DQogIHMgPC0gc2l0aW9zW2ksIF0NCiAgaW1nIDwtIGlmIChpcy5uYShzJHVyaV9wb3ApKSAiIiBlbHNlIHBhc3RlMCgiPGltZyBzcmM9JyIsIHMkdXJpX3BvcCwgIicgc3R5bGU9J3dpZHRoOjEwMCU7Ym9yZGVyLXJhZGl1czo2cHg7bWFyZ2luLWJvdHRvbTo2cHgnPjxicj4iKQ0KICBwYXN0ZTAoaW1nLCAiPGI+IiwgcyRpZF9hcmJvbCwgIjwvYj4gJm1pZGRvdDsgIiwgbGFiX2V4cG9bW3MkZXhwb3NpY2lvbl1dLCAiPGJyPkhvamFzIHJlZ2lzdHJhZGFzOiAiLCBzJGhvamFzLA0KICAgICAgICAgIjxicj5cdTAwYzFyZWEgbWVkaWE6ICIsIGlmIChpcy5uYShzJG1lZGlhKSkgInNpbiBcdTAwZTFyZWFzIG1lZGlkYXMiIGVsc2UgcGFzdGUwKGZ4KHMkbWVkaWEsIDEpLCAiIGNtXHUwMGIyIiksDQogICAgICAgICAiPGJyPjxzcGFuIHN0eWxlPSdjb2xvcjojNjY2Jz4iLCBmeChzJGxhdCwgNSksICI7ICIsIGZ4KHMkbG9uLCA1KSwgIjwvc3Bhbj4iKQ0KfSwgY2hhcmFjdGVyKDEpKQ0KYGBgDQoNCjo6OiBhYnN0cmFjdA0KKipSZXN1bWVuKioNCg0KKipDb250ZXh0byB5IG9iamV0aXZvLioqIExhcyBob2phcyBzb24gbG9zIHByaW5jaXBhbGVzIMOzcmdhbm9zIGNhcHRhZG9yZXMgZGUgbHV6IHkgc3UgdGFtYcOxbyBjb25kaWNpb25hIGxhIGx1eiBxdWUgZWwgw6FyYm9sIHB1ZWRlIGludGVyY2VwdGFyLiBFdmFsdWFtb3Mgc2kgZWwgw6FyZWEgZm9saWFyIGRlICpgciBSJGVzcGVjaWVgKiBkaWZpZXJlIGVudHJlIMOhcmJvbGVzIGEgcGxlbm8gc29sIHkgYSBsYSBzb21icmEgZW4gZWwgQm9zcXVlIFVyYmFubyBNdWx0aWNlbnRybyAoQ2FsaSwgVmFsbGUgZGVsIENhdWNhOyBgciBmeChSJGFsdGl0dWRbMV0sIDApYCBtIHMuIG4uIG0uKSwgY29udHJhc3RhbmRvIGRvcyBoaXDDs3Rlc2lzIG9wdWVzdGFzIHBsYW50ZWFkYXMgcG9yIGxvcyBkb3MgYXV0b3JlczogSDEsIGVsIMOhcmVhIGZvbGlhciBwcm9tZWRpbyBwb3Igw6FyYm9sIGVzIG1heW9yIGEgcGxlbm8gc29sOyBIMiwgZXMgbWF5b3IgZW4gbGEgc29tYnJhLg0KDQoqKkRpc2XDsW8uKiogU2UgcmVnaXN0cmFyb24gYHIgUiRuX2ZpbGFzYCBob2phcyBlbiBgciBSJG5fYXJiYCDDoXJib2xlcyAoYHIgUiRuX3NvbF90b3RgIGRlIHNvbCB5IGByIFIkbl9zb21fdG90YCBkZSBzb21icmEpOyBlbCDDoXJlYSBkZSBjYWRhIGhvamEgc2Ugb2J0dXZvIGRlIHN1IGZvdG9ncmFmw61hIGVzY2FsYWRhIGNvbiB1biBtYXJjbyByZWN0YW5ndWxhciBkZSBsYWRvcyBjb25vY2lkb3MuIENvbW8gbGEgZXhwb3NpY2nDs24gZXMgdW5hIHByb3BpZWRhZCBkZWwgw6FyYm9sIHkgbm8gZGUgbGEgaG9qYSwgbGEgdW5pZGFkIGRlIGFuw6FsaXNpcyBmdWUgZWwgw6FyYm9sLiBgciBSJHR4dF9wZW5kYA0KDQoqKlJlc3VsdGFkb3MuKiogYHIgUiR0eHRfcmVzYCBgciBSJHR4dF9pY2NgIGByIFIkdHh0X2JjYA0KDQoqKkNvbmNsdXNpw7NuLioqIGByIFIkZnJhc2VfaDFgIENvbiB0YW4gcG9jb3Mgw6FyYm9sZXMsIGVsIGRpc2XDsW8gdGllbmUgdW5hIHBvdGVuY2lhIGxpbWl0YWRhOiBsb3MgcmVzdWx0YWRvcyBzb24gZXN0aW1hY2lvbmVzIHByZWxpbWluYXJlcyB5IGdlbmVyYWRvcmFzIGRlIGhpcMOzdGVzaXMsIG5vIHVuYSBjb25maXJtYWNpw7NuLg0KOjo6DQoNCmBgYHtyIGtwaXMsIHJlc3VsdHM9J2FzaXMnLCBlY2hvPUZBTFNFfQ0Ka3BpIDwtIGZ1bmN0aW9uKHYsIGwsIHMgPSAiIikgcGFzdGUwKCc8ZGl2IGNsYXNzPSJrcGkiPjxkaXYgY2xhc3M9InYiPicsIHYsICc8L2Rpdj48ZGl2IGNsYXNzPSJsIj4nLCBsLCAnPC9kaXY+PGRpdiBjbGFzcz0icyI+JywgcywgJzwvZGl2PjwvZGl2PicpDQpjYXQoJ1xuYGBgez1odG1sfVxuPGRpdiBjbGFzcz0ia3BpcyI+XG4nLA0KICAgIGtwaShSJG5fYXJiLCAiw4FyYm9sZXMiLCBwYXN0ZTAoUiRuX3NvbF90b3QsICIgc29sIMK3ICIsIFIkbl9zb21fdG90LCAiIHNvbWJyYSIpKSwNCiAgICBrcGkoUiRuX2ZpbGFzLCAiSG9qYXMgcmVnaXN0cmFkYXMiLCBwYXN0ZTAoUiRuX21lZCwgIiBjb24gw6FyZWEgbWVkaWRhIikpLA0KICAgIGtwaShmeChiQSRyYXpvbiwgMiksICJSYXrDs24gc29tYnJhL3NvbCIsIGlmICghaXMubmEoYkEkbGkpKSBwYXN0ZTAoIklDIDk1ICU6ICIsIGZjaShiQSRsaSwgYkEkbHMpKSBlbHNlICJubyBlc3RpbWFibGUiKSwNCiAgICBrcGkoaWYgKCFpcy5udWxsKFIkaWNjKSkgcGFzdGUwKGZ4KDEwMCAqIFIkaWNjJGljYywgMCksICIgJSIpIGVsc2UgIm4vZCIsICJWYXJpYWNpw7NuIGVudHJlIMOhcmJvbGVzIiwgIkNDSSAodGFtYcOxbyBkZSBsYSBob2phKSIpLA0KICAgICc8L2Rpdj5cbmBgYFxuXG4nLCBzZXAgPSAiIikNCmBgYA0KDQojIEludHJvZHVjY2nDs24gey51bm51bWJlcmVkfQ0KDQoqQmF1aGluaWEgcGljdGEqLCBjb25vY2lkYSBjb23Dum5tZW50ZSBjb21vIHBhdGEgZGUgdmFjYSwgZXMgdW5hIGVzcGVjaWUgZGUgbGEgZmFtaWxpYSBGYWJhY2VhZSBjdWx0aXZhZGEgZW4gQ29sb21iaWEsIE3DqXhpY28sIFBhbmFtw6EsIFZlbmV6dWVsYSB5IEVjdWFkb3IuIFByZXNlbnRhIGhvamFzIHNpbXBsZXMsIGNvbiBsw7NidWxvcyBvdmFkb3MgeSBhY3VtaW5hZG9zIG8gYWxnbyBjYXVkYWRvcyBlbiBlbCDDoXBpY2UsIHkgZXMgc2VtaWNhZHVjaWZvbGlhLCBlcyBkZWNpciwgcGllcmRlIHBhcmNpYWxtZW50ZSBzdSBmb2xsYWplIGR1cmFudGUgbGEgw6lwb2NhIHNlY2EuIFNlIHV0aWxpemEgY29tbyBwbGFudGEgb3JuYW1lbnRhbCwgY29tbyBiYXJyZXJhIHJvbXBldmllbnRvcyB5IGVuIHByb2Nlc29zIGRlIHJlc3RhdXJhY2nDs24gZWNvbMOzZ2ljYSwgeSBzdSByYW5nbyBhbHRpdHVkaW5hbCB2YSBkZXNkZSAwIGhhc3RhIDIwMDAgbSBzLiBuLiBtLmByIGNpdGUoInVlaWEyMDE0IilgDQoNCkxhcyBob2phcyBzb24gbG9zIHByaW5jaXBhbGVzIMOzcmdhbm9zIGNhcHRhZG9yZXMgZGUgbHV6IHNvbGFyIHkgZWwgc2l0aW8gZG9uZGUgb2N1cnJlIGxhIG1heW9yIHBhcnRlIGRlIGxhIGZvdG9zw61udGVzaXMuIEVsIHRhbWHDsW8geSBsYSBmb3JtYSBkZSB1bmEgaG9qYSBkZXRlcm1pbmFuIGxhIGNhbnRpZGFkIGRlIGx1eiBxdWUgbGEgcGxhbnRhIHB1ZWRlIGludGVyY2VwdGFyLCBwb3IgbG8gcXVlIGVsIMOhcmVhIGZvbGlhciBlcyB1biByYXNnbyDDunRpbCBwYXJhIGV2YWx1YXIgY8OzbW8gcmVzcG9uZGUgdW4gw6FyYm9sIGEgc3UgYW1iaWVudGUgbHVtw61uaWNvLmByIGNpdGUoInZpb2xsZTIwMDciLCAicGVyZXoyMDEzIilgDQoNCkVuIGVzdGUgZXN0dWRpbyBzZSBidXNjw7MgcmVzcG9uZGVyIGPDs21vIGNhbWJpYSBlbCDDoXJlYSBmb2xpYXIgZGUgKkIuIHBpY3RhKiBzZWfDum4gbGEgZXhwb3NpY2nDs24gYSBsYSBsdXogKHNvbCBvIHNvbWJyYSkuIEVsIHRyYWJham8gc2UgcmVhbGl6w7MgZW4gZWwgQm9zcXVlIFVyYmFubyBNdWx0aWNlbnRybywgdWJpY2FkbyBlbiBlbCDDoXJlYSBmb3Jlc3RhbCBwcm90ZWN0b3JhIGRlbCByw61vIE1lbMOpbmRleiwgY29tdW5hIDIyLCBDYWxpLCBWYWxsZSBkZWwgQ2F1Y2EsIGEgYHIgZngoUiRhbHRpdHVkWzFdLCAwKWAgbSBzLiBuLiBtLiwgZG9uZGUgc2UgY29tcGFyw7MgZWwgw6FyZWEgZm9saWFyIGRlIMOhcmJvbGVzIGV4cHVlc3RvcyBhIHBsZW5vIHNvbCBjb24gbGEgZGUgw6FyYm9sZXMgZW4gc29tYnJhLg0KDQo6OjogY2FsbG91dA0KKipIaXDDs3Rlc2lzLioqIENhZGEgdW5vIGRlIGxvcyBkb3MgYXV0b3JlcyBwbGFudGXDsyB1bmEgaGlww7N0ZXNpcyBkaXN0aW50YSBzb2JyZSBjw7NtbyBjYW1iaWEgZWwgw6FyZWEgZm9saWFyIHByb21lZGlvIHBvciDDoXJib2wgY29uIGxhIGx1eiAoSDA6IG5vIGhheSBkaWZlcmVuY2lhLCByYXrDs24gZGUgw6FyZWFzIHNvbWJyYS9zb2wgPSAxKS4NCg0KLSAgICoqSDE6IG1heW9yIMOhcmVhIGEgcGxlbm8gc29sKiogKHJhesOzbiBzb21icmEvc29sIFw8IDEpLiBVbm8gZGUgbG9zIGF1dG9yZXMgcHJvcG9uZSBxdWUgZWwgw6FyZWEgZGUgbGEgaG9qYSBhdW1lbnRhIGNvbiB1bmEgbWF5b3IgZXhwb3NpY2nDs24gYWwgc29sOiBtw6FzIHJhZGlhY2nDs24gYXBvcnRhIG3DoXMgZW5lcmfDrWEgcGFyYSBsYSBmb3Rvc8OtbnRlc2lzIHkgcG9kcsOtYSBmYXZvcmVjZXIgdW5hIHN1cGVyZmljaWUgZm9saWFyIG1heW9yLCBlbiBsw61uZWEgY29uIGVsIHBhdHLDs24gZ2xvYmFsIGVuIHF1ZSBsYXMgaG9qYXMgZ3JhbmRlcyBwcmVkb21pbmFuIGVuIGFtYmllbnRlcyBjw6FsaWRvcywgaMO6bWVkb3MgeSBzb2xlYWRvcy5gciBjaXRlKCJ3cmlnaHQyMDE3IilgDQotICAgKipIMjogbWF5b3Igw6FyZWEgZW4gbGEgc29tYnJhKiogKHJhesOzbiBzb21icmEvc29sIFw+IDEpLiBFbCBvdHJvIGF1dG9yIHByb3BvbmUgbG8gY29udHJhcmlvOiBxdWUgZWwgw6FyZWEgZGUgbGEgaG9qYSBhdW1lbnRhIGVuIGxhIHNvbWJyYSwgcG9ycXVlIGNvbiBwb2NhIGx1eiBsYXMgcGxhbnRhcyBzdWVsZW4gZGVzcGxlZ2FyIHJhc2dvcyBxdWUgZmF2b3JlY2VuIGxhIGNhcHR1cmEgZGUgbHV6LCBjb21vIGzDoW1pbmFzIG3DoXMgZXh0ZW5zYXMuYHIgY2l0ZSgidmFsbGFkYXJlczIwMDgiLCAiZ2l2bmlzaDE5ODgiKWANCjo6Og0KDQpVbmEgaG9qYSBtw6FzIGdyYW5kZSBubyBzaWVtcHJlIHNpZ25pZmljYSBtYXlvciBwcm9kdWNjacOzbi4gQ29uIGV4Y2VzbyBkZSBjYWxvciBvIHBvY2EgZGlzcG9uaWJpbGlkYWQgZGUgYWd1YSBsYSBwbGFudGEgcHVlZGUgcmVkdWNpciBzdSBhY3RpdmlkYWQgZm90b3NpbnTDqXRpY2EsIHkgdW5hIGzDoW1pbmEgbWF5b3IgZW5ncm9zYSBsYSBjYXBhIGzDrW1pdGUgZGUgYWlyZSB5IGRpZmljdWx0YSBkaXNpcGFyIGNhbG9yLmByIGNpdGUoInBhcmtodXJzdDE5NzIiLCAibWljaGFsZXR6MjAxNSIpYCBQb3IgZXNvIGVsIHNlbnRpZG8gZGVsIGVmZWN0byBubyBlcyBldmlkZW50ZSBkZSBhbnRlbWFubyB5IGVzdGUgZXN0dWRpbyBwb25lIGEgcHJ1ZWJhIGFtYmFzIGhpcMOzdGVzaXMuIEFkZW3DoXMsIGVsIHZlcmRhZGVybyBhcHJvdmVjaGFtaWVudG8gZGUgbGEgbHV6IGRlcGVuZGUgZGUgY8OzbW8gc2Ugb3JnYW5pemEgdG9kbyBlbCBmb2xsYWplIHkgZGUgbGFzIGNvbmRpY2lvbmVzIGFtYmllbnRhbGVzIHF1ZSByb2RlYW4gYWwgw6FyYm9sLg0KDQoqKk9iamV0aXZvcy4qKg0KDQotICAgRXN0aW1hciBsYSByYXrDs24gZGUgw6FyZWFzIHNvbWJyYS9zb2wgY29uIGVsIMOhcmJvbCBjb21vIHVuaWRhZCBleHBlcmltZW50YWwgeSB2YWxvcmFyIGN1w6FsIGRlIGxhcyBkb3MgaGlww7N0ZXNpcyAoSDEgbyBIMikgcmVzcGFsZGEgbWVqb3IuDQotICAgUmVwYXJ0aXIgbGEgdmFyaWFjacOzbiBlbnRyZSDDoXJib2xlcyB5IGVudHJlIGhvamFzLg0KLSAgIENvbXByb2JhciBsYSByb2J1c3RleiBkZSBsYSBjb25jbHVzacOzbiBmcmVudGUgYSBsYSBwcnVlYmEgZW1wbGVhZGEsIGxhIGluZmx1ZW5jaWEgZGUgw6FyYm9sZXMgaW5kaXZpZHVhbGVzIHkgbG9zIHZhbG9yZXMgYXTDrXBpY29zLg0KLSAgIEN1YW50aWZpY2FyIHF1w6kgZGlmZXJlbmNpYSBwb2Ryw61hIGRldGVjdGFyIGVzdGUgZGlzZcOxby4NCg0KIyBEaXNlw7FvIG11ZXN0cmFsIHkgZGF0b3MNCg0KIyMgRGlzZcOxbyBqZXLDoXJxdWljbyB5IGZsdWpvIGRlIG1lZGljacOzbg0KDQpMYSBiYXNlIGNvbnRpZW5lIGByIFIkbl9maWxhc2AgaG9qYXMgZGUgYHIgUiRuX2FyYmAgw6FyYm9sZXMgZGUgKmByIFIkZXNwZWNpZWAqIChgciBSJG5fc29sX3RvdGAgZGUgc29sIHkgYHIgUiRuX3NvbV90b3RgIGRlIHNvbWJyYSksIGNvbiBgciBSJGhvamFzX3hfYXJib2xbMV1g4oCTYHIgUiRob2phc194X2FyYm9sWzJdYCBob2phcyBwb3Igw6FyYm9sLiBMYSBleHBvc2ljacOzbiBzZSBhc2lnbsOzIGFsIMOhcmJvbCB5IGxhcyBob2phcyBzb24gc3VibXVlc3RyYXMgKGByIGZyZWYoImRpc2VubyIpYCk7IHBvciBlc28gZWwgw6FyYm9sIGVzIGxhIHVuaWRhZCBkZSBhbsOhbGlzaXMuIExhIGByIHRyZWYoImNhciIpYCByZXN1bWUgbG9zIMOhcmJvbGVzIGRlIGNhZGEgZXhwb3NpY2nDs24uDQoNCmBgYHtyIGZpZ19kaXNlbm8sIGZpZy5oZWlnaHQ9My45LCBmaWcuY2FwPWZjYXAoImRpc2VubyIsICJEaXNlw7FvIGplcsOhcnF1aWNvIGRlbCBlc3R1ZGlvIHkgZmx1am8gZGUgbWVkaWNpw7NuIiwgcGFzdGUwKCJFbCBmYWN0b3IgZmlqbyAoZXhwb3NpY2nDs24pIHNlIGFzaWduYSBhIMOhcmJvbGVzLCBxdWUgc29uIGxhIHVuaWRhZCBleHBlcmltZW50YWw7IGxhcyBob2phcyBzb24gc3VibXVlc3RyYXMuIEPDrXJjdWxvczogw6FyYm9sZXMsIGNvbiBlbCBuw7ptZXJvIGRlIGhvamFzIGNvbiDDoXJlYSBtZWRpZGEgc29icmUgZWwgdG90YWwuIExhcyDDoXJlYXMgc2Ugb2J0aWVuZW4gZGUgbGEgZm90b2dyYWbDrWEgZGUgY2FkYSBob2phOiB1biBtYXJjbyByZWN0YW5ndWxhciBkaWJ1amFkbyBjb24gcmVnbGEgYWxyZWRlZG9yIGRlIHN1IGNvbnRvcm5vIGZpamEgbGEgZXNjYWxhIHBhcmEgY29udmVydGlyIHDDrXhlbGVzIGEgY23CsiBjb24gdW4gc2NyaXB0IGVuIFIuIFVuIGPDrXJjdWxvIHZhY8OtbyBpbmRpY2EgcXVlIGVsIMOhcmJvbCBhw7puIG5vIHRpZW5lIG5pbmd1bmEgw6FyZWEgbWVkaWRhLiIpKX0NCmNhamEgPC0gZnVuY3Rpb24oeCwgeSwgdywgaCwgbGFiLCBmaWxsID0gIndoaXRlIiwgY29sID0gImdyZXkyNSIsIGZhY2UgPSAicGxhaW4iLCBzaXplID0gMy4yKQ0KICBsaXN0KGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IHggLSB3LzIsIHhtYXggPSB4ICsgdy8yLCB5bWluID0geSAtIGgvMiwgeW1heCA9IHkgKyBoLzIsIGZpbGwgPSBmaWxsLCBjb2xvdXIgPSBjb2wsIGxpbmV3aWR0aCA9IC41KSwNCiAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSB4LCB5ID0geSwgbGFiZWwgPSBsYWIsIHNpemUgPSBzaXplLCBmb250ZmFjZSA9IGZhY2UsIGxpbmVoZWlnaHQgPSAuOTUpKQ0KZmxlY2hhIDwtIGZ1bmN0aW9uKHgsIHksIHhlLCB5ZSkgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0geCwgeGVuZCA9IHhlLCB5ID0geSwgeWVuZCA9IHllLCBjb2xvdXIgPSAiZ3JleTM1IiwgbGluZXdpZHRoID0gLjUsIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgyLjIsICJtbSIpLCB0eXBlID0gImNsb3NlZCIpKQ0KY2FwYSA8LSBsaXN0KCkNCmNzIDwtIGNvbXBbY29tcCRleHBvc2ljaW9uID09ICJzb2wiLCBdOyBjYiA8LSBjb21wW2NvbXAkZXhwb3NpY2lvbiA9PSAic29tYnJhIiwgXQ0KcG9zX2FyYm9sIDwtIGZ1bmN0aW9uKGspIGlmIChrID09IDApIG51bWVyaWMoMCkgZWxzZSBzZXEoNTAsIDUwICsgNi41ICogKGsgLSAxKSwgbGVuZ3RoLm91dCA9IGspDQphbHRfdHh0IDwtIGlmIChsZW5ndGgoUiRhbHRpdHVkKSkgcGFzdGUwKGZ4KFIkYWx0aXR1ZFsxXSwgMCksICIgbSBzLiBuLiBtLiIpIGVsc2UgIiINCmNhcGEgPC0gYyhjYXBhLCBjYWphKDExLCAzMCwgMjAsIDE3LCBwYXN0ZTAoIkJvc3F1ZSBVcmJhbm9cbk11bHRpY2VudHJvLCBDYWxpXG4iLCBhbHRfdHh0KSwgZmlsbCA9ICIjZjFmM2Y0IiwgZmFjZSA9ICJib2xkIikpDQpjYXBhIDwtIGMoY2FwYSwgY2FqYSgzMywgNDQsIDE3LCAxMCwgcGFzdGUwKCJBIHBsZW5vIHNvbFxuKCIsIG5yb3coY3MpLCAiIMOhcmJvbGVzKSIpLCBmaWxsID0gYWRqdXN0Y29sb3IoQ09MWyJzb2wiXSwgLjI1KSksDQogICAgICAgICAgICAgICAgIGNhamEoMzMsIDE2LCAxNywgMTAsIHBhc3RlMCgiQSBsYSBzb21icmFcbigiLCBucm93KGNiKSwgIiDDoXJib2xlcykiKSwgZmlsbCA9IGFkanVzdGNvbG9yKENPTFsic29tYnJhIl0sIC4yMikpKQ0KY2FwYSA8LSBjKGNhcGEsIGxpc3QoZmxlY2hhKDIxLCAzMywgMjQuNCwgNDEpLCBmbGVjaGEoMjEsIDI3LCAyNC40LCAxOSkpKQ0KZm9yIChleCBpbiBsaXN0KGxpc3QoZCA9IGNzLCB5ID0gNDQsIGMgPSBDT0xbInNvbCJdKSwgbGlzdChkID0gY2IsIHkgPSAxNiwgYyA9IENPTFsic29tYnJhIl0pKSkgew0KICBpZiAobnJvdyhleCRkKSA9PSAwKSBuZXh0DQogIHhzIDwtIHBvc19hcmJvbChucm93KGV4JGQpKQ0KICBjYXBhIDwtIGMoY2FwYSwgbGlzdChmbGVjaGEoNDEuOCwgZXgkeSwgbWluKHhzKSAtIDMuMywgZXgkeSksDQogICAgYW5ub3RhdGUoInBvaW50IiwgeCA9IHhzLCB5ID0gZXgkeSwgc2hhcGUgPSAyMSwgc2l6ZSA9IDExLCBmaWxsID0gaWZlbHNlKGV4JGQkbl9tZWRpZGEgPT0gMCwgIndoaXRlIiwgZXgkYyksIGNvbG91ciA9ICJncmV5MTUiLCBzdHJva2UgPSAuNyksDQogICAgYW5ub3RhdGUoInRleHQiLCB4ID0geHMsIHkgPSBleCR5LCBsYWJlbCA9IGV4JGQkYXJib2wsIHNpemUgPSAzLjEsIGZvbnRmYWNlID0gImJvbGQiKSwNCiAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSB4cywgeSA9IGV4JHkgLSA2LjQsIGxhYmVsID0gcGFzdGUwKGV4JGQkbl9tZWRpZGEsICIvIiwgZXgkZCRuX3RvdGFsKSwgc2l6ZSA9IDIuNywgY29sb3VyID0gImdyZXkzMCIpKSkNCn0NCmNhcGEgPC0gYyhjYXBhLCBjYWphKDg5LCAzMCwgMjAsIDIyLCAiSG9qYXMgcG9yIMOhcmJvbFxuKHVuaWRhZCBkZSBtdWVzdHJlbylcblxuY29udG9ybm8g4oaSIG1hcmNvIOKGkiBmb3RvXG7ihpIgw6FyZWEgKGNtwrIpIiwgZmlsbCA9ICIjZjFmM2Y0IikpDQpjYXBhIDwtIGMoY2FwYSwgbGlzdChmbGVjaGEoNzcuNSwgNDAsIDc4LjgsIDM0LjUpLCBmbGVjaGEoNzcuNSwgMjAsIDc4LjgsIDI1LjUpKSkNCmNhYiA8LSBkYXRhLmZyYW1lKHggPSBjKDExLCAzMywgNTksIDg5KSwgbCA9IGMoIlNJVElPIiwgIkZBQ1RPUiAoZmlqbykiLCAiVU5JREFEIEVYUEVSSU1FTlRBTDogZWwgw6FyYm9sIiwgIlNVQk1VRVNUUkEiKSkNCmdncGxvdCgpICsgY2FwYSArIGdlb21fdGV4dChkYXRhID0gY2FiLCBhZXMoeCwgNTcsIGxhYmVsID0gbCksIHNpemUgPSAzLCBmb250ZmFjZSA9ICJib2xkIiwgY29sb3VyID0gImdyZXkyMCIpICsNCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDEwMCksIHlsaW0gPSBjKDQsIDYwKSwgY2xpcCA9ICJvZmYiKSArIHRoZW1lX3ZvaWQoKQ0KYGBgDQoNCmBgYHtyIHRhYl9jYXIsIHJlc3VsdHM9J2FzaXMnfQ0KY2FyX2RmIDwtIG1lcmdlKGdlb1ssIGMoImFyYm9sIiwgImV4cG9zaWNpb24iLCAieF9tIiwgInlfbSIpXSwgY29tcFssIGMoImFyYm9sIiwgIm5fdG90YWwiLCAibl9tZWRpZGEiKV0sIGJ5ID0gImFyYm9sIikNCmNhcl9kZiA8LSBtZXJnZShjYXJfZGYsIGRlc2NfYWxsWywgYygiYXJib2wiLCAibWVkaWEiLCAiY3YiKV0sIGJ5ID0gImFyYm9sIiwgYWxsLnggPSBUUlVFKQ0KY2FyX2RmIDwtIG1lcmdlKGNhcl9kZiwgYWdncmVnYXRlKGNiaW5kKG1hcmNvX2NtMiwgYXNwZWN0bykgfiBhcmJvbCwgZGF0YSA9IGRhdG9zLCBGVU4gPSBtZWFuKSwgYnkgPSAiYXJib2wiLCBhbGwueCA9IFRSVUUpDQpjYXJfZGYkZGlzdCA8LSBzcXJ0KGNhcl9kZiR4X21eMiArIGNhcl9kZiR5X21eMikNCmNhcl9kZiRleHBvIDwtIGZhY3Rvcihhcy5jaGFyYWN0ZXIoY2FyX2RmJGV4cG9zaWNpb24pLCBsZXZlbHMgPSBjKCJzb2wiLCAic29tYnJhIiksIGxhYmVscyA9IGMoIkEgcGxlbm8gc29sIiwgIkEgbGEgc29tYnJhIikpDQpjYXQodGNhcCgiY2FyIiwgIkNhcmFjdGVyw61zdGljYXMgZGUgbG9zIMOhcmJvbGVzIHNlZ8O6biBzdSBleHBvc2ljacOzbiBsdW3DrW5pY2EiLA0KICAgICAgICAgIkNhZGEgZmlsYSByZXN1bWUgbG9zIMOhcmJvbGVzIGRlIGxhIGNvbHVtbmEgKDxpPk48L2k+ID0gbsO6bWVybyBkZSDDoXJib2xlcyk7IGRhdG9zIGNvbW8gbWVkaWEgKERFKSB5IG1lZGlhbmEgW23DrW4u4oCTbcOheC5dLiBERSwgZGVzdmlhY2nDs24gZXN0w6FuZGFyOyBDViwgY29lZmljaWVudGUgZGUgdmFyaWFjacOzbiBkZW50cm8gZGVsIMOhcmJvbDsgZWwgbWFyY28gZXMgZWwgcmVjdMOhbmd1bG8gZGlidWphZG8gYWxyZWRlZG9yIGRlIGNhZGEgaG9qYSAobGFkbyAxIMOXIGxhZG8gMik7IGxhIGRpc3RhbmNpYSBzZSBtaWRlIGFsIGNlbnRyb2lkZSBkZSBsb3Mgw6FyYm9sZXMuIExvcyDDoXJib2xlcyBzaW4gw6FyZWFzIG1lZGlkYXMgbm8gY29udHJpYnV5ZW4gYSBsYXMgZmlsYXMgZGUgw6FyZWEuIikpDQpva190MSA8LSBGQUxTRQ0KaWYgKEhBU19UMSkgew0KICByY19zdGF0cyA8LSBmdW5jdGlvbih4LCAuLi4pIHsNCiAgICB4IDwtIHhbaXMuZmluaXRlKHgpXTsgbiA8LSBsZW5ndGgoeCkNCiAgICBpZiAobiA9PSAwKSByZXR1cm4oYygiIiwgIm4vZCIgPSAiIikpDQogICAgYygiIiwgIk1lZGlhIChERSkiID0gcGFzdGUwKGZ4KG1lYW4oeCksIDEpLCAiICgiLCBpZiAobiA+IDEpIGZ4KHNkKHgpLCAxKSBlbHNlICJuL2QiLCAiKSIpLA0KICAgICAgIk1lZGlhbmEgW23DrW4u4oCTbcOheC5dIiA9IHBhc3RlMChmeChtZWRpYW4oeCksIDEpLCAiIFsiLCBmeChtaW4oeCksIDEpLCAi4oCTIiwgZngobWF4KHgpLCAxKSwgIl0iKSkNCiAgfQ0KICB0YWJsZTE6OmxhYmVsKGNhcl9kZiRuX3RvdGFsKSA8LSAiSG9qYXMgcmVnaXN0cmFkYXMgcG9yIMOhcmJvbCAobikiDQogIHRhYmxlMTo6bGFiZWwoY2FyX2RmJG5fbWVkaWRhKSA8LSAiSG9qYXMgY29uIMOhcmVhIG1lZGlkYSBwb3Igw6FyYm9sIChuKSINCiAgdGFibGUxOjpsYWJlbChjYXJfZGYkbWVkaWEpIDwtICLDgXJlYSBmb2xpYXIgbWVkaWEgZGVsIMOhcmJvbCAoY23CsikiDQogIHRhYmxlMTo6bGFiZWwoY2FyX2RmJGN2KSA8LSAiQ1YgZGVsIMOhcmVhIGRlbnRybyBkZWwgw6FyYm9sICglKSINCiAgdGFibGUxOjpsYWJlbChjYXJfZGYkbWFyY29fY20yKSA8LSAiw4FyZWEgZGVsIG1hcmNvIChjbcKyKSINCiAgdGFibGUxOjpsYWJlbChjYXJfZGYkYXNwZWN0bykgPC0gIlJlbGFjacOzbiBkZSBhc3BlY3RvIGRlbCBtYXJjbyAobGFkbyBtYXlvci9tZW5vcikiDQogIHRhYmxlMTo6bGFiZWwoY2FyX2RmJGRpc3QpIDwtICJEaXN0YW5jaWEgYWwgY2VudHJvaWRlIChtKSINCiAgdF9jYXIgPC0gdHJ5Q2F0Y2godGFibGUxOjp0YWJsZTEofiBuX3RvdGFsICsgbl9tZWRpZGEgKyBtZWRpYSArIGN2ICsgbWFyY29fY20yICsgYXNwZWN0byArIGRpc3QgfCBleHBvLCBkYXRhID0gY2FyX2RmLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyYWxsID0gIlRvdGFsIiwgcm93bGFiZWxoZWFkID0gIkNhcmFjdGVyw61zdGljYSIsIHJlbmRlci5jb250aW51b3VzID0gcmNfc3RhdHMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlci5taXNzaW5nID0gTlVMTCwgdG9wY2xhc3MgPSAiUnRhYmxlMS10aW1lcyIpLCBlcnJvciA9IGZ1bmN0aW9uKGUpIE5VTEwpDQogIGlmICghaXMubnVsbCh0X2NhcikpIHsgdDFfb3V0KHRfY2FyKTsgb2tfdDEgPC0gVFJVRSB9DQp9DQppZiAoIW9rX3QxKSB7DQogIHRjIDwtIGRhdGEuZnJhbWUow4FyYm9sID0gY2FyX2RmJGFyYm9sLCBFeHBvc2ljacOzbiA9IGFzLmNoYXJhY3RlcihjYXJfZGYkZXhwb3NpY2lvbiksIGBIb2phcyByZWdpc3RyYWRhc2AgPSBjYXJfZGYkbl90b3RhbCwgYEhvamFzIG1lZGlkYXNgID0gY2FyX2RmJG5fbWVkaWRhLA0KICAgICAgICAgICAgICAgICAgIGDDgXJlYSBtZWRpYSAoY23CsilgID0gZngoY2FyX2RmJG1lZGlhLCAxKSwgYENWICglKWAgPSBmeChjYXJfZGYkY3YsIDEpLCBgTWFyY28gKGNtwrIpYCA9IGZ4KGNhcl9kZiRtYXJjb19jbTIsIDEpLA0KICAgICAgICAgICAgICAgICAgIGBBc3BlY3RvYCA9IGZ4KGNhcl9kZiRhc3BlY3RvLCAyKSwgYERpc3RhbmNpYSBhbCBjZW50cm9pZGUgKG0pYCA9IGZ4KGNhcl9kZiRkaXN0LCAwKSwgY2hlY2submFtZXMgPSBGQUxTRSkNCiAgdGFibGEodGMsIGFsaWduID0gImxscnJycnJyciIpDQp9DQpgYGANCg0KIyMgQ2FsaWRhZCBkZSBsYSBiYXNlIGRlIGRhdG9zDQoNCjxkZXRhaWxzIGNsYXNzPSJkZXRhbGxlIj4NCg0KPHN1bW1hcnk+VmVyIGxhIGRlc2NyaXBjacOzbiBkZSBsYXMgdmFyaWFibGVzIGRlIGxhIGJhc2U8L3N1bW1hcnk+DQoNCmBgYHtyIHRhYl92YXJzLCByZXN1bHRzPSdhc2lzJ30NCnZhcnNfdGFiIDwtIGRhdGEuZnJhbWUoDQogIFZhcmlhYmxlID0gYygiw4FyYm9sIiwgIkV4cG9zaWNpw7NuIiwgIkxhZG8gMSB5IGxhZG8gMiIsICLDgXJlYSBkZWwgbWFyY28iLCAiw4FyZWEgZm9saWFyIiwgImxuKMOhcmVhKSIsICJDb2NpZW50ZSDDoXJlYS9tYXJjbyIsICJSZWxhY2nDs24gZGUgYXNwZWN0byIsICJMYXRpdHVkIHkgbG9uZ2l0dWQiLCAiQ0NJIiwgIlJhesOzbiBzb21icmEvc29sIiksDQogIGBDb2x1bW5hIG8gY8OhbGN1bG9gID0gYygiYXJib2wgKFQxLCBUMuKApikiLCAiZXhwb3NpY2lvbiIsICJsYWRvXzFfbW0sIGxhZG9fMl9tbSIsICJsYWRvIDEgw5cgbGFkbyAyIC8gMTAwIiwgImFyZWFfcmVhbF9jbTIiLCAibG9nKMOhcmVhIGZvbGlhcikiLCAiw6FyZWEgZm9saWFyIC8gw6FyZWEgZGVsIG1hcmNvIiwgImxhZG8gbWF5b3IgLyBsYWRvIG1lbm9yIiwgImxhdGl0dWQsIGxvbmdpdHVkIiwgIkFOT1ZBIGRlIHVuIGZhY3RvciBzb2JyZSBsbijDoXJlYSkiLCAiZXhwKM6yKSBkZWwgbW9kZWxvIG1peHRvIG8gcmF6w7NuIGRlIG1lZGlhcyBnZW9tw6l0cmljYXMiKSwNCiAgVW5pZGFkID0gYygi4oCUIiwgInNvbCAvIHNvbWJyYSIsICJtbSIsICJjbcKyIiwgImNtwrIiLCAibG4oY23CsikiLCAiMOKAkzEiLCAi4omlIDEiLCAiZ3JhZG9zIGRlY2ltYWxlcyIsICIw4oCTMSIsICJzaW4gdW5pZGFkIiksDQogIERlc2NyaXBjacOzbiA9IGMoIklkZW50aWZpY2Fkb3IgZGVsIMOhcmJvbDsgZXMgbGEgdW5pZGFkIGV4cGVyaW1lbnRhbC4iLCAiQ29uZGljacOzbiBsdW3DrW5pY2EgZGVsIMOhcmJvbCAoZmFjdG9yIGRlIGludGVyw6lzKS4iLCAiTGFkb3MgZGVsIHJlY3TDoW5ndWxvIGRpYnVqYWRvIGFscmVkZWRvciBkZSBjYWRhIGhvamEuIiwNCiAgICAgICAgICAgICAgICAgICJFc2NhbGEgZGUgbGEgZm90b2dyYWbDrWEgeSByZWZlcmVuY2lhIGRlbCB0YW1hw7FvIGRlIGxhIGhvamEuIiwgIsOBcmVhIGRlIGxhIGhvamEgb2J0ZW5pZGEgZGUgbGEgZm90b2dyYWbDrWEgZXNjYWxhZGEuIiwgIlZhcmlhYmxlIHJlc3B1ZXN0YSBkZSBsYSBpbmZlcmVuY2lhIChlbCB0YW1hw7FvIGVzIG11bHRpcGxpY2F0aXZvKS4iLA0KICAgICAgICAgICAgICAgICAgIkZyYWNjacOzbiBkZWwgbWFyY28gcXVlIG9jdXBhIGxhIGhvamEuIiwgIkluZGljYWRvciBidXJkbyBkZSBsYSBmb3JtYSBkZSBsYSBsw6FtaW5hLiIsICJQb3NpY2nDs24gZGVsIMOhcmJvbC4iLCAiRnJhY2Npw7NuIGRlIGxhIHZhcmlhbnphIHF1ZSBvY3VycmUgZW50cmUgw6FyYm9sZXMuIiwgIkNvY2llbnRlIGRlIMOhcmVhcyBkZSBzb21icmEgcmVzcGVjdG8gZGUgc29sOyAxID0gc2luIGVmZWN0by4iKSwNCiAgY2hlY2submFtZXMgPSBGQUxTRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KY2F0KHRjYXAoInZhcnMiLCAiVmFyaWFibGVzIGRlIGxhIGJhc2UgeSBzdSBzaWduaWZpY2FkbyIsICJMYXMgY29sdW1uYXMgZGVsIGFyY2hpdm8gZGUgZGF0b3Mgc2Ugbm9ybWFsaXphbiBhbCBsZWVybGFzIChtaW7DunNjdWxhcywgc2luIHRpbGRlcykuIikpDQp0YWJsYSh2YXJzX3RhYiwgYWxpZ24gPSAibGxsbCIpDQpgYGANCg0KPC9kZXRhaWxzPg0KDQpgYGB7ciB0YWJfcWMsIHJlc3VsdHM9J2FzaXMnfQ0KY2F0KHRjYXAoInFjIiwgIlJldmlzacOzbiBkZSBjYWxpZGFkIGRlIGxhIGJhc2UgeSBkZWNpc2lvbmVzIHRvbWFkYXMiLCAiQ2FkYSBwcm9ibGVtYSBzZSByZXN1ZWx2ZSBjb24gdW5hIHJlZ2xhIGV4cGzDrWNpdGEgeSByZXByb2R1Y2libGU7IGxhIGZpbGEgb3JpZ2luYWwgc2UgY29uc2VydmEgZW4gbGEgYmFzZSBkZSB0cmFiYWpvLiIpKQ0KdGFibGEocWNfdGFiLCBhbGlnbiA9ICJsbGwiKQ0KYGBgDQoNCmByIFIkdHh0X3BlbmQyYA0KDQpgYGB7ciBmaWdfY29tcGxldGl0dWQsIGZpZy5oZWlnaHQ9My41LCBmaWcuY2FwPWZjYXAoImNvbXBsZXRpdHVkIiwgIkNvbXBsZXRpdHVkIGRlIGxhIGJhc2UgcG9yIGhvamEgeSBwb3Igw6FyYm9sIiwgIioqYSoqLCBNb3NhaWNvIGhvamEgYSBob2phOyBsb3MgbsO6bWVyb3Mgc29uIGVsIMOhcmVhIChjbcKyKSB1c2FkYSBlbiBlbCBhbsOhbGlzaXMuICoqYioqLCBQb3JjZW50YWplIGRlIGhvamFzIGNvbiDDoXJlYSBtZWRpZGEgcG9yIMOhcmJvbC4iKX0NCmRkIDwtIGRhdG9zDQpkZCRlc3QgPC0gaWZlbHNlKGRkJGVzdGFkbyA9PSAib2siLCAiTWVkaWRhIiwgaWZlbHNlKGdyZXBsKCJjb3JyZWdpZGEiLCBkZCRlc3RhZG8pLCAiQ29ycmVnaWRhICh1bmlkYWQpIiwNCiAgICAgICAgICBpZmVsc2UoZGQkZXN0YWRvID09ICJzaW4gw6FyZWEgKHBlbmRpZW50ZSkiLCAiUGVuZGllbnRlIiwgIkV4Y2x1aWRhIikpKQ0KZGQkYXJib2xfZiA8LSBmYWN0b3IoZGQkYXJib2wsIGxldmVscyA9IHJldihjb21wJGFyYm9sKSkNCmV0cSA8LSBzZXROYW1lcyhwYXN0ZTAoY29tcCRhcmJvbCwgIiDCtyAiLCBjb21wJGV4cG9zaWNpb24pLCBjb21wJGFyYm9sKQ0KcGEgPC0gZ2dwbG90KGRkLCBhZXMoZmFjdG9yKG5faG9qYSwgbGV2ZWxzID0gc29ydCh1bmlxdWUobl9ob2phKSkpLCBhcmJvbF9mLCBmaWxsID0gZXN0KSkgKw0KICBnZW9tX3RpbGUoY29sb3VyID0gIndoaXRlIiwgbGluZXdpZHRoID0gLjgpICsgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGlmZWxzZSh1c2FyLCBzcHJpbnRmKCIlLjBmIiwgYXJlYSksICIiKSksIHNpemUgPSAyLjYsIGNvbG91ciA9ICJ3aGl0ZSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWVkaWRhIiA9ICIjMDA5RTczIiwgIkNvcnJlZ2lkYSAodW5pZGFkKSIgPSAiI0NDNzlBNyIsICJQZW5kaWVudGUiID0gImdyZXk4NSIsICJFeGNsdWlkYSIgPSAiI0Q1NUUwMCIpLCBuYW1lID0gIkVzdGFkbyBkZSBsYSBob2phIikgKw0KICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIGV0cVt4XSkgKyBsYWJzKHggPSAiSG9qYSAobi7CuiBkZW50cm8gZGVsIMOhcmJvbCkiLCB5ID0gIsOBcmJvbCDCtyBleHBvc2ljacOzbiIpICsNCiAgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAidG9wIikNCnBiIDwtIGdncGxvdChjb21wLCBhZXMoZmFjdG9yKGFyYm9sLCBsZXZlbHMgPSByZXYoY29tcCRhcmJvbCkpLCBwY3QsIGZpbGwgPSBleHBvc2ljaW9uKSkgKyBnZW9tX2NvbCh3aWR0aCA9IC42NSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKG5fbWVkaWRhLCAiLyIsIG5fdG90YWwpKSwgaGp1c3QgPSAtLjE1LCBzaXplID0gMykgKyBjb29yZF9mbGlwKHlsaW0gPSBjKDAsIDEyNSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gQ09MKSArIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDAsIDUwLCAxMDApKSArIGxhYnMoeCA9IE5VTEwsIHkgPSAiSG9qYXMgY29uIMOhcmVhIG1lZGlkYSAoJSkiKSArDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQ0KcGEgKyBwYiArIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMi4zLCAxKSkgKyBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJhIikNCmBgYA0KDQojIyBVYmljYWNpw7NuIGRlIGxvcyDDoXJib2xlczogbWFwYSBpbnRlcmFjdGl2bw0KDQpMb3Mgw6FyYm9sZXMgZXN0w6FuIHNlcGFyYWRvcyBlbnRyZSBgciBmeChSJGRpc3RfbWluLCAwKWAgeSBgciBmeChSJGRpc3RfbWF4LCAwKWAgbTsgZWwgbcOhcyBhbGVqYWRvIGRlbCBjZW50cm9pZGUgZXMgYHIgUiRsZWphbm9gIChgciBmeChSJGRpc3RfbGVqYW5vLCAwKWAgbSksIHVuIGRldGFsbGUgcmVsZXZhbnRlIHBvcnF1ZSBsYSBwb3NpY2nDs24gZXNwYWNpYWwgcHVlZGUgY29uZnVuZGlyc2UgY29uIGxhIGV4cG9zaWNpw7NuICh2w6lhc2UgKkZvcm1hIGRlIGxhIGhvamEgeSBjb250ZXh0byBlc3BhY2lhbCopLiBIYXogY2xpYyBlbiB1biBtYXJjYWRvciBwYXJhIHZlciBsYSBmb3RvZ3JhZsOtYSB5IGxvcyBkYXRvcyBkZWwgw6FyYm9sOyBlbCBjb250cm9sIGRlIGNhcGFzIHBlcm1pdGUgY2FtYmlhciBlbCBtYXBhIGJhc2UgeSBvY3VsdGFyIHVuYSBleHBvc2ljacOzbi4NCg0KYGBge3IgbWFwYV9pbnRlcmFjdGl2bywgZWNobz1UUlVFfQ0KcHJlc2VudGVzIDwtIGludGVyc2VjdChuaXZlbGVzX2V4cG8sIHVuaXF1ZShzaXRpb3MkZXhwb3NpY2lvbikpDQppZiAoSEFTX0xFQUZMRVQpIHsNCiAgbGlicmFyeShsZWFmbGV0KQ0KICBtYXBhIDwtIGxlYWZsZXQoaGVpZ2h0ID0gNDgwKSAlPiUNCiAgICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRFc3JpLldvcmxkSW1hZ2VyeSwgZ3JvdXAgPSAiU2F0w6lsaXRlIikgJT4lDQogICAgYWRkVGlsZXMoZ3JvdXAgPSAiQ2FsbGVzIikNCiAgZm9yIChlIGluIHByZXNlbnRlcykgew0KICAgIGQgPC0gc2l0aW9zW3NpdGlvcyRleHBvc2ljaW9uID09IGUsIF0NCiAgICBtYXBhIDwtIGFkZENpcmNsZU1hcmtlcnMobWFwYSwgZGF0YSA9IGQsIGxuZyA9IH5sb24sIGxhdCA9IH5sYXQsIHJhZGl1cyA9IDksIHdlaWdodCA9IDIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgZmlsbENvbG9yID0gY29sX2V4cG9bW2VdXSwgZmlsbE9wYWNpdHkgPSAwLjk1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IH5pZF9hcmJvbCwgcG9wdXAgPSB+cG9wdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcHVwT3B0aW9ucyA9IHBvcHVwT3B0aW9ucyhtYXhXaWR0aCA9IDI2MCksIGdyb3VwID0gbGFiX2V4cG9bW2VdXSkNCiAgfQ0KICBtYXBhICU+JQ0KICAgIGFkZExheWVyc0NvbnRyb2woYmFzZUdyb3VwcyA9IGMoIlNhdMOpbGl0ZSIsICJDYWxsZXMiKSwgb3ZlcmxheUdyb3VwcyA9IHVubmFtZShsYWJfZXhwb1twcmVzZW50ZXNdKSwNCiAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkpICU+JQ0KICAgIGFkZExlZ2VuZCgiYm90dG9tcmlnaHQiLCBjb2xvcnMgPSB1bm5hbWUoY29sX2V4cG9bcHJlc2VudGVzXSksIGxhYmVscyA9IHVubmFtZShsYWJfZXhwb1twcmVzZW50ZXNdKSwNCiAgICAgICAgICAgICAgdGl0bGUgPSAiRXhwb3NpY2nDs24iLCBvcGFjaXR5ID0gMSkgJT4lDQogICAgYWRkU2NhbGVCYXIoImJvdHRvbWxlZnQiKQ0KfSBlbHNlIHsNCiAgY2F0KCJFbCBwYXF1ZXRlICdsZWFmbGV0JyBubyBlc3TDoSBpbnN0YWxhZG86IHNlIG11ZXN0cmEgdW4gbWFwYSBzaW1wbGUuIiwNCiAgICAgICJQYXJhIGVsIG1hcGEgaW50ZXJhY3Rpdm8gZWplY3V0YSBpbnN0YWxsLnBhY2thZ2VzKCdsZWFmbGV0JykuXG4iKQ0KICBwbG90KHNpdGlvcyRsb24sIHNpdGlvcyRsYXQsIHBjaCA9IDIxLCBjZXggPSAzLCBiZyA9IGNvbF9leHBvW3NpdGlvcyRleHBvc2ljaW9uXSwNCiAgICAgICBhc3AgPSAxIC8gY29zKG1lYW4oc2l0aW9zJGxhdCkgKiBwaSAvIDE4MCksIHhsYWIgPSAiTG9uZ2l0dWQgKMKwKSIsIHlsYWIgPSAiTGF0aXR1ZCAowrApIiwNCiAgICAgICBtYWluID0gIlViaWNhY2nDs24gZGUgbG9zIMOhcmJvbGVzIikNCiAgdGV4dChzaXRpb3MkbG9uLCBzaXRpb3MkbGF0LCBzdWIoIi4qXyIsICIiLCBzaXRpb3MkaWRfYXJib2wpLCBjZXggPSAwLjgpDQogIGxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBsYWJfZXhwb1twcmVzZW50ZXNdLCBwdC5iZyA9IGNvbF9leHBvW3ByZXNlbnRlc10sIHBjaCA9IDIxLCBidHkgPSAibiIpDQp9DQpgYGANCg0KYHIgZmNhcF9odG1sKCJtYXBhX2ludCIsICJNYXBhIGludGVyYWN0aXZvIGRlIGxvcyDDoXJib2xlcyBtdWVzdHJlYWRvcyIsICJDYWRhIGPDrXJjdWxvIGVzIHVuIMOhcmJvbCAoY29sb3IgPSBleHBvc2ljacOzbiBsdW3DrW5pY2EpLiBBbCBwdWxzYXJsbyBzZSBtdWVzdHJhbiBzdSBmb3RvZ3JhZsOtYSwgZWwgbsO6bWVybyBkZSBob2phcyByZWdpc3RyYWRhcywgZWwgw6FyZWEgZm9saWFyIG1lZGlhIHkgc3VzIGNvb3JkZW5hZGFzIChncmFkb3MgZGVjaW1hbGVzKS4iKWANCg0KYGBge3IgZmlnX21hcGEsIGZpZy5oZWlnaHQ9NC4xLCBmaWcuY2FwPWZjYXAoIm1hcGEiLCAiUG9zaWNpw7NuIGRlIGxvcyDDoXJib2xlcyBlbiBlbCBib3NxdWUgdXJiYW5vIiwgIioqYSoqLCBQbGFubyBsb2NhbCAobWV0cm9zIHJlc3BlY3RvIGRlbCBjZW50cm9pZGUsIGEgcGFydGlyIGRlIGxhcyBjb29yZGVuYWRhcyByZWdpc3RyYWRhcykuIEVsIHRhbWHDsW8gZGVsIGPDrXJjdWxvIGVzIHByb3BvcmNpb25hbCBhbCDDoXJlYSBtZWRpYSBtZWRpZGE7IGxvcyBjw61yY3Vsb3MgdmFjw61vcyBzb24gw6FyYm9sZXMgc2luIMOhcmVhcyBtZWRpZGFzLiAqKmIqKiwgRGlzdGFuY2lhIGVudHJlIHBhcmVzIGRlIMOhcmJvbGVzIChtKS4iKX0NCmdtIDwtIG1lcmdlKGdlbywgZGVzY19hbGxbLCBjKCJhcmJvbCIsICJtZWRpYSIpXSwgYnkgPSAiYXJib2wiLCBhbGwueCA9IFRSVUUpDQpyeCA8LSByYW5nZShnbSR4X20pOyByeSA8LSByYW5nZShnbSR5X20pOyBwYWQgPC0gMC4xMiAqIG1heChkaWZmKHJ4KSwgZGlmZihyeSksIDYwKQ0KcGEgPC0gZ2dwbG90KGdtLCBhZXMoeF9tLCB5X20pKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGdtWyFpcy5uYShnbSRtZWRpYSksIF0sIGFlcyhmaWxsID0gZXhwb3NpY2lvbiwgc2l6ZSA9IG1lZGlhKSwgc2hhcGUgPSAyMSwgY29sb3VyID0gImdyZXkxNSIsIHN0cm9rZSA9IC42KSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGdtW2lzLm5hKGdtJG1lZGlhKSwgXSwgc2hhcGUgPSAyMSwgc2l6ZSA9IDUsIGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiZ3JleTE1Iiwgc3Ryb2tlID0gLjkpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGFyYm9sKSwgbnVkZ2VfeSA9IHBhZCAqIC41NSwgZm9udGZhY2UgPSAiYm9sZCIsIHNpemUgPSAzLjIpICsNCiAgYW5ub3RhdGUoInNlZ21lbnQiLCB4ID0gcnhbMV0gLSBwYWQgKiAuNSwgeGVuZCA9IHJ4WzFdIC0gcGFkICogLjUgKyA1MCwgeSA9IHJ5WzFdIC0gcGFkLCB5ZW5kID0gcnlbMV0gLSBwYWQsIGxpbmV3aWR0aCA9IDEpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gcnhbMV0gLSBwYWQgKiAuNSArIDI1LCB5ID0gcnlbMV0gLSBwYWQgKiAxLjUsIGxhYmVsID0gIjUwIG0iLCBzaXplID0gMykgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBDT0wsIG5hbWUgPSAiRXhwb3NpY2nDs24iKSArIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoNC41LCAxMCksIG5hbWUgPSAiw4FyZWEgbWVkaWEgKGNtwrIpIikgKw0KICBjb29yZF9lcXVhbCh4bGltID0gcnggKyBjKC1wYWQsIHBhZCksIHlsaW0gPSByeSArIGMoLXBhZCAqIDIsIHBhZCAqIDEuNCkpICsNCiAgbGFicyh4ID0gIkVzdGXigJNvZXN0ZSAobSkiLCB5ID0gIk5vcnRl4oCTc3VyIChtKSIpICsgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNSkpKSArDQogIHRoZW1lKGxlZ2VuZC5ib3ggPSAidmVydGljYWwiLCBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQ0KZG0gPC0gZXhwYW5kLmdyaWQoYSA9IGdlbyRhcmJvbCwgYiA9IGdlbyRhcmJvbCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KZG0kZCA8LSBoYXZlcnNpbmUoZ2VvJGxhdFttYXRjaChkbSRhLCBnZW8kYXJib2wpXSwgZ2VvJGxvblttYXRjaChkbSRhLCBnZW8kYXJib2wpXSwgZ2VvJGxhdFttYXRjaChkbSRiLCBnZW8kYXJib2wpXSwgZ2VvJGxvblttYXRjaChkbSRiLCBnZW8kYXJib2wpXSkNCmRtJGEgPC0gZmFjdG9yKGRtJGEsIGxldmVscyA9IGdlbyRhcmJvbCk7IGRtJGIgPC0gZmFjdG9yKGRtJGIsIGxldmVscyA9IHJldihnZW8kYXJib2wpKQ0KcGIgPC0gZ2dwbG90KGRtLCBhZXMoYSwgYiwgZmlsbCA9IGQpKSArIGdlb21fdGlsZShjb2xvdXIgPSAid2hpdGUiKSArIGdlb21fdGV4dChhZXMobGFiZWwgPSBpZmVsc2UoZCA9PSAwLCAiIiwgZngoZCwgMCkpKSwgc2l6ZSA9IDIuOSkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICIjZjdmYmZmIiwgaGlnaCA9ICIjNmJhZWQ2IiwgZ3VpZGUgPSAibm9uZSIpICsgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwpICsNCiAgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKQ0KcGEgKyBwYiArIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMS4zNSwgMSkpICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQpgYGANCg0KIyMgRm90b2dyYWbDrWFzIGRlIGxvcyDDoXJib2xlcw0KDQpGb3RvZ3JhZsOtYSBkZSByZWZlcmVuY2lhIGRlIGNhZGEgw6FyYm9sLCBxdWUgZG9jdW1lbnRhIHN1IGVzdGFkbywgc3UgZW50b3JubyB5IHN1IGdyYWRvIGRlIGV4cG9zaWNpw7NuIHNvbGFyLiBIYXogY2xpYyBlbiB1bmEgaW1hZ2VuIHBhcmEgYW1wbGlhcmxhIHkgdXNhIGxvcyBib3RvbmVzIHBhcmEgZmlsdHJhciBwb3IgZXhwb3NpY2nDs24uIGByIGlmIChsZW5ndGgoUiRzaW5fZm90bykpIHBhc3RlMCgiPGRpdiBjbGFzcz0nd2Fybic+PGI+Tm8gc2UgcHVkaWVyb24gY2FyZ2FyIGxhcyBmb3RvcyBkZTo8L2I+ICIsIHBhc3RlKFIkc2luX2ZvdG8sIGNvbGxhcHNlID0gIiwgIiksICIuICIsIGlmIChsZW5ndGgoUiRmb3RvX2hhbGxhZGFfc2luX3VyaSkpIHBhc3RlMCgiRWwgYXJjaGl2byBleGlzdGUgcGVybyBubyBzZSBwdWRvIGluY3J1c3RhciAoaW5zdGFsYSA8Y29kZT5tYWdpY2s8L2NvZGU+IGNvbiA8Y29kZT5pbnN0YWxsLnBhY2thZ2VzKCdtYWdpY2snKTwvY29kZT4gbyByZWR1Y2UgZWwgdGFtYcOxbyBkZSBsYSBmb3RvKS4gIikgZWxzZSAiTm8gc2UgZW5jb250csOzIGVsIGFyY2hpdm86IGd1w6FyZGFsbyBjb21vIDxjb2RlPmFyYm9sMS5qcGc8L2NvZGU+LCA8Y29kZT5hcmJvbDIuanBnPC9jb2RlPuKApiBlbiBsYSBjYXJwZXRhIGRlbCBpbmZvcm1lIG8gZW4gPGNvZGU+Zm90b3MvPC9jb2RlPi4gIiwgIjxicj48c21hbGw+IiwgUiRkaWFnX2ZvdG9zLCAiPC9zbWFsbD48L2Rpdj4iKSBlbHNlIHBhc3RlMCgiU2UgY2FyZ2Fyb24gIiwgUiRuX2ZvdG9zLCAiIGZvdG9ncmFmw61hcy4iKWANCg0KYGBge3IgZ2FsZXJpYV9mb3RvcywgcmVzdWx0cz0nYXNpcycsIGVjaG89VFJVRX0NCmZpZ19odG1sIDwtIHZhcHBseShzZXFfbGVuKG5yb3coc2l0aW9zKSksIGZ1bmN0aW9uKGkpIHsNCiAgcyA8LSBzaXRpb3NbaSwgXQ0KICBtYXJjbyA8LSBpZiAoaXMubmEocyR1cmlfZ2FsKSkgcGFzdGUwKCc8ZGl2IGNsYXNzPSJtYXJjbyB2YWNpbyI+PHNwYW4+Rm90byBubyBkaXNwb25pYmxlPGJyPjxjb2RlPmFyYm9sJywgcyRudW0sICcuanBnPC9jb2RlPjwvc3Bhbj48L2Rpdj4nKSBlbHNlDQogICAgcGFzdGUwKCc8ZGl2IGNsYXNzPSJtYXJjbyI+PGltZyBzcmM9IicsIHMkdXJpX2dhbCwgJyIgYWx0PSLDgXJib2wgJywgcyRpZF9hcmJvbCwgJyDCtyAnLCBsYWJfZXhwb1tbcyRleHBvc2ljaW9uXV0sICciIGxvYWRpbmc9ImxhenkiPjxzcGFuIGNsYXNzPSJiYWRnZSAnLCBzJGV4cG9zaWNpb24sICciPicsIHRvdXBwZXIocyRleHBvc2ljaW9uKSwgJzwvc3Bhbj48L2Rpdj4nKQ0KICBtZXRhIDwtIHBhc3RlMChzJGhvamFzLCAiIGhvamFzIMK3ICIsIGlmIChpcy5uYShzJG1lZGlhKSkgInNpbiDDoXJlYXMgbWVkaWRhcyIgZWxzZSBwYXN0ZTAoIsOhcmVhIG1lZGlhICIsIGZ4KHMkbWVkaWEsIDEpLCAiIGNtwrIiKSkNCiAgcGFzdGUwKCc8ZmlndXJlIGNsYXNzPSInLCBzJGV4cG9zaWNpb24sICciIGRhdGEtZXhwbz0iJywgcyRleHBvc2ljaW9uLCAnIj4nLCBtYXJjbywNCiAgICAgICAgICc8ZmlnY2FwdGlvbj48Yj7DgXJib2wgJywgcyRpZF9hcmJvbCwgJzwvYj4gwrcgJywgbGFiX2V4cG9bW3MkZXhwb3NpY2lvbl1dLCAnPGJyPjxzcGFuIGNsYXNzPSJtZXRhIj4nLCBtZXRhLCAnPC9zcGFuPjwvZmlnY2FwdGlvbj48L2ZpZ3VyZT4nKQ0KfSwgY2hhcmFjdGVyKDEpKQ0KanMgPC0gcGFzdGUwKCI8c2NyaXB0PihmdW5jdGlvbigpe3ZhciBsYj1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGInKSxpbT1sYi5xdWVyeVNlbGVjdG9yKCdpbWcnKSxjcD1sYi5xdWVyeVNlbGVjdG9yKCcubGJjYXAnKTsiLA0KICAiZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmdhbGVyaWEgLm1hcmNvIGltZycpLmZvckVhY2goZnVuY3Rpb24oZWwpe2VsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxmdW5jdGlvbigpe2ltLnNyYz1lbC5zcmM7Y3AudGV4dENvbnRlbnQ9ZWwuYWx0O2xiLmNsYXNzTGlzdC5hZGQoJ29uJyk7fSk7fSk7IiwNCiAgImxiLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxmdW5jdGlvbigpe2xiLmNsYXNzTGlzdC5yZW1vdmUoJ29uJyk7fSk7IiwNCiAgImRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLGZ1bmN0aW9uKGUpe2lmKGUua2V5PT09J0VzY2FwZScpe2xiLmNsYXNzTGlzdC5yZW1vdmUoJ29uJyk7fX0pOyIsDQogICJ2YXIgYnM9ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmdhbGVyaWEtZmlsdHJvcyBidXR0b24nKTticy5mb3JFYWNoKGZ1bmN0aW9uKGIpe2IuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLGZ1bmN0aW9uKCl7YnMuZm9yRWFjaChmdW5jdGlvbih4KXt4LmNsYXNzTGlzdC5yZW1vdmUoJ29uJyk7fSk7Yi5jbGFzc0xpc3QuYWRkKCdvbicpO3ZhciBmPWIuZ2V0QXR0cmlidXRlKCdkYXRhLWYnKTsiLA0KICAiZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmdhbGVyaWEgZmlndXJlJykuZm9yRWFjaChmdW5jdGlvbihmZyl7ZmcuY2xhc3NMaXN0LnRvZ2dsZSgnb2N1bHRvJyxmIT09J3RvZG9zJyYmZmcuZ2V0QXR0cmlidXRlKCdkYXRhLWV4cG8nKSE9PWYpO30pO30pO30pO30pKCk7PC9zY3JpcHQ+IikNCiMgU2UgZGV2dWVsdmUgY29tbyBvYmpldG8gJ2FzaXMnIChubyBjb24gY2F0KTogaW1wcmltaXIgdmFyaW9zIE1CIGRlIGJhc2U2NCBlbiB1bmEgc29sYSBsaW5lYSBoYWNlIHF1ZSBrbml0ciBzZSBjb25nZWxlDQprbml0cjo6YXNpc19vdXRwdXQocGFzdGUwKCdcbmBgYHs9aHRtbH1cbicsDQogICAgJzxkaXYgY2xhc3M9ImdhbGVyaWEtZmlsdHJvcyI+PGJ1dHRvbiBjbGFzcz0ib24iIGRhdGEtZj0idG9kb3MiPlRvZG9zPC9idXR0b24+PGJ1dHRvbiBkYXRhLWY9InNvbCI+QSBwbGVubyBzb2w8L2J1dHRvbj48YnV0dG9uIGRhdGEtZj0ic29tYnJhIj5BIGxhIHNvbWJyYTwvYnV0dG9uPjwvZGl2PlxuJywNCiAgICAnPGRpdiBjbGFzcz0iZ2FsZXJpYSI+XG4nLCBwYXN0ZShmaWdfaHRtbCwgY29sbGFwc2UgPSAiXG4iKSwgJ1xuPC9kaXY+XG4nLA0KICAgICc8ZGl2IGlkPSJsYiIgY2xhc3M9ImxiIj48aW1nIGFsdD0iIj48ZGl2IGNsYXNzPSJsYmNhcCI+PC9kaXY+PC9kaXY+XG4nLCBqcywgJ1xuYGBgXG5cbicpKQ0KYGBgDQoNCmByIGZjYXBfaHRtbCgiZm90b3MiLCAiRm90b2dyYWbDrWFzIGRlIHJlZmVyZW5jaWEgZGUgbG9zIMOhcmJvbGVzIG11ZXN0cmVhZG9zIiwgIk1hcmNvIHN1cGVyaW9yOiBleHBvc2ljacOzbiBsdW3DrW5pY2EgKG5hcmFuamEsIHBsZW5vIHNvbDsgYXp1bCwgc29tYnJhKS4gUGllOiBpZGVudGlmaWNhZG9yIGRlbCDDoXJib2wsIG7Dum1lcm8gZGUgaG9qYXMgcmVnaXN0cmFkYXMgeSDDoXJlYSBmb2xpYXIgbWVkaWEuIilgDQoNCiMgUmVzdWx0YWRvcw0KDQojIyBFbCBtYXJjbyByZWN0YW5ndWxhciBjb21vIGluZGljYWRvciBkZWwgdGFtYcOxbyBkZSBsYSBob2phDQoNCkNhZGEgaG9qYSBzZSB0cmF6w7MgZGVudHJvIGRlIHVuIG1hcmNvIHJlY3Rhbmd1bGFyIGN1eW9zIGxhZG9zIHNlIG1pZGllcm9uIGNvbiByZWdsYSwgZGUgbW9kbyBxdWUgZWwgKirDoXJlYSBkZWwgbWFyY28qKiAobGFkbyAxIMOXIGxhZG8gMikgZXhpc3RlIHBhcmEgbGFzIGByIFIkbl9maWxhc2AgaG9qYXMsIGluY2x1c28gY3VhbmRvIGVsIMOhcmVhIG1lZGlkYSBwb3IgaW1hZ2VuIGVzdMOhIHBlbmRpZW50ZS4gYHIgUiR0eHRfZmlsbGANCg0KYGBge3IgZmlnX3Byb3h5LCBmaWcuaGVpZ2h0PTQuMCwgZmlnLmNhcD1mY2FwKCJwcm94eSIsICJFbCDDoXJlYSBkZWwgbWFyY28gcHJlZGljZSBlbCDDoXJlYSBkZSBsYSBob2phIiwgIioqYSoqLCBSZWxhY2nDs24gZW50cmUgZWwgw6FyZWEgZGVsIG1hcmNvIHkgZWwgw6FyZWEgbWVkaWRhIChlc2NhbGEgbG9n4oCTbG9nKTsgbMOtbmVhIHPDs2xpZGEsIGFqdXN0ZSBwb3IgbcOtbmltb3MgY3VhZHJhZG9zOyBsw61uZWEgZGlzY29udGludWEsIHByb3BvcmNpb25hbGlkYWQgY29uIGVsIGNvY2llbnRlIG1lZGlvLiAqKmIqKiwgQ29jaWVudGUgw6FyZWEvbWFyY28gcG9yIMOhcmJvbCAocHVudG9zOiBob2phczsgYmFycmFzOiBtZWRpYSDCsSBERSkuIil9DQpzaHBfZiA8LSBzZXROYW1lcyhyZXAoYygyMSwgMjIsIDIzLCAyNCwgMjUpLCBsZW5ndGgub3V0ID0gbGVuZ3RoKGFyYm9sZXNfYWxsKSksIGFyYm9sZXNfYWxsKQ0KaWYgKFIkcHJveHlfb2spIHsNCiAgeHIgPC0gcmFuZ2UobGltJG1hcmNvX2NtMikNCiAgcGEgPC0gZ2dwbG90KGxpbSwgYWVzKG1hcmNvX2NtMiwgYXJlYSkpICsNCiAgICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IGxvZzEwKFIkZmlsbF9tZWFuKSwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiZ3JleTQ1IikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBUUlVFLCBjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gImdyZXk4MCIsIGxpbmV3aWR0aCA9IC42KSArDQogICAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGV4cG9zaWNpb24sIHNoYXBlID0gYXJib2wpLCBzaXplID0gMi42LCBjb2xvdXIgPSAiZ3JleTE1Iiwgc3Ryb2tlID0gLjMsIGFscGhhID0gLjkpICsNCiAgICBzY2FsZV94X2xvZzEwKGJyZWFrcyA9IGMoNTAsIDEwMCwgMTUwLCAyNTApKSArIHNjYWxlX3lfbG9nMTAoYnJlYWtzID0gYyg0MCwgODAsIDEyMCwgMjAwKSkgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IENPTCwgbmFtZSA9ICJFeHBvc2ljacOzbiIpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IHNocF9mLCBuYW1lID0gIsOBcmJvbCIpICsNCiAgICBsYWJzKHggPSAiw4FyZWEgZGVsIG1hcmNvIChjbcKyLCBlc2NhbGEgbG9nKSIsIHkgPSAiw4FyZWEgZGUgbGEgaG9qYSAoY23CsiwgZXNjYWxhIGxvZykiKSArDQogICAgYW5ub3RhdGUoInRleHQiLCB4ID0geHJbMV0sIHkgPSBtYXgobGltJGFyZWEpLCBoanVzdCA9IDAsIHZqdXN0ID0gMSwgc2l6ZSA9IDMuMywNCiAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiUsKyID0gIiwgZngoUiRweF9yMiwgMyksICJcbnBlbmRpZW50ZSA9ICIsIGZ4KFIkcHhfYiwgMikpKSArDQogICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaGFwZSA9IDIxKSksIHNoYXBlID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAxKSkNCiAgZnIgPC0gbGltOyBmciRhcmJvbF9mIDwtIGZhY3RvcihmciRhcmJvbCwgbGV2ZWxzID0gY29tcCRhcmJvbCkNCiAgcGIgPC0gZ2dwbG90KGZyLCBhZXMoYXJib2xfZiwgcmF6b25fbWFyY28pKSArDQogICAgZ2VvbV9qaXR0ZXIoYWVzKGZpbGwgPSBleHBvc2ljaW9uKSwgd2lkdGggPSAuMTIsIGhlaWdodCA9IDAsIHNoYXBlID0gMjEsIHNpemUgPSAyLjIsIGNvbG91ciA9ICJncmV5MTUiLCBzdHJva2UgPSAuMywgYWxwaGEgPSAuODUpICsNCiAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBmdW5jdGlvbih4KSBkYXRhLmZyYW1lKHkgPSBtZWFuKHgpLCB5bWluID0gbWVhbih4KSAtIHNkKHgpLCB5bWF4ID0gbWVhbih4KSArIHNkKHgpKSwgZ2VvbSA9ICJwb2ludHJhbmdlIiwgc2l6ZSA9IC4zNSwgY29sb3VyID0gImJsYWNrIikgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IFIkZmlsbF9tZWFuLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJncmV5NDUiKSArIHNjYWxlX3hfZGlzY3JldGUoZHJvcCA9IEZBTFNFKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gQ09MLCBndWlkZSA9ICJub25lIikgKyBsYWJzKHggPSBOVUxMLCB5ID0gIsOBcmVhIC8gw6FyZWEgZGVsIG1hcmNvIikNCiAgcGEgKyBwYiArIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMS4xNSwgMSkpICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQp9DQpgYGANCg0KIyMgVmFyaWFjacOzbiBlbnRyZSB5IGRlbnRybyBkZSDDoXJib2xlcw0KDQpgYGB7ciB0YWJfZGVzYywgcmVzdWx0cz0nYXNpcyd9DQp0ZCA8LSBtZXJnZShjb21wWywgYygiYXJib2wiLCAiZXhwb3NpY2lvbiIsICJuX21lZGlkYSIsICJuX3RvdGFsIildLCBkZXNjX2FsbFssIGMoImFyYm9sIiwgIm1lZGlhIiwgIm1lZGlhbmEiLCAiZGUiLCAiY3YiLCAibGkiLCAibHMiLCAibWluIiwgIm1heCIsICJnZW9tIildLCBieSA9ICJhcmJvbCIsIGFsbC54ID0gVFJVRSkNCnRkIDwtIHRkW29yZGVyKGFzLmludGVnZXIoZ3N1YigiXFxEIiwgIiIsIHRkJGFyYm9sKSkpLCBdDQp0ZF9vdXQgPC0gZGF0YS5mcmFtZSjDgXJib2wgPSB0ZCRhcmJvbCwgRXhwb3NpY2nDs24gPSB0ZCRleHBvc2ljaW9uLCBgbiAobWVkaWRhcy90b3RhbClgID0gcGFzdGUwKHRkJG5fbWVkaWRhLCAiLyIsIHRkJG5fdG90YWwpLA0KICAgICAgICAgICAgICAgICAgICAgTWVkaWEgPSBmeCh0ZCRtZWRpYSwgMSksIE1lZGlhbmEgPSBmeCh0ZCRtZWRpYW5hLCAxKSwgREUgPSBmeCh0ZCRkZSwgMSksIGBDViAoJSlgID0gZngodGQkY3YsIDEpLA0KICAgICAgICAgICAgICAgICAgICAgYElDIDk1ICUgZGUgbGEgbWVkaWFgID0gaWZlbHNlKGlzLm5hKHRkJGxpKSwgIm4vZCIsIHBhc3RlMChmeCh0ZCRsaSwgMSksICLigJMiLCBmeCh0ZCRscywgMSkpKSwNCiAgICAgICAgICAgICAgICAgICAgIGBNw61uLuKAk23DoXguYCA9IGlmZWxzZShpcy5uYSh0ZCRtaW4pLCAibi9kIiwgcGFzdGUwKGZ4KHRkJG1pbiwgMSksICLigJMiLCBmeCh0ZCRtYXgsIDEpKSksDQogICAgICAgICAgICAgICAgICAgICBgTWVkaWEgZ2VvbS5gID0gZngodGQkZ2VvbSwgMSksIGNoZWNrLm5hbWVzID0gRkFMU0UsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCmNhdCh0Y2FwKCJkZXNjIiwgIkVzdGFkw61zdGljb3MgZGVzY3JpcHRpdm9zIGRlbCDDoXJlYSBmb2xpYXIgKGNtwrIpIHBvciDDoXJib2wiLA0KICAgICAgICAgIkNhZGEgY29sdW1uYSBlcyB1biDDoXJib2wgKGV4cG9zaWNpw7NuIHRyYXMgZWwgcHVudG8pOyBkYXRvcyBkZSBsYXMgaG9qYXMgY29uIMOhcmVhIG1lZGlkYS4gREUsIGRlc3ZpYWNpw7NuIGVzdMOhbmRhcjsgQ1YsIGNvZWZpY2llbnRlIGRlIHZhcmlhY2nDs24gKERFL21lZGlhKTsgSUMsIGludGVydmFsbyBkZSBjb25maWFuemEgPGk+dDwvaT4gZGUgU3R1ZGVudCBkZSBsYSBtZWRpYTsgbi9kLCBubyBkaXNwb25pYmxlIChzaW4gw6FyZWFzIG1lZGlkYXMgbyB1bmEgc29sYSBob2phKS4iKSkNCm9rX3QxIDwtIEZBTFNFDQppZiAoSEFTX1QxKSB7DQogIHJjX2FyYm9sIDwtIGZ1bmN0aW9uKHgsIC4uLikgew0KICAgIHggPC0geFtpcy5maW5pdGUoeCldOyBuIDwtIGxlbmd0aCh4KQ0KICAgIGlmIChuID09IDApIHJldHVybihjKCIiLCAibiIgPSAiMCIsICJNZWRpYSAoREUpIiA9ICJuL2QiLCAiTWVkaWFuYSBbbcOtbi7igJNtw6F4Ll0iID0gIm4vZCIsICJDViAoJSkiID0gIm4vZCIsICJNZWRpYSBnZW9tw6l0cmljYSIgPSAibi9kIiwgIklDIDk1ICUgZGUgbGEgbWVkaWEiID0gIm4vZCIpKQ0KICAgIG0gPC0gbWVhbih4KTsgcyA8LSBpZiAobiA+IDEpIHNkKHgpIGVsc2UgTkENCiAgICBpYyA8LSBpZiAobiA+IDEpIG0gKyBjKC0xLCAxKSAqIHF0KC45NzUsIG4gLSAxKSAqIHMgLyBzcXJ0KG4pIGVsc2UgYyhOQSwgTkEpDQogICAgYygiIiwgIm4iID0gYXMuY2hhcmFjdGVyKG4pLCAiTWVkaWEgKERFKSIgPSBwYXN0ZTAoZngobSwgMSksICIgKCIsIGZ4KHMsIDEpLCAiKSIpLA0KICAgICAgIk1lZGlhbmEgW23DrW4u4oCTbcOheC5dIiA9IHBhc3RlMChmeChtZWRpYW4oeCksIDEpLCAiIFsiLCBmeChtaW4oeCksIDEpLCAi4oCTIiwgZngobWF4KHgpLCAxKSwgIl0iKSwNCiAgICAgICJDViAoJSkiID0gZngoaWYgKG4gPiAxKSAxMDAgKiBzIC8gbSBlbHNlIE5BLCAxKSwgIk1lZGlhIGdlb23DqXRyaWNhIiA9IGZ4KGV4cChtZWFuKGxvZyh4KSkpLCAxKSwNCiAgICAgICJJQyA5NSAlIGRlIGxhIG1lZGlhIiA9IGlmIChuID4gMSkgcGFzdGUwKGZ4KGljWzFdLCAxKSwgIuKAkyIsIGZ4KGljWzJdLCAxKSkgZWxzZSAibi9kIikNCiAgfQ0KICBsZCA8LSBsaW1bLCBjKCJhcmVhIiwgImFyYm9sIildDQogIGxkJGFyYm9sX2YgPC0gZmFjdG9yKHBhc3RlMChsZCRhcmJvbCwgIiDCtyAiLCBhcy5jaGFyYWN0ZXIobGltJGV4cG9zaWNpb24pKSwgbGV2ZWxzID0gcGFzdGUwKGNvbXAkYXJib2wsICIgwrcgIiwgY29tcCRleHBvc2ljaW9uKSkNCiAgdGFibGUxOjpsYWJlbChsZCRhcmVhKSA8LSAiw4FyZWEgZm9saWFyIGRlIGxhIGhvamEgKGNtwrIpIg0KICB0X2Rlc2MgPC0gdHJ5Q2F0Y2godGFibGUxOjp0YWJsZTEofiBhcmVhIHwgYXJib2xfZiwgZGF0YSA9IGxkLCBvdmVyYWxsID0gRkFMU0UsIGRyb3BsZXZlbHMgPSBGQUxTRSwgcm93bGFiZWxoZWFkID0gIlZhcmlhYmxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlci5jb250aW51b3VzID0gcmNfYXJib2wsIHJlbmRlci5taXNzaW5nID0gTlVMTCwgdG9wY2xhc3MgPSAiUnRhYmxlMS10aW1lcyIpLCBlcnJvciA9IGZ1bmN0aW9uKGUpIE5VTEwpDQogIGlmICghaXMubnVsbCh0X2Rlc2MpKSB7IHQxX291dCh0X2Rlc2MpOyBva190MSA8LSBUUlVFIH0NCn0NCmlmICghb2tfdDEpIHRhYmxhKHRkX291dCwgYWxpZ24gPSAibGxycnJycnJyciIpDQpgYGANCg0KYHIgUiR0eHRfZGVzY2ANCg0KYGBge3IgZmlnX3BvcmFyYm9sLCBmaWcuaGVpZ2h0PTUuNiwgZmlnLmNhcD1mY2FwKCJwb3JhcmJvbCIsICJEaXN0cmlidWNpw7NuIGRlbCDDoXJlYSBmb2xpYXIgcG9yIMOhcmJvbCB5IHJlbGFjacOzbiBtZWRpYeKAk2Rpc3BlcnNpw7NuIiwgIioqYSoqLCBVbmEgY2FqYSBwb3Igw6FyYm9sIChtZWRpYW5hLCByYW5nbyBpbnRlcmN1YXJ0w61saWNvIHkgYmlnb3RlcyBkZSAxLDUgw5cgUklDKTsgcHVudG9zLCBob2phczsgcm9tYm9zIGJsYW5jb3MsIG1lZGlhcy4gKipiLCBjKiosIERlc3ZpYWNpw7NuIGVzdMOhbmRhciBmcmVudGUgYSBsYSBtZWRpYSBkZSBjYWRhIMOhcmJvbCBlbiBsYSBlc2NhbGEgb3JpZ2luYWwgKCoqYioqKSB5IGVuIGxvZ2FyaXRtb3MgKCoqYyoqKTsgbGEgdHJhbnNmb3JtYWNpw7NuIGxvZ2Fyw610bWljYSBlc3RhYmlsaXphIGxhIHZhcmlhbnphIHNpIGRlc2FwYXJlY2UgbGEgZGVwZW5kZW5jaWEuIil9DQpsaW0kYXJib2xfZjIgPC0gZmFjdG9yKGxpbSRhcmJvbCwgbGV2ZWxzID0gY29tcCRhcmJvbCkNCnZhY2lvcyA8LSB3aGljaChjb21wJG5fbWVkaWRhID09IDApDQpldHEyIDwtIHNldE5hbWVzKGNvbXAkZXhwb3NpY2lvbiwgY29tcCRhcmJvbCkNCnBhIDwtIGdncGxvdChsaW0sIGFlcyhhcmJvbF9mMiwgYXJlYSwgZmlsbCA9IGV4cG9zaWNpb24pKSArDQogIGdlb21fYm94cGxvdCh3aWR0aCA9IC41NSwgb3V0bGllci5zaGFwZSA9IE5BLCBhbHBoYSA9IC41LCBjb2xvdXIgPSAiZ3JleTI1IiwgbGluZXdpZHRoID0gLjQpICsNCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG91ciA9IGV4cG9zaWNpb24pLCB3aWR0aCA9IC4xMywgaGVpZ2h0ID0gMCwgc2l6ZSA9IDEuNywgYWxwaGEgPSAuODUpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaGFwZSA9IDIzLCBzaXplID0gMywgZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJncmV5MTUiKSArDQogIHNjYWxlX3hfZGlzY3JldGUoZHJvcCA9IEZBTFNFLCBsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIlxuIiwgZXRxMlt4XSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gQ09MLCBuYW1lID0gIkV4cG9zaWNpw7NuIikgKyBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IENPTCwgZ3VpZGUgPSAibm9uZSIpICsgbGFicyh4ID0gTlVMTCwgeSA9ICLDgXJlYSBmb2xpYXIgKGNtwrIpIikNCmlmIChsZW5ndGgodmFjaW9zKSkgcGEgPC0gcGEgKyBhbm5vdGF0ZSgidGV4dCIsIHggPSB2YWNpb3MsIHkgPSBtZWFuKHJhbmdlKGxpbSRhcmVhKSksIGxhYmVsID0gInNpbiDDoXJlYXNcbm1lZGlkYXMiLCBzaXplID0gMywgY29sb3VyID0gImdyZXk0MCIpDQpwYiA8LSBnZ3Bsb3QoZGVzY19hbGxbIWlzLm5hKGRlc2NfYWxsJGRlKSwgXSwgYWVzKG1lZGlhLCBkZSkpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9IHkgfiB4LCBzZSA9IEZBTFNFLCBjb2xvdXIgPSAiZ3JleTQwIiwgbGluZXdpZHRoID0gLjQsIGxpbmV0eXBlID0gMikgKw0KICBnZW9tX3BvaW50KGFlcyhmaWxsID0gZXhwb3NpY2lvbiksIHNoYXBlID0gMjEsIHNpemUgPSAzLjQsIGNvbG91ciA9ICJncmV5MTUiKSArIGdlb21fdGV4dChhZXMobGFiZWwgPSBhcmJvbCksIG51ZGdlX3kgPSBkaWZmKHJhbmdlKGRlc2NfYWxsJGRlLCBuYS5ybSA9IFRSVUUpKSAqIC4xICsgLjMsIHNpemUgPSAzKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IENPTCwgZ3VpZGUgPSAibm9uZSIpICsgbGFicyh4ID0gIk1lZGlhIGRlbCDDoXJib2wgKGNtwrIpIiwgeSA9ICJERSBkZW50cm8gZGVsIMOhcmJvbCAoY23CsikiKQ0KcGMgPC0gZ2dwbG90KGRlc2NfYWxsWyFpcy5uYShkZXNjX2FsbCRkZV9sbiksIF0sIGFlcyhtZWRpYV9sbiwgZGVfbG4pKSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSwgY29sb3VyID0gImdyZXk0MCIsIGxpbmV3aWR0aCA9IC40LCBsaW5ldHlwZSA9IDIpICsNCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGV4cG9zaWNpb24pLCBzaGFwZSA9IDIxLCBzaXplID0gMy40LCBjb2xvdXIgPSAiZ3JleTE1IikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBDT0wsIGd1aWRlID0gIm5vbmUiKSArIGxhYnMoeCA9ICJNZWRpYSBkZWwgw6FyZWEgKGVzY2FsYSBsb2cpIiwgeSA9ICJERSBkZWwgw6FyZWEgKGVzY2FsYSBsb2cpIikNCmRkMiA8LSBkZXNjX2FsbFshaXMubmEoZGVzY19hbGwkZGUpLCBdDQppZiAobnJvdyhkZDIpID49IDMpIHsNCiAgUiRyX29yaWcgPC0gY29yKGRkMiRtZWRpYSwgZGQyJGRlKTsgUiRyX2xvZyA8LSBjb3IoZGQyJG1lZGlhX2xuLCBkZDIkZGVfbG4pDQogIHBiIDwtIHBiICsgYW5ub3RhdGUoInRleHQiLCB4ID0gbWluKGRkMiRtZWRpYSksIHkgPSBtYXgoZGQyJGRlKSwgaGp1c3QgPSAwLCBzaXplID0gMy4yLCBsYWJlbCA9IHBhc3RlMCgiciA9ICIsIGZ4KFIkcl9vcmlnLCAyKSkpDQogIHBjIDwtIHBjICsgYW5ub3RhdGUoInRleHQiLCB4ID0gbWluKGRkMiRtZWRpYV9sbiksIHkgPSBtYXgoZGQyJGRlX2xuKSwgaGp1c3QgPSAwLCBzaXplID0gMy4yLCBsYWJlbCA9IHBhc3RlMCgiciA9ICIsIGZ4KFIkcl9sb2csIDIpKSkNCn0NCnBhIC8gKHBiIHwgcGMpICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMS4yNSwgMSkpICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQpgYGANCg0KYGBge3IgY2FsY19sb2dzLCBpbmNsdWRlPUZBTFNFfQ0KUiR0eHRfYW5vdmExIDwtIGlmICghaXMubnVsbChSJGljYykpIHBhc3RlMCgiTG9zIMOhcmJvbGVzICIsIGlmZWxzZShSJGljYyRwIDwgMC4wNSwgInPDrSBkaWZpZXJlbiBlbnRyZSBzw60iLCAibm8gZGlmaWVyZW4gZGUgZm9ybWEgZGV0ZWN0YWJsZSIpLCAiIGVuIGVsIHRhbWHDsW8gZGUgc3VzIGhvamFzIChBTk9WQSwgKkYqKCIsIFIkaWNjJGQxLCAiOyAiLCBSJGljYyRkMiwgIikgPSAiLCBmeChSJGljYyRGLCAyKSwgIjsgIiwgZnBwKFIkaWNjJHApLA0KICAgICIpLiBFbCAiLCBmeCgxMDAgKiBSJGljYyRpY2MsIDApLCAiICUgZGUgbGEgdmFyaWFjacOzbiBkZWwgdGFtYcOxbyBzZSBkZWJlIGEgZGlmZXJlbmNpYXMgZW50cmUgw6FyYm9sZXMgKGNvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiBpbnRyYWNsYXNlLCBDQ0kgPSAiLCBmeChSJGljYyRpY2MsIDIpLCAiOyBJQyA5NSAlOiAiLCBmeChSJGljYyRsaSwgMiksICLigJMiLCBmeChSJGljYyRscywgMiksICIpIiwNCiAgICBjaXRlKCJtY2dyYXcxOTk2IiksICIgeSBlbCByZXN0bywgYSBkaWZlcmVuY2lhcyBlbnRyZSBob2phcyBkZSB1biBtaXNtbyDDoXJib2wgKCIsIGZyZWYoInZhcmlhbnphIiksICIpLiBFcyBkZWNpciwgbGFzIGhvamFzIGRlIHVuIG1pc21vIMOhcmJvbCB0aWVuZGVuIGEgcGFyZWNlcnNlIGVudHJlIHPDrS4iKSBlbHNlDQogICAgIk5vIGhheSBzdWZpY2llbnRlcyDDoXJib2xlcyBjb24gaG9qYXMgbWVkaWRhcyBwYXJhIHJlcGFydGlyIGxhIHZhcmlhY2nDs24uIg0KUiR0eHRfbG9ncyA8LSBpZiAoIWlzLm51bGwoUiRyX29yaWcpKSBwYXN0ZTAoIkVudHJlIMOhcmJvbGVzLCBsYSBkaXNwZXJzacOzbiBkZSBsYXMgaG9qYXMgY3JlY2UgY29uIGVsIHRhbWHDsW8gbWVkaW8gKHIgPSAiLCBmeChSJHJfb3JpZywgMiksICIpIHkgZXNhIHJlbGFjacOzbiBwYXNhIGEgciA9ICIsIGZ4KFIkcl9sb2csIDIpLA0KICAiIGFsIHVzYXIgbG9nYXJpdG1vcyAoIiwgc3VtKCFpcy5uYShkZXNjX2FsbCRkZSkpLCAiIMOhcmJvbGVzOyBjb2VmaWNpZW50ZXMgc29sbyBkZXNjcmlwdGl2b3MpLiBQb3IgZXNvIGVsIGFuw6FsaXNpcyBzZSBoYWNlIGVuIGVzY2FsYSBsb2dhcsOtdG1pY2EgeSBsb3MgZWZlY3RvcyBzZSBleHByZXNhbiBjb21vIHJhem9uZXMgZGUgdGFtYcOxby4iKSBlbHNlDQogICJDb24gbWVub3MgZGUgMyDDoXJib2xlcyBubyBzZSBldmFsw7phIGxhIHJlbGFjacOzbiBlbnRyZSBtZWRpYSB5IGRpc3BlcnNpw7NuOyBlbCBhbsOhbGlzaXMgc2UgaGFjZSBlbiBlc2NhbGEgbG9nYXLDrXRtaWNhIHBvcnF1ZSBlbCB0YW1hw7FvIGRlIHVuYSBob2phIHZhcsOtYSBkZSBmb3JtYSBtdWx0aXBsaWNhdGl2YS4iDQpgYGANCg0KYHIgUiR0eHRfbG9nc2ANCg0KIyMjIEN1w6FudGEgdmFyaWFjacOzbiBoYXkgZW50cmUgw6FyYm9sZXMNCg0KYHIgUiR0eHRfYW5vdmExYA0KDQpgYGB7ciBmaWdfdmFyaWFuemEsIGZpZy5oZWlnaHQ9My4zLCBmaWcuY2FwPWZjYXAoInZhcmlhbnphIiwgIlJlcGFydG8gZGUgbGEgdmFyaWFjacOzbiBkZWwgdGFtYcOxbyBkZSBsYSBob2phIiwgcGFzdGUwKCIqKmEqKiwgQ29tcG9uZW50ZXMgZGUgdmFyaWFuemEgKHBvcmNlbnRhamUgZGVsIHRvdGFsKSBkZWwgbW9kZWxvIHNvbG8gY29uIMOhcmJvbCAoZXN0aW1hZG9yZXMgZGUgQU5PVkEpIHksIHNpIGVzdMOhIGRpc3BvbmlibGUsIGRlbCBtb2RlbG8gbWl4dG8gY29uIGxhIGV4cG9zaWNpw7NuIGNvbW8gZWZlY3RvIGZpam8uIiwgY2l0ZSgibmFrYWdhd2EyMDEzIiksICIgKipiKiosIENvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiBpbnRyYWNsYXNlIGNvbiBzdSBpbnRlcnZhbG8gZGUgY29uZmlhbnphIGRlIDk1ICUuIikpfQ0KaWYgKCFpcy5udWxsKFIkaWNjKSkgew0KICBhMSA8LSBSJGljYyRhbjsgbXNiIDwtIGExJGBNZWFuIFNxYFsxXTsgbXN3IDwtIGExJGBNZWFuIFNxYFsyXQ0KICB2X3RfYSA8LSBtYXgoKG1zYiAtIG1zdykgLyBSJGljYyRuMCwgMCk7IHZfZV9hIDwtIG1zdw0KICB2diA8LSBkYXRhLmZyYW1lKG1vZGVsbyA9ICJTb2xvIMOhcmJvbFxuKEFOT1ZBKSIsIGNvbXAgPSBjKCJFbnRyZSDDoXJib2xlcyIsICJFbnRyZSBob2phcyAoZGVudHJvIGRlbCDDoXJib2wpIiksIHYgPSBjKHZfdF9hLCB2X2VfYSkpDQogIGlmICghaXMubnVsbChSJG1peCkpIHsNCiAgICBYbSA8LSBsbWU0OjpnZXRNRShSJG1peCRtLCAiWCIpOyB2ZiA8LSB2YXIoYXMubnVtZXJpYyhYbSAlKiUgbG1lNDo6Zml4ZWYoUiRtaXgkbSkpKQ0KICAgIHZ2IDwtIHJiaW5kKHZ2LCBkYXRhLmZyYW1lKG1vZGVsbyA9ICJDb24gZXhwb3NpY2nDs25cbihtaXh0bykiLCBjb21wID0gYygiRXhwb3NpY2nDs24gKGZpamEpIiwgIkVudHJlIMOhcmJvbGVzIiwgIkVudHJlIGhvamFzIChkZW50cm8gZGVsIMOhcmJvbCkiKSwgdiA9IGModmYsIFIkbWl4JHZfdCwgUiRtaXgkdl9lKSkpDQogIH0NCiAgdnYkcGN0IDwtIGF2ZSh2diR2LCB2diRtb2RlbG8sIEZVTiA9IGZ1bmN0aW9uKHopIDEwMCAqIHogLyBzdW0oeikpDQogIHZ2JGNvbXAgPC0gZmFjdG9yKHZ2JGNvbXAsIGxldmVscyA9IGMoIkV4cG9zaWNpw7NuIChmaWphKSIsICJFbnRyZSDDoXJib2xlcyIsICJFbnRyZSBob2phcyAoZGVudHJvIGRlbCDDoXJib2wpIikpDQogIHBhIDwtIGdncGxvdCh2diwgYWVzKHBjdCwgbW9kZWxvLCBmaWxsID0gY29tcCkpICsgZ2VvbV9jb2wod2lkdGggPSAuNTUsIGNvbG91ciA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gaWZlbHNlKHBjdCA+IDYsIHBhc3RlMChmeChwY3QsIDApLCAiICUiKSwgIiIpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSwgc2l6ZSA9IDMsIGNvbG91ciA9ICJ3aGl0ZSIsIGZvbnRmYWNlID0gImJvbGQiKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRXhwb3NpY2nDs24gKGZpamEpIiA9ICIjRTY5RjAwIiwgIkVudHJlIMOhcmJvbGVzIiA9ICIjMDA3MkIyIiwgIkVudHJlIGhvamFzIChkZW50cm8gZGVsIMOhcmJvbCkiID0gImdyZXk3MCIpLCBuYW1lID0gIkZ1ZW50ZSBkZSB2YXJpYWNpw7NuIikgKw0KICAgIGxhYnMoeCA9ICIlIGRlIGxhIHZhcmlhY2nDs24gZGVsIHRhbWHDsW8gZGUgbGEgaG9qYSIsIHkgPSBOVUxMKSArIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAyKSkNCiAgcGIgPC0gZ2dwbG90KGRhdGEuZnJhbWUoeCA9ICJDQ0kiLCBlID0gUiRpY2MkaWNjLCBsbyA9IFIkaWNjJGxpLCBoaSA9IFIkaWNjJGxzKSwgYWVzKGUsIHgpKSArDQogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwLCAxKSwgbGluZXR5cGUgPSAzLCBjb2xvdXIgPSAiZ3JleTYwIikgKw0KICAgIGdlb21fc2VnbWVudChhZXMoeCA9IGxvLCB4ZW5kID0gaGksIHkgPSB4LCB5ZW5kID0geCksIGxpbmV3aWR0aCA9IC44KSArIGdlb21fcG9pbnQoc2l6ZSA9IDMuNiwgc2hhcGUgPSAyMSwgZmlsbCA9ICIjMDA3MkIyIikgKw0KICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKG1pbigwLCBSJGljYyRsaSkgLSAuMDUsIDEuMDIpKSArIGxhYnMoeCA9ICJDb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gaW50cmFjbGFzZSIsIHkgPSBOVUxMKSArDQogICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkNCiAgcGEgKyBwYiArIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMS44LCAxKSkgKyBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJhIikNCn0NCmBgYA0KDQojIyBWYWxvcmVzIGF0w61waWNvczogwr9lcnJvciBkZSBtZWRpY2nDs24gdSBob2phIHJlYWxtZW50ZSBkaXN0aW50YT8NCg0KPGRldGFpbHMgY2xhc3M9ImRldGFsbGUiPg0KDQo8c3VtbWFyeT5Dcml0ZXJpbyBwYXJhIGRlY2lkaXIgc2kgdW5hIGhvamEgYXTDrXBpY2Egc2UgY29uc2VydmEgKGRvcyBwYXNvcyk8L3N1bW1hcnk+DQoNClNlIGFwbGljw7MgdW4gY3JpdGVyaW8gZW4gZG9zIHBhc29zLiAqKlByaW1lcm8qKiwgwr9oYXkgdW5hIGNhdXNhIGRlIG1lZGljacOzbiAodW5pZGFkIGVxdWl2b2NhZGEsIMOhcmVhIG1heW9yIHF1ZSBlbCBtYXJjbywgdHJhem8gZHVkb3NvLCBmb3RvIGJvcnJvc2EpPyBTaSBsYSBoYXksIHNlIGNvcnJpZ2UgbyBzZSBleGNsdXllLCBjb21vIGVuIGxhIHJldmlzacOzbiBkZSBjYWxpZGFkIChgciB0cmVmKCJxYyIpYCkuICoqU2VndW5kbyoqLCBzaSBubyBoYXkgY2F1c2EgZGUgbWVkaWNpw7NuIHBlcm8gbGEgaG9qYSBxdWVkYSBmdWVyYSBkZSBsYSByZWdsYSBkZSBUdWtleSBkZSBzdSDDoXJib2wgKFExIOKIkiAxLDXCt1JJQywgUTMgKyAxLDXCt1JJQykgbyBzdSAqeiogcm9idXN0byBiYXNhZG8gZW4gbGEgTUFEIHN1cGVyYSAzLDUgZW4gdmFsb3IgYWJzb2x1dG8sIHNlIGNvbnNpZGVyYSB1bmEgaG9qYSByZWFsbWVudGUgZGlzdGludGE6ICoqc2UgY29uc2VydmEqKiB5IHNlIG1pZGUgY3XDoW50byBjYW1iaWEgZWwgcmVzdWx0YWRvIHNpbiBlbGxhIChhbsOhbGlzaXMgZGUgc2Vuc2liaWxpZGFkKS4gQWRlbcOhcyBzZSBleGFtaW5hcm9uIGxvcyByZXNpZHVvcyBzdHVkZW50aXphZG9zIHkgbGEgZGlzdGFuY2lhIGRlIENvb2sgZGVsIG1vZGVsbyBjb24gw6FyYm9sLg0KDQo8L2RldGFpbHM+DQoNCmBgYHtyIHRhYl9hdGlwLCByZXN1bHRzPSdhc2lzJ30NCmNhdCh0Y2FwKCJhdGlwIiwgIkhvamFzIG1hcmNhZGFzIHBvciBhbGfDum4gY3JpdGVyaW8gZGUgYXRpcGljaWRhZCIsICJTZSBldmFsw7phbiDDoXJib2xlcyBjb24gYWwgbWVub3MgNCBob2phcyBtZWRpZGFzLiA8aT56PC9pPiByb2J1c3RvID0gMCw2NzQ1wrcoeCDiiJIgbWVkaWFuYSkvTUFELiIpKQ0KaWYgKG5yb3coYXRpcF9tYXJjYWRhcykgPiAwKSB7DQogIHRhIDwtIGRhdGEuZnJhbWUow4FyYm9sID0gYXRpcF9tYXJjYWRhcyRhcmJvbCwgYEhvamEgKG4uwropYCA9IGF0aXBfbWFyY2FkYXMkbl9ob2phLCBgw4FyZWEgKGNtwrIpYCA9IGZ4KGF0aXBfbWFyY2FkYXMkYXJlYSwgMSksDQogICAgICAgICAgICAgICAgICAgYHogcm9idXN0b2AgPSBmeChhdGlwX21hcmNhZGFzJHpfcm9idXN0bywgMiksIGBGdWVyYSBkZSBUdWtleWAgPSBpZmVsc2UoYXRpcF9tYXJjYWRhcyRmdWVyYV90dWtleSwgInPDrSIsICJubyIpLA0KICAgICAgICAgICAgICAgICAgIGB8enwgPiAzLDVgID0gaWZlbHNlKGF0aXBfbWFyY2FkYXMkZnVlcmFfeiwgInPDrSIsICJubyIpLCBgUmF6w7NuIMOhcmVhIC8gbWVkaWFuYSBkZWwgw6FyYm9sYCA9IGZ4KGF0aXBfbWFyY2FkYXMkcmF6b25fbWVkaWFuYSwgMiksIGNoZWNrLm5hbWVzID0gRkFMU0UpDQogIHRhYmxhKHRhLCBhbGlnbiA9ICJscnJyY2NyIikNCn0gZWxzZSBjYXQoIjxwPjxpPk5pbmd1bmEgaG9qYSBxdWVkYSBmdWVyYSBkZSBsb3MgY3JpdGVyaW9zIGVuIGxvcyDDoXJib2xlcyBldmFsdWFibGVzLjwvaT48L3A+XG4iKQ0KUiR0eHRfYXRpcCA8LSBwYXN0ZTAoIkNvbiBsb3MgY3JpdGVyaW9zIGRlc2NyaXRvcyBzZSBtYXJjYXJvbiAiLCBSJG5fYXRpcCwgIiBob2phcyAoIiwgdHJlZigiYXRpcCIpLCAiKS4gTmluZ3VuYSB0aWVuZSB1bmEgY2F1c2EgZGUgbWVkaWNpw7NuIGV2aWRlbnRlIChzdSBjb2NpZW50ZSDDoXJlYS9tYXJjbyBlc3TDoSBkZW50cm8gZGVsIHJhbmdvIG9ic2VydmFkbywgIiwgZngoUiRyYXRpb19va1sxXSwgMiksICLigJMiLCBmeChSJHJhdGlvX29rWzJdLCAyKSwgIiksIHBvciBsbyBxdWUgc2UgY29uc2VydmFuLiBTZWfDum4gY8OzbW8gc2UgcmVzdW1hIGNhZGEgw6FyYm9sIChtZWRpYSwgbWVkaWFuYSwgZXRjLiksIGxhIGRpZmVyZW5jaWEgc29tYnJhIOKIkiBzb2wgdmEgZGUgIiwNCiAgZngoUiRzZW5zX3JhbmdvWzFdLCAxKSwgIiBhICIsIGZ4KFIkc2Vuc19yYW5nb1syXSwgMSksICIgY23CsiAoIiwgZnJlZigiYXRpcGljb3MiKSwgImIpIiwNCiAgaWYgKCFpcy5uYShSJHNlbnNfcmFuZ29bMV0pICYmIFIkc2Vuc19yYW5nb1sxXSAqIFIkc2Vuc19yYW5nb1syXSA8IDApICI6ICoqZWwgc2lnbm8gY2FtYmlhIGNvbiBlbCByZXN1bWVuIGVsZWdpZG8qKiwgYXPDrSBxdWUgbGEgY29uY2x1c2nDs24gZGVwZW5kZSBkZSB1bmFzIHBvY2FzIGhvamFzLiIgZWxzZSAiOiBlbCBzaWdubyBubyBjYW1iaWEsIGFzw60gcXVlIGxhIGNvbmNsdXNpw7NuIG5vIGRlcGVuZGUgZGUgaG9qYXMgaW5kaXZpZHVhbGVzLiIpDQpgYGANCg0KYHIgUiR0eHRfYXRpcGANCg0KYGBge3IgZmlnX2F0aXBpY29zLCBmaWcuaGVpZ2h0PTMuNiwgZmlnLmNhcD1mY2FwKCJhdGlwaWNvcyIsICJEZXRlY2Npw7NuIGRlIGhvamFzIGF0w61waWNhcyB5IHNlbnNpYmlsaWRhZCBkZWwgcmVzdWx0YWRvIiwgIioqYSoqLCAqeiogcm9idXN0byBkZSBjYWRhIGhvamEgcmVzcGVjdG8gZGUgbGEgbWVkaWFuYSBkZSBzdSDDoXJib2w7IGzDrW5lYXMgZGlzY29udGludWFzLCDCsTMsNS4gKipiKiosIERpZmVyZW5jaWEgc29tYnJhIOKIkiBzb2wgZW50cmUgw6FyYm9sZXMgc2Vnw7puIGVsIGVzdGFkw61zdGljbyBjb24gcXVlIHNlIHJlc3VtZSBjYWRhIMOhcmJvbC4iKX0NCmlmIChucm93KGF0aXApID4gMCkgew0KICBhdGlwJGNscyA8LSBpZmVsc2UoYXRpcCRmdWVyYV90dWtleSB8IGF0aXAkZnVlcmFfeiwgIm1hcmNhZGEiLCAiZGVudHJvIikNCiAgcGEgPC0gZ2dwbG90KGF0aXAsIGFlcyhhcmJvbCwgel9yb2J1c3RvKSkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKC0zLjUsIDMuNSksIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImdyZXk1MCIpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3VyID0gImdyZXk4NSIpICsNCiAgICBnZW9tX2ppdHRlcihhZXMoZmlsbCA9IGNscyksIHdpZHRoID0gLjEyLCBoZWlnaHQgPSAwLCBzaGFwZSA9IDIxLCBzaXplID0gMi42LCBjb2xvdXIgPSAiZ3JleTIwIikgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoZGVudHJvID0gImdyZXk4MCIsIG1hcmNhZGEgPSAiI0Q1NUUwMCIpLCBuYW1lID0gIkNsYXNpZmljYWNpw7NuIikgKyBsYWJzKHggPSBOVUxMLCB5ID0gInogcm9idXN0byAoTUFEKSIpDQp9IGVsc2UgcGEgPC0gZ2dwbG90KCkgKyB0aGVtZV92b2lkKCkgKyBhbm5vdGF0ZSgidGV4dCIsIHggPSAwLCB5ID0gMCwgbGFiZWwgPSAiU2luIMOhcmJvbGVzIGV2YWx1YWJsZXMiKQ0Kc2Vuc190YWIkUmVzdW1lbiA8LSBmYWN0b3Ioc2Vuc190YWIkUmVzdW1lbiwgbGV2ZWxzID0gc2Vuc190YWIkUmVzdW1lbltvcmRlcihzZW5zX3RhYiRkaWYpXSkNCnBiIDwtIGdncGxvdChzZW5zX3RhYiwgYWVzKGRpZiwgUmVzdW1lbikpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAzKSArDQogIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHhlbmQgPSBkaWYsIHllbmQgPSBSZXN1bWVuKSwgY29sb3VyID0gImdyZXk2MCIpICsgZ2VvbV9wb2ludChzaXplID0gMy41LCBzaGFwZSA9IDIxLCBmaWxsID0gQ09MWyJzb21icmEiXSwgY29sb3VyID0gImdyZXkxNSIpICsNCiAgbGFicyh4ID0gIlNvbWJyYSDiiJIgc29sIChjbcKyKSIsIHkgPSBOVUxMKQ0KcGEgKyBwYiArIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMSwgMS4xNSkpICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQpgYGANCg0KIyMgTGEgdW5pZGFkIGRlIGFuw6FsaXNpcyBlcyBlbCDDoXJib2wNCg0KTGEgZXhwb3NpY2nDs24gc2UgYXNpZ27DsyBhbCDDoXJib2wsIG5vIGEgbGEgaG9qYTogbGFzIGhvamFzIGRlIHVuIG1pc21vIMOhcmJvbCBjb21wYXJ0ZW4gc3VlbG8sIGVkYWQsIGdlbm90aXBvIHkgbHV6LiBUcmF0YXJsYXMgY29tbyByw6lwbGljYXMgZGUgbGEgZXhwb3NpY2nDs24gbXVsdGlwbGljYSBhcnRpZmljaWFsbWVudGUgZWwgdGFtYcOxbyBkZSBtdWVzdHJhLmByIGNpdGUoImh1cmxiZXJ0MTk4NCIpYCBDdWFudGlmaWNhbW9zIGVzYSBpbmZsYWNpw7NuIGNvbiBlbCAqKmVmZWN0byBkZSBkaXNlw7FvKiosICpERUZGKiA9IDEgKyAoKm3MhCog4oiSIDEpwrdDQ0ksIHkgY29uIGVsIHRhbWHDsW8gZGUgbXVlc3RyYSBlZmVjdGl2bywgKk4qLypERUZGKi4NCg0KYGBge3IgdGFiX3BzZXVkbywgcmVzdWx0cz0nYXNpcyd9DQpSJGRlZmYgPC0gTkE7IFIkbmVmZiA8LSBOQQ0KaWYgKCFpcy5udWxsKFIkaWNjKSkgeyBtYmFyIDwtIG5yb3cobGltQSkgLyBubGV2ZWxzKGxpbUEkYXJib2xfZik7IFIkZGVmZiA8LSAxICsgKG1iYXIgLSAxKSAqIG1heChSJGljYyRpY2MsIDApOyBSJG5lZmYgPC0gbnJvdyhsaW1BKSAvIFIkZGVmZjsgUiRtYmFyIDwtIG1iYXIgfQ0KZmlsYXMgPC0gbGlzdCgpDQppZiAoIWlzLm51bGwoUiRwc2V1ZG8pKSBmaWxhc1tbMV1dIDwtIGMoIkhvamFzIGNvbW8gZGF0b3MgaW5kZXBlbmRpZW50ZXMgKGluY29ycmVjdG8pIiwgUiRwc2V1ZG8kbiwgZngoUiRwc2V1ZG8kcmF6b24sIDIpLCBmY2koUiRwc2V1ZG8kbGksIFIkcHNldWRvJGxzKSwgZnAoUiRwc2V1ZG8kcCkpDQpmaWxhc1tbbGVuZ3RoKGZpbGFzKSArIDFdXSA8LSBjKCJVbiBwcm9tZWRpbyBwb3Igw6FyYm9sIChjb3JyZWN0bykiLCBwYXN0ZTAoUiRuX3NvbCwgIiArICIsIFIkbl9zb20sICIgPSAiLCBSJG5fc29sICsgUiRuX3NvbSksIGZ4KGJBJHJhem9uLCAyKSwgZmNpKGJBJGxpLCBiQSRscyksIGZwKGJBJHBfd2VsY2gpKQ0KdHAgPC0gYXMuZGF0YS5mcmFtZShkby5jYWxsKHJiaW5kLCBmaWxhcyksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCm5hbWVzKHRwKSA8LSBjKCJFc3RyYXRlZ2lhIGRlIGFuw6FsaXNpcyIsICJVbmlkYWRlcyBhbmFsaXphZGFzIChuKSIsICJSYXrDs24gc29tYnJhL3NvbCIsICJJQyA5NSAlIiwgIlZhbG9yIGRlIHAgKFdlbGNoKSIpDQpjYXQodGNhcCgicHNldWRvIiwgIlBzZXVkb3JyZXBsaWNhY2nDs246IGhvamFzIGZyZW50ZSBhIMOhcmJvbGVzIGNvbW8gdW5pZGFkIGRlIGFuw6FsaXNpcyIsIHBhc3RlMCgiUHJ1ZWJhIGRlIFdlbGNoIGVuIGVzY2FsYSBsb2dhcsOtdG1pY2EgKHJhesOzbiBkZSBtZWRpYXMgZ2VvbcOpdHJpY2FzKS4gRWZlY3RvIGRlIGRpc2XDsW8gZXN0aW1hZG86ICIsIGZ4KFIkZGVmZiwgMSksICI7IHRhbWHDsW8gZGUgbXVlc3RyYSBlZmVjdGl2byDiiYggIiwgZngoUiRuZWZmLCAxKSwgIiBob2phcyBpbmRlcGVuZGllbnRlcyBkZSAiLCBucm93KGxpbUEpLCAiLiIpKSkNCnRhYmxhKHRwLCBhbGlnbiA9ICJscnJyciIpDQpSJHR4dF9wc2V1ZG8gPC0gaWYgKCFpcy5udWxsKFIkcHNldWRvKSkgcGFzdGUwKCJTaSBsYXMgIiwgUiRwc2V1ZG8kbiwgIiBob2phcyBzZSB0cmF0YXJhbiBjb21vIGRhdG9zIGluZGVwZW5kaWVudGVzLCBlbCB2YWxvciBkZSAqcCogc2Vyw61hICIsIGZwKFIkcHNldWRvJHApLCAiIChlbiBsdWdhciBkZSAiLCBmcChiQSRwX3dlbGNoKSwgIikgeSBlbCBpbnRlcnZhbG8gcGFyZWNlcsOtYSBtw6FzIGVzdHJlY2hvICgiLCBmY2koUiRwc2V1ZG8kbGksIFIkcHNldWRvJGxzKSwgIiBmcmVudGUgYSAiLCBmY2koYkEkbGksIGJBJGxzKSwNCiAgIikuIEVzYSBwcmVjaXNpw7NuIGVzIGlsdXNvcmlhOiBjb21vIGxhcyBob2phcyBkZSB1biBtaXNtbyDDoXJib2wgc2UgcGFyZWNlbiBlbnRyZSBzw60gKENDSSA9ICIsIGZ4KFIkaWNjJGljYywgMiksICIpLCBsYXMgIiwgbnJvdyhsaW1BKSwgIiBob2phcyBhcG9ydGFuIGluZm9ybWFjacOzbiBlcXVpdmFsZW50ZSBhIHNvbG8gdW5hcyAiLCBmeChSJG5lZmYsIDApLCAiIGhvamFzIGluZGVwZW5kaWVudGVzLiIpIGVsc2UgIk5vIGhheSBkb3MgZXhwb3NpY2lvbmVzIGNvbiBkYXRvcyBzdWZpY2llbnRlcyBwYXJhIGlsdXN0cmFyIGxhIHBzZXVkb3JyZXBsaWNhY2nDs24uIg0KYGBgDQoNCmByIFIkdHh0X3BzZXVkb2ANCg0KYGBge3IgZmlnX2V4cG9zaWNpb24sIGZpZy5oZWlnaHQ9NC40LCBmaWcuY2FwPWZjYXAoImV4cG9zaWNpb24iLCAiRWwgY29udHJhc3RlIHNvbOKAk3NvbWJyYTogaG9qYXMgZnJlbnRlIGEgw6FyYm9sZXMiLCAiKiphKiosIEhvamFzIChkZXNjcmlwdGl2byk6IGNhZGEgc8OtbWJvbG8gZXMgdW4gw6FyYm9sIGRpc3RpbnRvOyBsYXMgaG9qYXMgZGVsIG1pc21vIMOhcmJvbCBzZSBhZ3J1cGFuLCBsbyBxdWUgcmV2ZWxhIHN1IGZhbHRhIGRlIGluZGVwZW5kZW5jaWEuICoqYioqLCBVbmlkYWQgZGUgYW7DoWxpc2lzIGNvcnJlY3RhOiB1biBwdW50byBwb3Igw6FyYm9sIChtZWRpYSBhcml0bcOpdGljYSBkZSBzdXMgaG9qYXMpLCBjb24gbGEgbWVkaWEgZGUgY2FkYSBleHBvc2ljacOzbiB5IHN1IGludGVydmFsbyBkZSBjb25maWFuemEgPGk+dDwvaT4gZGUgOTUgJSAoYmFycmEpOyAqbiogPSBuw7ptZXJvIGRlIMOhcmJvbGVzLiIpfQ0KaWYgKG5sZXZlbHMobGltQSRleHBvc2ljaW9uKSA9PSAyKSB7DQogIHBhIDwtIGdncGxvdChsaW1BLCBhZXMoZXhwb3NpY2lvbiwgYXJlYSkpICsNCiAgICBnZW9tX3Zpb2xpbihhZXMoZmlsbCA9IGV4cG9zaWNpb24pLCBhbHBoYSA9IC4yMiwgY29sb3VyID0gTkEsIHNjYWxlID0gIndpZHRoIikgKw0KICAgIGdlb21fYm94cGxvdCh3aWR0aCA9IC4xNCwgb3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImdyZXkyNSIsIGxpbmV3aWR0aCA9IC40KSArDQogICAgZ2VvbV9qaXR0ZXIoYWVzKGZpbGwgPSBleHBvc2ljaW9uLCBzaGFwZSA9IGFyYm9sKSwgd2lkdGggPSAuMTQsIGhlaWdodCA9IDAsIHNpemUgPSAyLjIsIGNvbG91ciA9ICJncmV5MTUiLCBzdHJva2UgPSAuMywgYWxwaGEgPSAuODUpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBDT0wsIGd1aWRlID0gIm5vbmUiKSArIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBzaHBfZiwgbmFtZSA9ICLDgXJib2wiKSArIGxhYnMoeCA9IE5VTEwsIHkgPSAiw4FyZWEgZm9saWFyIGRlIGxhIGhvamEgKGNtwrIpIikNCiAgZXhfc3VtIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShzcGxpdChhcmIsIGRyb3BsZXZlbHMoYXJiJGV4cG9zaWNpb24pKSwgZnVuY3Rpb24oZCkgew0KICAgIG4gPC0gbnJvdyhkKTsgbSA8LSBtZWFuKGQkbWVkaWEpOyBzIDwtIGlmIChuID4gMSkgc2QoZCRtZWRpYSkgZWxzZSBOQTsgdGMgPC0gaWYgKG4gPiAxKSBxdCguOTc1LCBuIC0gMSkgZWxzZSBOQQ0KICAgIGRhdGEuZnJhbWUoZXhwb3NpY2lvbiA9IGFzLmNoYXJhY3RlcihkJGV4cG9zaWNpb25bMV0pLCBuID0gbiwgbSA9IG0sIGxpID0gbSAtIHRjICogcyAvIHNxcnQobiksIGxzID0gbSArIHRjICogcyAvIHNxcnQobikpDQogIH0pKQ0KICBleF9zdW0kZXhwb3NpY2lvbiA8LSBmYWN0b3IoZXhfc3VtJGV4cG9zaWNpb24sIGxldmVscyA9IGMoInNvbCIsICJzb21icmEiKSkNCiAgcGIgPC0gZ2dwbG90KCkgKw0KICAgIGdlb21fc2VnbWVudChkYXRhID0gZXhfc3VtLCBhZXMoeCA9IGV4cG9zaWNpb24sIHhlbmQgPSBleHBvc2ljaW9uLCB5ID0gbGksIHllbmQgPSBscyksIGxpbmV3aWR0aCA9IDEuMSwgY29sb3VyID0gImdyZXkyMCIsIG5hLnJtID0gVFJVRSkgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGV4X3N1bSwgYWVzKGV4cG9zaWNpb24sIG0pLCBzaGFwZSA9IDk1LCBzaXplID0gMTQsIGNvbG91ciA9ICJncmV5MjAiKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gYXJiLCBhZXMoZXhwb3NpY2lvbiwgbWVkaWEsIGZpbGwgPSBleHBvc2ljaW9uLCBzaGFwZSA9IGFyYm9sKSwgc2l6ZSA9IDQsIGNvbG91ciA9ICJncmV5MTUiLCBzdHJva2UgPSAuNSwgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4ID0gLjE4KSkgKw0KICAgIGdlb21fdGV4dChkYXRhID0gYXJiLCBhZXMoZXhwb3NpY2lvbiwgbWVkaWEsIGxhYmVsID0gYXJib2wpLCBudWRnZV94ID0gLjMyLCBzaXplID0gMywgY29sb3VyID0gImdyZXkyNSIpICsNCiAgICBnZW9tX3RleHQoZGF0YSA9IGV4X3N1bSwgYWVzKGV4cG9zaWNpb24sIEluZiwgbGFiZWwgPSBwYXN0ZTAoIm4gPSAiLCBuLCAiIMOhcmJvbGVzIikpLCB2anVzdCA9IDEuNiwgc2l6ZSA9IDMuMikgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IENPTCwgZ3VpZGUgPSAibm9uZSIpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IHNocF9mLCBndWlkZSA9ICJub25lIikgKyBsYWJzKHggPSBOVUxMLCB5ID0gIsOBcmVhIGZvbGlhciBtZWRpYSBkZWwgw6FyYm9sIChjbcKyKSIpDQogIHBhICsgcGIgKyBwbG90X2xheW91dCh3aWR0aHMgPSBjKDEuMiwgMSkpICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQp9DQpgYGANCg0KIyMgSW5mZXJlbmNpYSBzb2JyZSBsYSBleHBvc2ljacOzbiBjb24gZWwgw6FyYm9sIGNvbW8gdW5pZGFkDQoNClNvYnJlIGxvcyBwcm9tZWRpb3MgZGUgw6FyYm9sIHNlIGFwbGljYXJvbiBzZWlzIGVuZm9xdWVzIGNvbXBsZW1lbnRhcmlvcyAoYHIgdHJlZigiYmF0ZXJpYSIpYCksIHF1ZSBzZSByZXN1bWVuIGVuIGxhIGByIGZyZWYoImZvcmVzdCIpYC4NCg0KPGRldGFpbHMgY2xhc3M9ImRldGFsbGUiPg0KDQo8c3VtbWFyeT5WZXIgbG9zIHNlaXMgZW5mb3F1ZXMgeSBlbCB0YW1hw7FvIGRlbCBlZmVjdG88L3N1bW1hcnk+DQoNCkxvcyBlbmZvcXVlcyBmdWVyb246IGxhIHBydWViYSAqdCogZGUgV2VsY2gsYHIgY2l0ZSgid2VsY2gxOTQ3IilgIHNvYnJlIGxhIGVzY2FsYSBvcmlnaW5hbCB5IHNvYnJlIGxhIGVzY2FsYSBsb2dhcsOtdG1pY2EgKHF1ZSBkYSBkaXJlY3RhbWVudGUgdW5hIHJhesOzbiBkZSBtZWRpYXMgZ2VvbcOpdHJpY2FzKTsgbGEgcHJ1ZWJhIGRlIFdpbGNveG9uIGV4YWN0YTtgciBjaXRlKCJ3aWxjb3hvbjE5NDUiKWAgdW5hIHBydWViYSBkZSBwZXJtdXRhY2nDs24gZXhhY3RhIHF1ZSBlbnVtZXJhIHRvZG9zIGxvcyByZXBhcnRpbWllbnRvcyBwb3NpYmxlcyBkZSBsYXMgZXRpcXVldGFzIHNvbC9zb21icmEgZW50cmUgbG9zIMOhcmJvbGVzOyB1biBib290c3RyYXAgamVyw6FycXVpY28gZW4gZG9zIGV0YXBhcyAow6FyYm9sZXMgeSBsdWVnbyBob2phcyBkZW50cm8gZGUgw6FyYm9sKTtgciBjaXRlKCJlZnJvbjE5NzkiKWAgZWwgbW9kZWxvIG1peHRvIGNvbiBlbCDDoXJib2wgY29tbyBlZmVjdG8gYWxlYXRvcmlvLCBjb24gZ3JhZG9zIGRlIGxpYmVydGFkIGRlIFNhdHRlcnRod2FpdGU7YHIgY2l0ZSgiYmF0ZXMyMDE1IiwgImt1em5ldHNvdmEyMDE3IiwgInNhdHRlcnRod2FpdGUxOTQ2IilgIHkgZWwgQU5PVkEgYW5pZGFkbywgcXVlIHBydWViYSBsYSBleHBvc2ljacOzbiBjb250cmEgbGEgdmFyaWFjacOzbiBlbnRyZSDDoXJib2xlcy4gRWwgdGFtYcOxbyBkZWwgZWZlY3RvIHNlIHJlc3VtZSBjb24gbGEgKmcqIGRlIEhlZGdlcy5gciBjaXRlKCJoZWRnZXMxOTgxIiwgImxha2VuczIwMTMiKWANCg0KPC9kZXRhaWxzPg0KDQpgYGB7ciB0YWJfYmF0ZXJpYSwgcmVzdWx0cz0nYXNpcyd9DQpmaWwgPC0gbGlzdCgpDQpmaWxbWzFdXSA8LSBjKCJXZWxjaCBjb24gZWwgcHJvbWVkaW8gcG9yIMOhcmJvbCAoZXNjYWxhIGxvZykiLCBwYXN0ZTAoInJhesOzbiA9ICIsIGZ4KGJBJHJhem9uLCAyKSksIGZjaShiQSRsaSwgYkEkbHMpLCBwYXN0ZTAoImdsID0gIiwgZngoYkEkZGYsIDEpKSwgZnAoYkEkcF93ZWxjaCkpDQpmaWxbWzJdXSA8LSBjKCJXZWxjaCBzb2JyZSDDoXJlYSBtZWRpYSBwb3Igw6FyYm9sIChjbcKyKSIsIGlmICghaXMubnVsbChiY20pKSBwYXN0ZTAoImRpZi4gPSAiLCBmeChiY20kZGlmLCAxKSwgIiBjbcKyIikgZWxzZSAibi9kIiwgaWYgKCFpcy5udWxsKGJjbSkpIGZjaShiY20kbGksIGJjbSRscywgMSkgZWxzZSAibi9kIiwgIiIsIGlmICghaXMubnVsbChiY20pKSBmcChiY20kcCkgZWxzZSAibi9kIikNCmZpbFtbM11dIDwtIGMoIldpbGNveG9uIChleGFjdGEpIiwgIuKAlCIsICLigJQiLCAiIiwgZnAoYkEkcF93aWxjb3gpKQ0KZmlsW1s0XV0gPC0gYygiUGVybXV0YWNpw7NuIGV4YWN0YSBkZSBldGlxdWV0YXMiLCAi4oCUIiwgIuKAlCIsIHBhc3RlMChpZiAoIWlzLm51bGwoYkEkcGVybSkpIGJBJHBlcm0kbl9yZXAgZWxzZSAibi9kIiwgIiByZXBhcnRvczsgcCBtw61uaW1vID0gIiwgUiRwbWluX3R4dCksIGZwKGJBJHBfcGVybSkpDQpmaWxbWzVdXSA8LSBjKCJCb290c3RyYXAgamVyw6FycXVpY28gKHBlcmNlbnRpbCkiLCBpZiAoIWlzLm51bGwoUiRib290KSkgcGFzdGUwKCJyYXrDs24gPSAiLCBmeChleHAobWVkaWFuKFIkYm9vdCkpLCAyKSkgZWxzZSAibi9kIiwgaWYgKCFpcy5udWxsKFIkYm9vdCkpIGZjaShSJGJvb3RfY2lbMV0sIFIkYm9vdF9jaVsyXSkgZWxzZSAibi9kIiwNCiAgICAgICAgICAgICAgaWYgKCFpcy5udWxsKFIkYm9vdCkpIHBhc3RlMCgiUChyYXrDs24gPiAxKSA9ICIsIGZ4KFIkYm9vdF9wcm9iLCAyKSkgZWxzZSAiIiwgIuKAlCIpDQpmaWxbWzZdXSA8LSBjKCJNb2RlbG8gbWl4dG8gKMOhcmJvbCBhbGVhdG9yaW8pIiwgaWYgKCFpcy5udWxsKFIkbWl4KSkgcGFzdGUwKCJyYXrDs24gPSAiLCBmeChSJG1peCRyYXpvbiwgMikpIGVsc2UgIm5vIGRpc3BvbmlibGUiLCBpZiAoIWlzLm51bGwoUiRtaXgpKSBmY2koUiRtaXgkbGksIFIkbWl4JGxzKSBlbHNlICLigJQiLA0KICAgICAgICAgICAgICBpZiAoIWlzLm51bGwoUiRtaXgpKSBwYXN0ZTAoInQgPSAiLCBmeChSJG1peCR0LCAyKSwgIjsgZ2wgPSAiLCBmeChSJG1peCRkZiwgMSkpIGVsc2UgIiIsIGlmICghaXMubnVsbChSJG1peCkpIGZwKFIkbWl4JHApIGVsc2UgIuKAlCIpDQpmaWxbWzddXSA8LSBjKCJBTk9WQSBhbmlkYWRvIChleHBvc2ljacOzbiB2cy4gw6FyYm9sKSIsICLigJQiLCAi4oCUIiwgaWYgKCFpcy5udWxsKFIkbmVzdGVkKSkgcGFzdGUwKCJGKDE7ICIsIFIkbmVzdGVkJGFuJERmWzJdLCAiKSA9ICIsIGZ4KFIkbmVzdGVkJEZlLCAyKSkgZWxzZSAibi9kIiwgaWYgKCFpcy5udWxsKFIkbmVzdGVkKSkgZnAoUiRuZXN0ZWQkcGUpIGVsc2UgIm4vZCIpDQpmaWxbWzhdXSA8LSBjKCJUYW1hw7FvIGRlbCBlZmVjdG8gKGcgZGUgSGVkZ2VzLCBlc2NhbGEgbG9nKSIsIHBhc3RlMCgiZyA9ICIsIGZ4KGJBJGcsIDIpKSwgZmNpKGJBJGdfbGksIGJBJGdfbHMpLCAiIiwgIuKAlCIpDQp0YiA8LSBhcy5kYXRhLmZyYW1lKGRvLmNhbGwocmJpbmQsIGZpbCksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSk7IG5hbWVzKHRiKSA8LSBjKCJNw6l0b2RvIGRlIGFuw6FsaXNpcyIsICJFc3RpbWFjacOzbiAoc29tYnJhIHJlc3BlY3RvIGRlIHNvbCkiLCAiSUMgOTUgJSIsICJFc3RhZMOtc3RpY28gLyBkZXRhbGxlIiwgIlZhbG9yIGRlIHAiKQ0KY2F0KHRjYXAoImJhdGVyaWEiLCAiQ29tcGFyYWNpw7NuIHNvbOKAk3NvbWJyYSBjb24gZWwgw6FyYm9sIGNvbW8gdW5pZGFkIChhbsOhbGlzaXMgcHJpbWFyaW86IMOhcmVhcyBtZWRpZGFzKSIsIHBhc3RlMCgiUmF6b25lcyB5IGRpZmVyZW5jaWFzIHNvbiBzb21icmEgcmVzcGVjdG8gZGUgc29sOyAiLCBSJG5fc29sLCAiIMOhcmJvbGVzIGRlIHNvbCB5ICIsIFIkbl9zb20sICIgZGUgc29tYnJhLiBFbCBJQyBkZWwgYm9vdHN0cmFwIGVzIHBlcmNlbnRpbDsgbG9zIGRlbcOhcyBzb24gPGk+dDwvaT4gKFdlbGNoIG8gU2F0dGVydGh3YWl0ZSkuIikpKQ0KdGFibGEodGIsIGFsaWduID0gImxycnJyIikNCmJ0X3R4dCA8LSBpZiAoIWlzLm51bGwoUiRib290KSkgcGFzdGUwKCJFbCBib290c3RyYXAgamVyw6FycXVpY28gc29sbyBkaXNwb25lIGRlICIsIFIkYm9vdF9udW5pcSwgIiBjb21iaW5hY2lvbmVzIGRpc3RpbnRhcyBkZSDDoXJib2xlcywgcG9yIGxvIHF1ZSBzdSBpbnRlcnZhbG8gZGVzY3JpYmUgbGEgaW5lc3RhYmlsaWRhZCBkZWwgcmVzdWx0YWRvIG3DoXMgcXVlIHVuYSBpbmZlcmVuY2lhIGZpYWJsZS4iKSBlbHNlICIiDQpSJHR4dF9iYXQgPC0gaWYgKGlzLm5hKGJBJHBfd2VsY2gpKSAiQ29uIGxvcyDDoXJib2xlcyBkaXNwb25pYmxlcyBubyBlcyBwb3NpYmxlIGVzdGltYXIgdW4gY29udHJhc3RlIGluZmVyZW5jaWFsLiIgZWxzZSBwYXN0ZTAoDQogICJFbiBwcm9tZWRpbywgbGFzIGhvamFzIGRlIGxvcyDDoXJib2xlcyBkZSBzb21icmEgbWlkaWVyb24gIiwgZngoUiRtX3NvbSwgMSksICIgY23CsiB5IGxhcyBkZSBzb2wsICIsIGZ4KFIkbV9zb2wsIDEpLCAiIGNtwrIgKGRpZmVyZW5jaWEgPSAiLCBmeChSJGRpZl9jbSwgMSksICIgY23CsikuIEVuIHJhesOzbiBkZSB0YW1hw7FvcyBzb21icmEvc29sLCAiLCBmeChiQSRyYXpvbiwgMiksICIgKElDIDk1ICU6ICIsIGZ4KGJBJGxpLCAyKSwgIuKAkyIsIGZ4KGJBJGxzLCAyKSwNCiAgIjsgIiwgZnBwKGJBJHBfd2VsY2gpLCAiOyB0YW1hw7FvIGRlbCBlZmVjdG8gKmcqIGRlIEhlZGdlcyA9ICIsIGZ4KGJBJGcsIDIpLCAiKS4gIiwgUiRmcmFzZV9oMSwgIiAiLA0KICBpZiAoUiRub19hbGNhbnphKSBwYXN0ZTAoIkFkZW3DoXMsIGNvbiAiLCBSJG5fc29sLCAiIHkgIiwgUiRuX3NvbSwgIiDDoXJib2xlcyBzb2xvIGhheSAiLCBiQSRwZXJtJG5fcmVwLCAiIHJlcGFydG9zIHBvc2libGVzIGRlIGxhcyBldGlxdWV0YXMgc29sL3NvbWJyYSwgZGUgbW9kbyBxdWUgZWwgbWVub3IgdmFsb3IgZGUgKnAqIHF1ZSBzZSBwb2Ryw61hIG9idGVuZXIgZXMgIiwgUiRwbWluX3R4dCwgIjogKiplc3RlIGRpc2XDsW8gbm8gcHVlZGUgYWxjYW56YXIgc2lnbmlmaWNhY2nDs24gYWwgNSAlLCBzZWFuIGN1YWxlcyBzZWFuIGxvcyBkYXRvcyoqLiAiKSBlbHNlDQogICAgcGFzdGUwKCJMYSBwcnVlYmEgZGUgcGVybXV0YWNpw7NuIGV4YWN0YSBkYSAiLCBmcHAoYkEkcF9wZXJtKSwgIi4gIiksIGJ0X3R4dCkNCmBgYA0KDQpgciBSJHR4dF9iYXRgDQoNCmBgYHtyIGZpZ19wZXJtLCBmaWcuaGVpZ2h0PTMuMiwgZmlnLmNhcD1mY2FwKCJwZXJtIiwgIkRpc3RyaWJ1Y2nDs24gZGUgcGVybXV0YWNpw7NuIGV4YWN0YSBkZSBsYSByYXrDs24gc29tYnJhL3NvbCIsICJDYWRhIHB1bnRvIGVzIHVuIHJlcGFydG8gcG9zaWJsZSBkZSBsYXMgZXRpcXVldGFzICpzb2wqIHkgKnNvbWJyYSogZW50cmUgbG9zIMOhcmJvbGVzIGFuYWxpemFkb3M7IGxhIGzDrW5lYSBhenVsIGVzIGVsIHJlcGFydG8gb2JzZXJ2YWRvIHkgbGEgbMOtbmVhIHB1bnRlYWRhLCBsYSBhdXNlbmNpYSBkZSBlZmVjdG8gKHJhesOzbiA9IDEpLiBTaSBlbCBmYWN0b3Igbm8gaW1wb3J0YXJhLCB0b2RvcyBsb3MgcmVwYXJ0b3Mgc2Vyw61hbiBpZ3VhbG1lbnRlIHByb2JhYmxlcy4iKX0NCnBlIDwtIGJBJHBlcm0NCmlmICghaXMubnVsbChwZSkpIHsNCiAgZGZwIDwtIGRhdGEuZnJhbWUociA9IGV4cChwZSRkKSk7IGRmcCRrIDwtIHJvdW5kKGRmcCRyLCA0KTsgZGZwJHkgPC0gYXZlKGRmcCRrLCBkZnAkaywgRlVOID0gc2VxX2Fsb25nKQ0KICBnZ3Bsb3QoZGZwLCBhZXMociwgeSkpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAzKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGV4cChwZSRvYnMpLCBjb2xvdXIgPSBDT0xbInNvbWJyYSJdLCBsaW5ld2lkdGggPSAxKSArDQogICAgZ2VvbV9wb2ludChzaXplID0gNC4yLCBzaGFwZSA9IDIxLCBmaWxsID0gImdyZXk4NSIsIGNvbG91ciA9ICJncmV5MzAiKSArDQogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gZXhwKHBlJG9icyksIHkgPSBtYXgoZGZwJHkpICsgLjcsIGxhYmVsID0gIm9ic2VydmFkbyIsIGNvbG91ciA9IENPTFsic29tYnJhIl0sIHNpemUgPSAzLjMsIGhqdXN0ID0gLS4xKSArDQogICAgc2NhbGVfeF9sb2cxMCgpICsgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihhZGQgPSBjKC41LCAxKSkpICsNCiAgICBsYWJzKHggPSAiUmF6w7NuIGRlIG1lZGlhcyBnZW9tw6l0cmljYXMgc29tYnJhL3NvbCAoZXNjYWxhIGxvZykiLCB5ID0gIlJlcGFydG9zIikgKyB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpKQ0KfQ0KYGBgDQoNCmBgYHtyIGZpZ19mb3Jlc3QsIGZpZy5oZWlnaHQ9My45LCBmaWcuY2FwPWZjYXAoImZvcmVzdCIsICJMYSByYXrDs24gc29tYnJhL3NvbCBzZWfDum4gZWwgbcOpdG9kbyB5IGxhIGJhc2UgZGUgZGF0b3MiLCAiUHVudG9zOiBlc3RpbWFjaW9uZXM7IGJhcnJhczogaW50ZXJ2YWxvcyBkZSBjb25maWFuemEgZGUgOTUgJSAoZXNjYWxhIGxvZ2Fyw610bWljYSkuICoqQSoqLCDDoXJlYXMgbWVkaWRhcywgY29uIGVsIMOhcmJvbCBjb21vIHVuaWRhZDsgKipCKiosIMOhcmVhIGRlbCBtYXJjbyBkZSBsYXMgaG9qYXM7ICoqQyoqIChzb2xvIHNpIGh1Ym8gw6FyZWFzIHBlbmRpZW50ZXMpLCDDoXJlYXMgbWVkaWRhcyBtw6FzIGxhcyBwZW5kaWVudGVzIGNvbXBsZXRhZGFzIGNvbiBlbCBtb2RlbG8gZGVsIG1hcmNvLiBFbiByb2pvLCBlbCBhbsOhbGlzaXMgY29uIGhvamFzIGNvbW8gcsOpcGxpY2FzIChpbmNvcnJlY3RvKS4gVW5hIHJhesOzbiBkZSAxIHNpZ25pZmljYSBhdXNlbmNpYSBkZSBlZmVjdG8uIil9DQpmciA8LSBkYXRhLmZyYW1lKGxhYmVsID0gY2hhcmFjdGVyKCksIGVzdCA9IG51bWVyaWMoKSwgbG8gPSBudW1lcmljKCksIGhpID0gbnVtZXJpYygpLCB0aXBvID0gY2hhcmFjdGVyKCksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCmFkZGYgPC0gZnVuY3Rpb24obCwgZSwgbG8sIGhpLCB0KSBpZiAoIWlzLm51bGwoZSkgJiYgbGVuZ3RoKGUpID09IDEgJiYgIWlzLm5hKGUpKSBmciA8PC0gcmJpbmQoZnIsIGRhdGEuZnJhbWUobGFiZWwgPSBsLCBlc3QgPSBlLCBsbyA9IGxvLCBoaSA9IGhpLCB0aXBvID0gdCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSkNCmFkZGYoIkEgwrcgV2VsY2ggc29icmUgcHJvbWVkaW9zIGRlIMOhcmJvbCIsIGJBJHJhem9uLCBiQSRsaSwgYkEkbHMsICJjb3JyZWN0byIpDQppZiAoIWlzLm51bGwoUiRtaXgpKSBhZGRmKCJBIMK3IE1vZGVsbyBtaXh0byAow6FyYm9sIGFsZWF0b3JpbykiLCBSJG1peCRyYXpvbiwgUiRtaXgkbGksIFIkbWl4JGxzLCAiY29ycmVjdG8iKQ0KaWYgKCFpcy5udWxsKFIkYm9vdCkpIGFkZGYoIkEgwrcgQm9vdHN0cmFwIGplcsOhcnF1aWNvIiwgZXhwKG1lZGlhbihSJGJvb3QpKSwgUiRib290X2NpWzFdLCBSJGJvb3RfY2lbMl0sICJjb3JyZWN0byIpDQphZGRmKCJCIMK3IE1hcmNvIGRlIHRvZGFzIGxhcyBob2phcyIsIGJCJHJhem9uLCBiQiRsaSwgYkIkbHMsICJjb3JyZWN0byIpDQppZiAoUiRuX2ltcCA+IDApIGFkZGYoIkMgwrcgTWVkaWRhcyArIGNvbXBsZXRhZGFzIiwgYkMkcmF6b24sIGJDJGxpLCBiQyRscywgImNvcnJlY3RvIikNCmlmICghaXMubnVsbChSJHBzZXVkbykpIGFkZGYoIkhvamFzIGNvbW8gcsOpcGxpY2FzIChpbmNvcnJlY3RvKSIsIFIkcHNldWRvJHJhem9uLCBSJHBzZXVkbyRsaSwgUiRwc2V1ZG8kbHMsICJpbmNvcnJlY3RvIikNCmlmIChucm93KGZyKSA+IDApIHsNCiAgZnIkbGFiZWwgPC0gZmFjdG9yKGZyJGxhYmVsLCBsZXZlbHMgPSByZXYoZnIkbGFiZWwpKQ0KICBnZ3Bsb3QoZnIsIGFlcyhlc3QsIGxhYmVsLCBjb2xvdXIgPSB0aXBvKSkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJncmV5NTAiKSArDQogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gbG8sIHhlbmQgPSBoaSwgeWVuZCA9IGxhYmVsKSwgbGluZXdpZHRoID0gMSwgbmEucm0gPSBUUlVFKSArIGdlb21fcG9pbnQoc2l6ZSA9IDMuNCkgKw0KICAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYyhjb3JyZWN0byA9ICIjMDA3MkIyIiwgaW5jb3JyZWN0byA9ICIjRDU1RTAwIiksIGd1aWRlID0gIm5vbmUiKSArDQogICAgc2NhbGVfeF9sb2cxMChicmVha3MgPSBjKC4yNSwgLjUsIDEsIDIsIDQsIDgpKSArIGxhYnMoeCA9ICJSYXrDs24gZGUgw6FyZWFzIHNvbWJyYS9zb2wgKGVzY2FsYSBsb2cpIiwgeSA9IE5VTEwpDQp9DQpgYGANCg0KIyMgTW9kZWxvIG1peHRvIHkgQU5PVkEgYW5pZGFkbw0KDQpFbCBtb2RlbG8gbWl4dG8gY29tcGFyYSBsYSBleHBvc2ljacOzbiB1c2FuZG8gdG9kYXMgbGFzIGhvamFzLCBwZXJvIHJlc3BldGFuZG8gcXVlIGNhZGEgaG9qYSBwZXJ0ZW5lY2UgYSB1biDDoXJib2w6IGVsIHRhbWHDsW8gZGUgbGEgaG9qYSBkZXBlbmRlIGRlIGxhIGV4cG9zaWNpw7NuIChlZmVjdG8gZmlqbykgeSBkZSB1biBlZmVjdG8gcHJvcGlvIGRlIGNhZGEgw6FyYm9sIChlZmVjdG8gYWxlYXRvcmlvKS4gRXMgZWwgZXF1aXZhbGVudGUgbW9kZXJubyBkZWwgQU5PVkEgYW5pZGFkbyB5LCBjb24gZGF0b3MgZGVzYmFsYW5jZWFkb3MgKGRpc3RpbnRvIG7Dum1lcm8gZGUgaG9qYXMgcG9yIMOhcmJvbCwgY29tbyBhcXXDrSksIGVzIHByZWZlcmlibGUuIGByIGlmIChIQVNfTE1FUikgIiIgZWxzZSAiKipFbCBwYXF1ZXRlIGxtZTQvbG1lclRlc3Qgbm8gZXN0w6EgZGlzcG9uaWJsZTsgc2UgbXVlc3RyYSBzb2xvIGVsIEFOT1ZBIGFuaWRhZG8uKioiYA0KDQpgYGB7ciB0YWJfbWl4dG8sIHJlc3VsdHM9J2FzaXMnfQ0KaWYgKCFpcy5udWxsKFIkbWl4KSkgew0KICBteCA8LSBSJG1peA0KICB0MSA8LSBkYXRhLmZyYW1lKA0KICAgIE1lZGlkYSA9IGMoIlJhesOzbiBkZSDDoXJlYXMgc29tYnJhL3NvbCIsICJWYXJpYWNpw7NuIGV4cGxpY2FkYSBwb3IgbGEgZXhwb3NpY2nDs24iLCAiVmFyaWFjacOzbiBkZWJpZGEgYSBkaWZlcmVuY2lhcyBlbnRyZSDDoXJib2xlcyIsICJWYXJpYWNpw7NuIGVudHJlIGhvamFzIGRlbCBtaXNtbyDDoXJib2wiLCAiwr9EaWZpZXJlbiBsb3Mgw6FyYm9sZXMgZW50cmUgc8OtPyIpLA0KICAgIFZhbG9yID0gYyhwYXN0ZTAoZngobXgkcmF6b24sIDIpLCAiICIsIGZjaShteCRsaSwgbXgkbHMpLCAiOyAiLCBnc3ViKCJcXCoiLCAiIiwgZnBwKG14JHApKSksDQogICAgICAgICAgICAgIHBhc3RlMChmeCgxMDAgKiBteCRyMm0sIDApLCAiICUiKSwgcGFzdGUwKGZ4KDEwMCAqIChteCRyMmMgLSBteCRyMm0pLCAwKSwgIiAlIiksIHBhc3RlMChmeCgxMDAgKiAoMSAtIG14JHIyYyksIDApLCAiICUiKSwNCiAgICAgICAgICAgICAgZ3N1YigiXFwqIiwgIiIsIGZwcChteCRwX3JhbmVmKSkpLA0KICAgIGBRdcOpIHNpZ25pZmljYWAgPSBjKCJDdcOhbnRhcyB2ZWNlcyBlcyBtYXlvciAoPiAxKSBvIG1lbm9yICg8IDEpIGxhIGhvamEgZGUgc29tYnJhIHJlc3BlY3RvIGRlIGxhIGRlIHNvbDsgMSA9IHNpbiBkaWZlcmVuY2lhLiBFbnRyZSBjb3JjaGV0ZXMsIElDIDk1ICUuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJQYXJ0ZSBkZSBsYSB2YXJpYWNpw7NuIHRvdGFsIGRlbCB0YW1hw7FvIGRlIGxhcyBob2phcyBxdWUgc2UgZXhwbGljYSBzb2xvIHBvciBzb2wgbyBzb21icmEuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJQYXJ0ZSBkZSBsYSB2YXJpYWNpw7NuIHRvdGFsIGRlYmlkYSBhIHF1ZSB1bm9zIMOhcmJvbGVzIHRpZW5lbiBob2phcyBtw6FzIGdyYW5kZXMgcXVlIG90cm9zLCBhZGVtw6FzIGRlIGxvIHF1ZSBleHBsaWNhIGxhIGV4cG9zaWNpw7NuLiIsDQogICAgICAgICAgICAgICAgICAgICAgICAiUGFydGUgZGUgbGEgdmFyaWFjacOzbiB0b3RhbCBxdWUgY29ycmVzcG9uZGUgYSBkaWZlcmVuY2lhcyBlbnRyZSBob2phcyBkZSB1biBtaXNtbyDDoXJib2wuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiUHJ1ZWJhIGRlIHF1ZSBsYSB2YXJpYWNpw7NuIGVudHJlIMOhcmJvbGVzIGVzIG1heW9yIHF1ZSBjZXJvLiIsIGlmZWxzZShteCRzaW5ndWxhciwgIiBBanVzdGUgc2luZ3VsYXI6IGxhIHZhcmlhY2nDs24gZW50cmUgw6FyYm9sZXMgZXN0aW1hZGEgZXMg4omIIDAuIiwgIiIpKSksDQogICAgY2hlY2submFtZXMgPSBGQUxTRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KICBjYXQodGNhcCgibWl4dG8iLCAiTW9kZWxvIG1peHRvOiByYXrDs24gc29tYnJhL3NvbCB5IHJlcGFydG8gZGUgbGEgdmFyaWFjacOzbiBkZWwgdGFtYcOxbyBkZSBsYSBob2phIiwgIkVzdGltYWRvIGNvbiB0b2RhcyBsYXMgaG9qYXMgeSBlbCDDoXJib2wgY29tbyBlZmVjdG8gYWxlYXRvcmlvIChSRU1MOyBnbCBkZSBTYXR0ZXJ0aHdhaXRlKS4gRWwgbW9kZWxvIHNlIGFqdXN0YSBlbiBlc2NhbGEgbG9nYXLDrXRtaWNhLCBwZXJvIGFxdcOtIGxhIHJhesOzbiBzZSBleHByZXNhIGVuIGxhIGVzY2FsYSBvcmlnaW5hbC4gTG9zIHRyZXMgcG9yY2VudGFqZXMgc3VtYW4gMTAwICUgKHNhbHZvIHJlZG9uZGVvKS4iKSkNCiAgdGFibGEodDEsIGFsaWduID0gImxsbCIpDQp9IGVsc2UgY2F0KCI8cD48aT5Nb2RlbG8gbWl4dG8gbm8gZGlzcG9uaWJsZSAoZmFsdGFuIHBhcXVldGVzIG8gw6FyYm9sZXMpLjwvaT48L3A+IikNCmBgYA0KDQpgYGB7ciB0YWJfYW5vdmEsIHJlc3VsdHM9J2FzaXMnfQ0KaWYgKCFpcy5udWxsKFIkbmVzdGVkKSkgew0KICBhbiA8LSBSJG5lc3RlZCRhbg0KICB0MiA8LSBkYXRhLmZyYW1lKGBGdWVudGUgZGUgdmFyaWFjacOzbmAgPSBjKCJFeHBvc2ljacOzbiIsICLDgXJib2wgKGRlbnRybyBkZSBleHBvc2ljacOzbikiLCAiSG9qYXMgKHJlc2lkdWFsKSIpLCBgZ2xgID0gYW4kRGYsIGBTdW1hIGRlIGN1YWRyYWRvc2AgPSBmeChhbiRgU3VtIFNxYCwgMyksIGBDdWFkcmFkbyBtZWRpb2AgPSBmeChhbiRgTWVhbiBTcWAsIDMpLA0KICAgICAgICAgICAgICAgICAgIGBTZSBwcnVlYmEgY29udHJhYCA9IGMoIkNNIGRlIMOhcmJvbCIsICJDTSBkZSBob2phcyIsICIiKSwgYEZgID0gYyhmeChSJG5lc3RlZCRGZSwgMiksIGZ4KFIkbmVzdGVkJEZhLCAyKSwgIiIpLCBgVmFsb3IgZGUgcGAgPSBjKGZwKFIkbmVzdGVkJHBlKSwgZnAoUiRuZXN0ZWQkcGEpLCAiIiksIGNoZWNrLm5hbWVzID0gRkFMU0UsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCiAgY2F0KHRjYXAoImFub3ZhIiwgIkFOT1ZBIGFuaWRhZG86IGhvamFzIGRlbnRybyBkZSDDoXJib2xlcyBkZW50cm8gZGUgZXhwb3NpY2nDs24iLCAiQW7DoWxpc2lzIGVuIGVzY2FsYSBsb2dhcsOtdG1pY2EuIExhIGV4cG9zaWNpw7NuIHNlIHBydWViYSBjb250cmEgZWwgY3VhZHJhZG8gbWVkaW8gZGUgw6FyYm9sLCBxdWUgZXMgc3UgZXJyb3IgZXhwZXJpbWVudGFsIGNvcnJlY3RvLiBDb24gbsO6bWVybyBkZXNpZ3VhbCBkZSBob2phcyBwb3Igw6FyYm9sIGxhIHBhcnRpY2nDs24gc2VjdWVuY2lhbCBlcyBhcHJveGltYWRhOyBlbCBtb2RlbG8gbWl4dG8gZXMgbGEgcmVmZXJlbmNpYS4iKSkNCiAgdGFibGEodDIsIGFsaWduID0gImxycnJscnIiKQ0KICBSJHR4dF9uZXN0ZWQgPC0gcGFzdGUwKCJFbCBBTk9WQSBhbmlkYWRvIGRhIGVsIG1pc21vIG1lbnNhamU6IGxhIGV4cG9zaWNpw7NuICIsIGlmZWxzZShSJG5lc3RlZCRwZSA8IDAuMDUsICJ0aWVuZSB1biBlZmVjdG8gZGV0ZWN0YWJsZSIsICJubyB0aWVuZSB1biBlZmVjdG8gZGV0ZWN0YWJsZSIpLCAiICgqRiooMTsgIiwgYW4kRGZbMl0sICIpID0gIiwgZngoUiRuZXN0ZWQkRmUsIDIpLCAiOyAiLCBmcHAoUiRuZXN0ZWQkcGUpLCAiKSB5IGxvcyDDoXJib2xlcyBkZSB1bmEgbWlzbWEgZXhwb3NpY2nDs24gIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUiRuZXN0ZWQkcGEgPCAwLjA1LCAic8OtIGRpZmllcmVuIGVudHJlIHPDrSIsICJubyBkaWZpZXJlbiBkZSBmb3JtYSBkZXRlY3RhYmxlIiksICIgKCIsIGZwcChSJG5lc3RlZCRwYSksICIpLiAiKQ0KfSBlbHNlIHsgY2F0KCI8cD48aT5BTk9WQSBhbmlkYWRvIG5vIGRpc3BvbmlibGUgKHNlIHJlcXVpZXJlbiBhbCBtZW5vcyAzIMOhcmJvbGVzIHkgbGFzIGRvcyBleHBvc2ljaW9uZXMpLjwvaT48L3A+Iik7IFIkdHh0X25lc3RlZCA8LSAiIiB9DQpSJHR4dF9taXggPC0gaWYgKCFpcy5udWxsKFIkbWl4KSkgcGFzdGUwKCJFbCBtb2RlbG8gbWl4dG8gZXN0aW1hIHVuYSByYXrDs24gc29tYnJhL3NvbCBkZSAiLCBmeChSJG1peCRyYXpvbiwgMiksICIgKElDIDk1ICU6ICIsIGZ4KFIkbWl4JGxpLCAyKSwgIuKAkyIsIGZ4KFIkbWl4JGxzLCAyKSwgIjsgIiwgZnBwKFIkbWl4JHApLA0KICAiKS4gTGEgZXhwb3NpY2nDs24gZXhwbGljYSBzb2xvIGVsICIsIGZ4KDEwMCAqIFIkbWl4JHIybSwgMCksICIgJSBkZSBsYSB2YXJpYWNpw7NuIGRlbCB0YW1hw7FvIGRlIGxhcyBob2phczsgbGFzIGRpZmVyZW5jaWFzIGVudHJlIMOhcmJvbGVzLCBlbCAiLCBmeCgxMDAgKiAoUiRtaXgkcjJjIC0gUiRtaXgkcjJtKSwgMCksICIgJTsgeSBlbCAiLCBmeCgxMDAgKiAoMSAtIFIkbWl4JHIyYyksIDApLCAiICUgcmVzdGFudGUgY29ycmVzcG9uZGUgYSBkaWZlcmVuY2lhcyBlbnRyZSBob2phcyBkZWwgbWlzbW8gw6FyYm9sICgiLCB0cmVmKCJtaXh0byIpLCAiKS4gIikgZWxzZSAiIg0KYGBgDQoNCmByIFIkdHh0X21peGAgYHIgUiR0eHRfbmVzdGVkYCBDb21vIGxhIGV4cG9zaWNpw7NuIHNlIGFzaWduw7MgYSDDoXJib2xlcyB5IG5vIGEgaG9qYXMsIGVsIGNvbnRyYXN0ZSBkZXBlbmRlIGRlbCBuw7ptZXJvIGRlIMOhcmJvbGVzOyBwb3IgZXNvIGxvcyBpbnRlcnZhbG9zIHNvbiBhbmNob3MgYXVucXVlIGhheWEgbXVjaGFzIGhvamFzLiBBIGNvbnRpbnVhY2nDs24gc2UgcmV2aXNhbiBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8gKGByIGZyZWYoImRpYWciKWApLg0KDQpgYGB7ciBmaWdfZGlhZywgZmlnLmhlaWdodD0zLjQsIGZpZy5jYXA9ZmNhcCgiZGlhZyIsICJEaWFnbsOzc3RpY28gZGVsIG1vZGVsbyIsICIqKmEqKiwgUmVzaWR1b3MgZnJlbnRlIGEgdmFsb3JlcyBhanVzdGFkb3M6IG5vIGRlYmVyw61hIHZlcnNlIG5pbmfDum4gcGF0csOzbi4gKipiKiosIEdyw6FmaWNvIGN1YW50aWzigJNjdWFudGlsIGRlIGxvcyByZXNpZHVvczogbG9zIHB1bnRvcyBkZWJlcsOtYW4gc2VndWlyIGxhIGzDrW5lYS4gTG9zIHJlc2lkdW9zIGRlbCBtb2RlbG8gbWl4dG8gc29uIGxvcyBjb25kaWNpb25hbGVzLiIpfQ0KbW0gPC0gTlVMTA0KaWYgKCFpcy5udWxsKFIkbWl4KSkgbW0gPC0gUiRtaXgkbSBlbHNlIGlmIChleGlzdHMoIm1fbmVzdCIpKSBtbSA8LSBtX25lc3QNCmlmICghaXMubnVsbChtbSkpIHsNCiAgZGQzIDwtIGRhdGEuZnJhbWUoZSA9IGFzLm51bWVyaWMocmVzaWQobW0pKSwgZiA9IGFzLm51bWVyaWMoZml0dGVkKG1tKSksIGFyYm9sID0gbGltQSRhcmJvbCwgZXhwbyA9IGxpbUEkZXhwb3NpY2lvbikNCiAgcDEgPC0gZ2dwbG90KGRkMywgYWVzKGYsIGUpKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMikgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gZXhwbyksIHNoYXBlID0gMjEsIHNpemUgPSAyLjIsIGNvbG91ciA9ICJncmV5MjAiLCBhbHBoYSA9IC44NSkgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IENPTCwgZ3VpZGUgPSAibm9uZSIpICsgbGFicyh4ID0gIlZhbG9yIGFqdXN0YWRvIiwgeSA9ICJSZXNpZHVvIikNCiAgcDIgPC0gZ2dwbG90KGRkMywgYWVzKHNhbXBsZSA9IGUpKSArIHN0YXRfcXFfbGluZShjb2xvdXIgPSAiZ3JleTQwIikgKyBzdGF0X3FxKHNpemUgPSAxLjgsIGFscGhhID0gLjgpICsgbGFicyh4ID0gIkN1YW50aWxlcyB0ZcOzcmljb3MiLCB5ID0gIkN1YW50aWxlcyBkZSBsb3MgcmVzaWR1b3MiKQ0KICBwMSArIHAyICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQp9DQpgYGANCg0KYGBge3IgY2FsY19zdXAsIGluY2x1ZGU9RkFMU0V9DQpSJHR4dF9zdXAgPC0gaWYgKCFpcy5udWxsKFIkc3VwKSkgew0KICBva19uIDwtIFIkc3VwJHNoX3AgPj0gMC4wNTsgb2tfdiA8LSBSJHN1cCRmbF9wID49IDAuMDUNCiAgcGFzdGUwKCJFbiBlbCBkaWFnbsOzc3RpY28gZGVsIG1vZGVsbyAoIiwgZnJlZigiZGlhZyIpLCAiKSAiLCBpZmVsc2Uob2tfbiwgImxvcyByZXNpZHVvcyBzb24gY29tcGF0aWJsZXMgY29uIHVuYSBkaXN0cmlidWNpw7NuIG5vcm1hbCIsICJsb3MgcmVzaWR1b3Mgc2UgYXBhcnRhbiBkZSBsYSBub3JtYWxpZGFkIiksDQogICAgIiAoU2hhcGlyb+KAk1dpbGssICIsIGZwcChSJHN1cCRzaF9wKSwgIikiLCBjaXRlKCJzaGFwaXJvMTk2NSIpLCAiIHkgIiwgaWZlbHNlKG9rX3YsICJsYSB2YXJpYWNpw7NuIGVzIHNpbWlsYXIgZW50cmUgw6FyYm9sZXMiLCAibGEgdmFyaWFjacOzbiBkaWZpZXJlIGVudHJlIMOhcmJvbGVzIiksICIgKEZsaWduZXLigJNLaWxsZWVuLCAiLCBmcHAoUiRzdXAkZmxfcCksICIpIiwgY2l0ZSgiZmxpZ25lcjE5NzYiKSwgIi4gIiwNCiAgICAiTGFzIHBydWViYXMgcXVlIG5vIGRlcGVuZGVuIGRlIGVzb3Mgc3VwdWVzdG9zIChBTk9WQSBkZSBXZWxjaCB5IEtydXNrYWzigJNXYWxsaXMpIiwgY2l0ZSgid2VsY2gxOTQ3IiwgImtydXNrYWwxOTUyIiksDQogICAgaWZlbHNlKChSJHN1cCR3ZWxjaF9wIDwgMC4wNSkgPT0gKFIkaWNjJHAgPCAwLjA1KSAmJiAoUiRzdXAka3dfcCA8IDAuMDUpID09IChSJGljYyRwIDwgMC4wNSksICIgbGxldmFuIGEgbGEgbWlzbWEgY29uY2x1c2nDs24gcXVlIGVsIEFOT1ZBIiwgIiBubyBjb2luY2lkZW4gZGVsIHRvZG8gY29uIGVsIEFOT1ZBIiksDQogICAgIiAoIiwgZnBwKFIkc3VwJHdlbGNoX3ApLCAiIHkgIiwgZnBwKFIkc3VwJGt3X3ApLCAiLCByZXNwZWN0aXZhbWVudGUpLiBDb24gcG9jYXMgaG9qYXMgcG9yIMOhcmJvbCBlc3RhcyBwcnVlYmFzIGRldGVjdGFuIHBvY28sIHBvciBlc28gc2UgaW50ZXJwcmV0YSBzaWVtcHJlIGVsIGdyw6FmaWNvLiIpDQp9IGVsc2UgIiINCmBgYA0KDQpgciBSJHR4dF9zdXBgDQoNCiMjIERpZmVyZW5jaWFzIGVudHJlIMOhcmJvbGVzOiBBTk9WQSB5IGNvbXBhcmFjaW9uZXMgbcO6bHRpcGxlcyBkZSBUdWtleQ0KDQpgciBpZiAoIWlzLm51bGwoUiR0aykpIHBhc3RlMCgiQ29uICIsIG5sZXZlbHMobGltQSRhcmJvbF9mKSwgIiDDoXJib2xlcyBoYXkgIiwgUiR0a19uLCAiIGNvbXBhcmFjaW9uZXMgcG9yIHBhcmVzLiBIYWNlciB0YW50YXMgcHJ1ZWJhcyBzdWVsdGFzIGFsIDUgJSBlbGV2YXLDrWEgbGEgcHJvYmFiaWxpZGFkIGRlIGFsZ8O6biBmYWxzbyBwb3NpdGl2byBhIOKJiCAiLCBmeCgxMDAgKiAoMSAtIDAuOTVeUiR0a19uKSwgMCksICIgJSwgcG9yIGxvIHF1ZSBzZSB1c8OzIGxhIHBydWViYSBIU0QgZGUgVHVrZXksIiwgY2l0ZSgidHVrZXkxOTQ5IiksICIgcXVlIGNvbnRyb2xhIGVsIGVycm9yIGRlbCBjb25qdW50bywgY29udHJhc3RhZGEgY29uIHBydWViYXMgZGUgV2VsY2ggcG9yIHBhcmVzIGNvbiBhanVzdGUgZGUgSG9sbS4iLCBjaXRlKCJob2xtMTk3OSIpLCAiIExvcyDDoXJib2xlcyBkaWZpZXJlbiBlbiAiLCBSJHRrX25zaWcsICIgZGUgIiwgUiR0a19uLCAiIHBhcmVzICgiLCB0cmVmKCJ0dWtleSIpLCAiLCAiLCBmcmVmKCJ0dWtleSIpLCAiKSwgeSBlbiAiLCBSJHRrX21pc21hX3NpZywgIiBkZSAiLCBSJHRrX21pc21hX24sICIgcGFyZXMgZGUgw6FyYm9sZXMgZGUgbGEgKiptaXNtYSBleHBvc2ljacOzbioqLiBFcyBkZWNpciwgZG9zIMOhcmJvbGVzIGNvbiBsYSBtaXNtYSBleHBvc2ljacOzbiBwdWVkZW4gZGlmZXJpciB0YW50byBjb21vIHVubyBkZSBzb2wgeSB1bm8gZGUgc29tYnJhOiBlc2EgdmFyaWFjacOzbiBlbnRyZSDDoXJib2xlcyBlcyBlbCBydWlkbyBmcmVudGUgYWwgY3VhbCBkZWJlIGNvbXBldGlyIGVsIGVmZWN0byBkZSBsYSBleHBvc2ljacOzbi4iKSBlbHNlICJObyBoYXkgc3VmaWNpZW50ZXMgw6FyYm9sZXMgKOKJpSAzLCBjYWRhIHVubyBjb24gdmFyaWFzIGhvamFzIG1lZGlkYXMpIHBhcmEgY29tcGFyYWNpb25lcyBtw7psdGlwbGVzLiJgDQoNCmBgYHtyIHRhYl90dWtleSwgcmVzdWx0cz0nYXNpcyd9DQppZiAoIWlzLm51bGwoUiR0aykpIHsNCiAgdGsgPC0gUiR0aw0KICB0MyA8LSBkYXRhLmZyYW1lKGBDb21wYXJhY2nDs24gKEEgLyBCKWAgPSB0ayRjb21wYXJhY2lvbiwgYE1pc21hIGV4cG9zaWNpw7NuYCA9IGlmZWxzZSh0ayRtaXNtYSwgInPDrSIsICJubyIpLCBgUmF6w7NuIEEvQmAgPSBmeCh0ayRyYXpvbiwgMiksIGBJQyA5NSAlIChUdWtleSlgID0gZmNpKHRrJGxpLCB0ayRscyksDQogICAgICAgICAgICAgICAgICAgYHAgYWp1c3RhZG8gKFR1a2V5KWAgPSBmcCh0ayRwKSwgYHAgYWp1c3RhZG8gKFdlbGNoICsgSG9sbSlgID0gZnAodGskcF93ZWxjaF9ob2xtKSwgYERpZmllcmVuICg1ICUpYCA9IGlmZWxzZSh0ayRwIDwgMC4wNSwgInPDrSIsICJubyIpLCBjaGVjay5uYW1lcyA9IEZBTFNFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQogIGNhdCh0Y2FwKCJ0dWtleSIsICJDb21wYXJhY2lvbmVzIHBvciBwYXJlcyBlbnRyZSDDoXJib2xlcyIsICJFc2NhbGEgbG9nYXLDrXRtaWNhLCBtb3N0cmFkYXMgY29tbyByYXpvbmVzIGRlIMOhcmVhcyAoQSByZXNwZWN0byBkZSBCKS4iKSkNCiAgdGFibGEodDMsIGFsaWduID0gImxjcnJycmMiKQ0KfQ0KYGBgDQoNCmBgYHtyIGZpZ190dWtleSwgZmlnLmhlaWdodD00LjIsIGZpZy5jYXA9ZmNhcCgidHVrZXkiLCAiUmF6w7NuIGRlIMOhcmVhcyBlbnRyZSBwYXJlcyBkZSDDoXJib2xlcyIsICJSYXrDs24gY29uIHN1IGludGVydmFsbyBIU0QgZGUgVHVrZXkgKGVzY2FsYSBsb2cpLiBTaSBlbCBpbnRlcnZhbG8gY3J1emEgMSwgbm8gaGF5IGRpZmVyZW5jaWEgZGV0ZWN0YWJsZS4gQ8OtcmN1bG9zIHJlbGxlbm9zOiDDoXJib2xlcyBkZSBsYSBtaXNtYSBleHBvc2ljacOzbjsgY8OtcmN1bG9zIHZhY8Otb3M6IGV4cG9zaWNpb25lcyBkaXN0aW50YXMuIFJvam86IGRpZmVyZW5jaWEgZGV0ZWN0YWJsZSBhbCA1ICUuIil9DQppZiAoIWlzLm51bGwoUiR0aykpIHsNCiAgdGsgPC0gUiR0azsgdGskeSA8LSBmYWN0b3IodGskY29tcGFyYWNpb24sIGxldmVscyA9IHJldih0ayRjb21wYXJhY2lvbikpOyB0ayRzaWcgPC0gaWZlbHNlKHRrJHAgPCAwLjA1LCAic8OtIiwgIm5vIikNCiAgZ2dwbG90KHRrLCBhZXMocmF6b24sIHksIGNvbG91ciA9IHNpZykpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiZ3JleTUwIikgKw0KICAgIGdlb21fc2VnbWVudChhZXMoeCA9IGxpLCB4ZW5kID0gbHMsIHllbmQgPSB5KSwgbGluZXdpZHRoID0gLjkpICsNCiAgICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IG1pc21hKSwgc2l6ZSA9IDMuMiwgZmlsbCA9ICJ3aGl0ZSIsIHN0cm9rZSA9IDEpICsNCiAgICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYyhgVFJVRWAgPSAxNiwgYEZBTFNFYCA9IDIxKSwgbGFiZWxzID0gYyhgVFJVRWAgPSAibWlzbWEgZXhwb3NpY2nDs24iLCBgRkFMU0VgID0gImV4cG9zaWNpw7NuIGRpc3RpbnRhIiksIG5hbWUgPSBOVUxMKSArDQogICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJzw60iID0gIiNENTVFMDAiLCAibm8iID0gImdyZXk0NSIpLCBndWlkZSA9ICJub25lIikgKyBzY2FsZV94X2xvZzEwKCkgKyBsYWJzKHggPSAiUmF6w7NuIGRlIMOhcmVhcyBBL0IgKGVzY2FsYSBsb2cpIiwgeSA9IE5VTEwpDQp9DQpgYGANCg0KIyMgUm9idXN0ZXogZnJlbnRlIGEgbGEgYmFzZSBkZSBkYXRvcyB5IGEgw6FyYm9sZXMgaW5kaXZpZHVhbGVzDQoNCmByIFIkdHh0X3JvYmANCg0KYGBge3IgdGFiX3NlbnMsIHJlc3VsdHM9J2FzaXMnfQ0KbWsgPC0gZnVuY3Rpb24obGFiLCBiLCBleHRyYSA9ICIiKSBjKGxhYiwgcGFzdGUwKGIkbl9zb2wsICIgLyAiLCBiJG5fc29tKSwgZngoYiRyYXpvbiwgMiksIGZjaShiJGxpLCBiJGxzKSwgZnAoYiRwX3dlbGNoKSwgZnAoYiRwX3dpbGNveCksIGZwKGIkcF9wZXJtKSkNCmZzIDwtIGxpc3QobWsoIkEgwrcgw4FyZWFzIG1lZGlkYXMiLCBiQSksIG1rKCJCIMK3IE1hcmNvIGRlIHRvZGFzIGxhcyBob2phcyIsIGJCKSkNCmlmIChSJG5faW1wID4gMCkgZnNbWzNdXSA8LSBtaygiQyDCtyBNZWRpZGFzICsgY29tcGxldGFkYXMiLCBiQykNCmlmICghaXMubnVsbChSJHNpbSkpIGZzW1tsZW5ndGgoZnMpICsgMV1dIDwtIGMoIkMgwrcgaW5jZXJ0aWR1bWJyZSBkZWwgY29tcGxldGFkbyAobWVkaWFuYSB5IHJhbmdvIDIsNeKAkzk3LDUgJSkiLCAi4oCUIiwgZngoUiRzaW1fcVsyXSwgMiksIGZjaShSJHNpbV9xWzFdLCBSJHNpbV9xWzNdKSwgIuKAlCIsICLigJQiLCAi4oCUIikNCmlmICghaXMubnVsbChSJGprKSkgZnNbW2xlbmd0aChmcykgKyAxXV0gPC0gYygiQSDCtyBkZWphbmRvIHVuIMOhcmJvbCBmdWVyYSAocmFuZ28pIiwgIuKAlCIsIHBhc3RlMChmeChSJGprX3JhbmdvWzFdLCAyKSwgIuKAkyIsIGZ4KFIkamtfcmFuZ29bMl0sIDIpKSwgIuKAlCIsICLigJQiLCAi4oCUIiwgIuKAlCIpDQp0cyA8LSBhcy5kYXRhLmZyYW1lKGRvLmNhbGwocmJpbmQsIGZzKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KbmFtZXModHMpIDwtIGMoIkJhc2UgZGUgZGF0b3MiLCAibiDDoXJib2xlcyAoc29sIC8gc29tYnJhKSIsICJSYXrDs24gc29tYnJhL3NvbCIsICJJQyA5NSAlIiwgInAgV2VsY2giLCAicCBXaWxjb3hvbiIsICJwIHBlcm11dGFjacOzbiIpDQpjYXQodGNhcCgic2VucyIsICJTZW5zaWJpbGlkYWQgZGVsIGNvbnRyYXN0ZSBzb2zigJNzb21icmEgYSBsYSBiYXNlIGRlIGRhdG9zIHkgYSDDoXJib2xlcyBpbmRpdmlkdWFsZXMiLCAiV2VsY2gsIFdpbGNveG9uIGV4YWN0YSB5IHBlcm11dGFjacOzbiBleGFjdGEgc29icmUgcHJvbWVkaW9zIGRlIMOhcmJvbCAoZXNjYWxhIGxvZyBwYXJhIGxhcyByYXpvbmVzKS4iKSkNCnRhYmxhKHRzLCBhbGlnbiA9ICJscnJycnJyIikNCmRpcnMgPC0gYyhiQSRyYXpvbiwgYkIkcmF6b24sIGlmIChSJG5faW1wID4gMCkgYkMkcmF6b24pOyBkaXJzIDwtIGRpcnNbIWlzLm5hKGRpcnMpXQ0KUiRjb25jb3JkIDwtIGxlbmd0aChkaXJzKSA+PSAyICYmIChhbGwoZGlycyA+IDEpIHx8IGFsbChkaXJzIDwgMSkpDQpSJHR4dF9zZW5zIDwtIHBhc3RlMCgiTGFzIGJhc2VzIGRlIGRhdG9zIGFuYWxpemFkYXMgIiwgaWYgKFIkY29uY29yZCkgcGFzdGUwKCJhcHVudGFuIGVuIGxhIG1pc21hIGRpcmVjY2nDs24gKCIsIGlmZWxzZShhbGwoZGlycyA+IDEpLCAiaG9qYXMgbWF5b3JlcyBlbiBzb21icmEiLCAiaG9qYXMgbWF5b3JlcyBlbiBzb2wiKSwgIikiKSBlbHNlICIqKm5vIGNvaW5jaWRlbioqIGVuIGxhIGRpcmVjY2nDs24gZGVsIGVmZWN0byIsDQogICIuIENsYXNpZmljYWNpw7NuOiBBLCAiLCBSJGNvbmNfQSwgIjsgQiwgIiwgUiRjb25jX0IsIGlmIChSJG5faW1wID4gMCkgcGFzdGUwKCI7IEMsICIsIFIkY29uY19DKSBlbHNlICIiLCAiLiAiLA0KICBpZiAoIWlzLm51bGwoUiRzaW0pKSBwYXN0ZTAoIkNvbXBsZXRhciBsYXMgw6FyZWFzIHBlbmRpZW50ZXMgYcOxYWRlIHBvY2EgaW5jZXJ0aWR1bWJyZSAoIiwgZngoUiRzaW1fcVsxXSwgMiksICLigJMiLCBmeChSJHNpbV9xWzNdLCAyKSwgIikgZnJlbnRlIGEgbGEgcXVlIGltcG9uZSBlbCBuw7ptZXJvIGRlIMOhcmJvbGVzLiAiKSBlbHNlICIiLA0KICBpZiAoIWlzLm5hKFIkamtfcmFuZ29bMV0pKSBwYXN0ZTAoIkFsIHF1aXRhciB1biDDoXJib2wgYSBsYSB2ZXosIGxhIHJhesOzbiB2YXLDrWEgZW50cmUgIiwgZngoUiRqa19yYW5nb1sxXSwgMiksICIgeSAiLCBmeChSJGprX3JhbmdvWzJdLCAyKSwNCiAgICBpZiAoUiRqa19jcnV6YSkgcGFzdGUwKCI6ICoqZWwgcmVzdWx0YWRvIGNhbWJpYSBkZSBzaWdubyBzZWfDum4gZWwgw6FyYm9sIHF1ZSBzZSBvbWl0YSoqLCBlcyBkZWNpciwgZGVwZW5kZSBkZSDDoXJib2xlcyBjb25jcmV0b3MgKCIsIGZyZWYoImphY2siKSwgIikuIikgZWxzZSBwYXN0ZTAoIjogbGEgZGlyZWNjacOzbiBzZSBtYW50aWVuZSAoIiwgZnJlZigiamFjayIpLCAiKS4iKSkgZWxzZSAiIikNCmBgYA0KDQpgciBSJHR4dF9zZW5zYA0KDQpgYGB7ciBmaWdfc2Vuc2liLCBmaWcuaGVpZ2h0PTMuMywgZmlnLmNhcD1mY2FwKCJzZW5zaWIiLCAiSW5jZXJ0aWR1bWJyZSBwcm9wYWdhZGEgZGVsIGNvbXBsZXRhZG8gZGUgbGFzIMOhcmVhcyBwZW5kaWVudGVzIiwgIkRpc3RyaWJ1Y2nDs24gZGUgbGEgcmF6w7NuIHNvbWJyYS9zb2wgZW4gbGFzIHNpbXVsYWNpb25lcyBxdWUgcmVlbXBsYXphbiBjYWRhIMOhcmVhIHBlbmRpZW50ZSBwb3IgdW5hIHByZWRpY2Npw7NuIGRlbCBtb2RlbG8gbWFyY28g4oaSIMOhcmVhIG3DoXMgcnVpZG8gcmVzaWR1YWwuIEzDrW5lYSBhenVsOiBlc3RpbWFjacOzbiBjb24gZWwgY29tcGxldGFkbyBkZXRlcm1pbmlzdGEgKEMpOyBsw61uZWEgbmVncmE6IGFuw6FsaXNpcyBjb24gc29sbyDDoXJlYXMgbWVkaWRhcyAoQSkuIil9DQppZiAoIWlzLm51bGwoUiRzaW0pKSB7DQogIGdncGxvdChkYXRhLmZyYW1lKHIgPSBleHAoUiRzaW0pKSwgYWVzKHIpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSA0MCwgZmlsbCA9ICJncmV5ODAiLCBjb2xvdXIgPSAid2hpdGUiKSArDQogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYkMkcmF6b24sIGNvbG91ciA9IENPTFsic29tYnJhIl0sIGxpbmV3aWR0aCA9IDEpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYkEkcmF6b24sIGNvbG91ciA9ICJibGFjayIsIGxpbmV0eXBlID0gMikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9IDMsIGNvbG91ciA9ICJncmV5NTAiKSArDQogICAgbGFicyh4ID0gIlJhesOzbiBzb21icmEvc29sIiwgeSA9ICJTaW11bGFjaW9uZXMiKQ0KfSBlbHNlIGdncGxvdCgpICsgdGhlbWVfdm9pZCgpICsgYW5ub3RhdGUoInRleHQiLCB4ID0gMCwgeSA9IDAsIGxhYmVsID0gIk5vIGhheSDDoXJlYXMgcGVuZGllbnRlcyBxdWUgY29tcGxldGFyIikNCmBgYA0KDQpgYGB7ciBmaWdfamFjaywgZmlnLmhlaWdodD0zLjIsIGZpZy5jYXA9ZmNhcCgiamFjayIsICJJbmZsdWVuY2lhIGRlIGNhZGEgw6FyYm9sIChvbWlzacOzbiBkZSB1biDDoXJib2wgYSBsYSB2ZXopIiwgIlJhesOzbiBzb21icmEvc29sIGFsIGV4Y2x1aXIgY2FkYSDDoXJib2wuIEzDrW5lYSBkaXNjb250aW51YTogZXN0aW1hY2nDs24gY29uIHRvZG9zIGxvcyDDoXJib2xlczsgbMOtbmVhIHB1bnRlYWRhOiBhdXNlbmNpYSBkZSBlZmVjdG8uIFVuIMOhcmJvbCBjdXlhIG9taXNpw7NuIGNhbWJpYSBtdWNobyBsYSBlc3RpbWFjacOzbiBlcyB1biDDoXJib2wgaW5mbHV5ZW50ZS4iKX0NCmpqIDwtIFIkamtbIWlzLm5hKFIkamskcmF6b24pLCBdDQppZiAobnJvdyhqaikgPiAwKSBnZ3Bsb3QoamosIGFlcyhyYXpvbiwgcmVvcmRlcihvbWl0aWRvLCByYXpvbikpKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsIGxpbmV0eXBlID0gMykgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBiQSRyYXpvbiwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiZ3JleTQwIikgKw0KICBnZW9tX3NlZ21lbnQoYWVzKHggPSBiQSRyYXpvbiwgeGVuZCA9IHJhem9uLCB5ZW5kID0gb21pdGlkbyksIGNvbG91ciA9ICJncmV5NjAiKSArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBleHBvc2ljaW9uKSwgc2hhcGUgPSAyMSwgc2l6ZSA9IDQsIGNvbG91ciA9ICJncmV5MTUiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IENPTCwgbmFtZSA9ICJFeHBvc2ljacOzbiBkZWwgw6FyYm9sIG9taXRpZG8iKSArIGxhYnMoeCA9ICJSYXrDs24gc29tYnJhL3NvbCBzaW4gZXNlIMOhcmJvbCIsIHkgPSAiw4FyYm9sIG9taXRpZG8iKQ0KYGBgDQoNCiMjIFBvdGVuY2lhIHkgdGFtYcOxbyBkZSBtdWVzdHJhDQoNCkNvbiBsYSBkZXN2aWFjacOzbiBlc3TDoW5kYXIgZW50cmUgw6FyYm9sZXMgb2JzZXJ2YWRhIChlbiBlc2NhbGEgbG9nYXLDrXRtaWNhOyBgciBpZiAoIWlzLm51bGwoUiRwb3QpKSBwYXN0ZTAoIs+DID0gIiwgZngoUiRwb3Qkc2RfdCwgMiksICIsIElDIDk1ICU6ICIsIGZ4KFIkcG90JHNkX2ljWzFdLCAyKSwgIuKAkyIsIGZ4KFIkcG90JHNkX2ljWzJdLCAyKSwgIiwgY29uIHNvbG8gIiwgUiRwb3QkZ2wsICIgZ3JhZG9zIGRlIGxpYmVydGFkIikgZWxzZSAibi9kImApLCBzZSBjYWxjdWzDsyBsYSByYXrDs24gbcOtbmltYSBkZXRlY3RhYmxlIGNvbiA4MCAlIGRlIHBvdGVuY2lhIHkgzrEgPSAwLDA1IHNlZ8O6biBlbCBuw7ptZXJvIGRlIMOhcmJvbGVzIHBvciBleHBvc2ljacOzbiAoYHIgZnJlZigicG90ZW5jaWEiKWApLg0KDQpgYGB7ciBmaWdfcG90ZW5jaWEsIGZpZy5oZWlnaHQ9My42LCBmaWcuY2FwPWZjYXAoInBvdGVuY2lhIiwgIkRpZmVyZW5jaWEgbcOtbmltYSBkZXRlY3RhYmxlIGVuIGZ1bmNpw7NuIGRlbCBuw7ptZXJvIGRlIMOhcmJvbGVzIiwgIlJhesOzbiBzb21icmEvc29sIGRldGVjdGFibGUgY29uIDgwICUgZGUgcG90ZW5jaWEgKHBydWViYSAqdCogZGUgZG9zIG11ZXN0cmFzIHNvYnJlIHByb21lZGlvcyBkZSDDoXJib2w7IGJhbmRhOiBpbmNlcnRpZHVtYnJlIGRlIGxhIGRlc3ZpYWNpw7NuIGVzdMOhbmRhciBlbnRyZSDDoXJib2xlcyBlc3RpbWFkYSBjb24gcG9jb3MgZ3JhZG9zIGRlIGxpYmVydGFkKS4gTMOtbmVhIHZlcnRpY2FsOiDDoXJib2xlcyBwb3IgZXhwb3NpY2nDs24gZW4gZWwgYW7DoWxpc2lzIEE7IGzDrW5lYSBhenVsIGRpc2NvbnRpbnVhOiByYXrDs24gb2JzZXJ2YWRhLiIpfQ0KaWYgKCFpcy5udWxsKFIkcG90KSkgew0KICBwIDwtIFIkcG90DQogIGxvIDwtIHZhcHBseShwJG5zLCBmdW5jdGlvbihuKSBleHAocG93ZXIudC50ZXN0KG4gPSBuLCBwb3dlciA9IC44LCBzZCA9IHAkc2RfaWNbMV0pJGRlbHRhKSwgbnVtZXJpYygxKSkNCiAgaGkgPC0gdmFwcGx5KHAkbnMsIGZ1bmN0aW9uKG4pIGV4cChwb3dlci50LnRlc3QobiA9IG4sIHBvd2VyID0gLjgsIHNkID0gcCRzZF9pY1syXSkkZGVsdGEpLCBudW1lcmljKDEpKQ0KICBkZnAgPC0gZGF0YS5mcmFtZShuID0gcCRucywgbWRlID0gcCRtZGUsIGxvID0gbG8sIGhpID0gaGkpDQogIGdncGxvdChkZnAsIGFlcyhuLCBtZGUpKSArIGdlb21fcmliYm9uKGFlcyh5bWluID0gbG8sIHltYXggPSBoaSksIGZpbGwgPSAiZ3JleTg3IikgKyBnZW9tX2xpbmUobGluZXdpZHRoID0gLjkpICsNCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9IDMpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYkEkcmF6b24sIGNvbG91ciA9IENPTFsic29tYnJhIl0sIGxpbmV0eXBlID0gMikgKw0KICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1pbihSJG5fc29sLCBSJG5fc29tKSwgY29sb3VyID0gImdyZXk0MCIsIGxpbmV0eXBlID0gMikgKw0KICAgIHNjYWxlX3lfbG9nMTAoYnJlYWtzID0gYygxLCAxLjI1LCAxLjUsIDIsIDMsIDUpKSArIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygxLCA1KSkgKw0KICAgIGxhYnMoeCA9ICLDgXJib2xlcyBwb3IgZXhwb3NpY2nDs24iLCB5ID0gIlJhesOzbiBtw61uaW1hIGRldGVjdGFibGUgKHNvbWJyYS9zb2wpIikNCn0NCmBgYA0KDQpgciBpZiAoIWlzLm51bGwoUiRwb3QpKSBwYXN0ZTAoIkNvbiAiLCBtaW4oUiRuX3NvbCwgUiRuX3NvbSksICIgw6FyYm9sZXMgcG9yIGV4cG9zaWNpw7NuLCBsYSByYXrDs24gbcOtbmltYSBkZXRlY3RhYmxlIGVzIOKJiCAiLCBmeChSJHBvdCRtZGVbUiRwb3QkbnMgPT0gbWF4KDIsIG1pbihSJG5fc29sLCBSJG5fc29tKSldLCAyKSwgIiwgZXMgZGVjaXIsIHNvbG8gZGlmZXJlbmNpYXMgbXV5IGdyYW5kZXMuIFBhcmEgZGV0ZWN0YXIgcmF6b25lcyBkZSAxLDI7IDEsMzsgMSw1IHkgMiwwIHNlIG5lY2VzaXRhcsOtYW4gYXByb3hpbWFkYW1lbnRlICIsIHBhc3RlKFIkcG90JHJlcSRuLCBjb2xsYXBzZSA9ICIsICIpLCAiIMOhcmJvbGVzIHBvciBleHBvc2ljacOzbiwgcmVzcGVjdGl2YW1lbnRlIChjb24gbGEgZGVzdmlhY2nDs24gZW50cmUgw6FyYm9sZXMgYXF1w60gZXN0aW1hZGEsIHF1ZSBlcyBpbmNpZXJ0YSkuIExhIGNvbmNsdXNpw7NuIHByw6FjdGljYSBjb2luY2lkZSBjb24gbGEgZGUgbGEgcGFydGljacOzbiBkZSB2YXJpYW56YTogY29udmllbmUgbWVkaXIgKiptw6FzIMOhcmJvbGVzKiogYW50ZXMgcXVlIG3DoXMgaG9qYXMgcG9yIMOhcmJvbC4iKSBlbHNlICIiYA0KDQojIyBGb3JtYSBkZSBsYSBob2phIHkgY29udGV4dG8gZXNwYWNpYWwNCg0KYGBge3IgZmlnX2Zvcm1hLCBmaWcuaGVpZ2h0PTMuOCwgZmlnLmNhcD1mY2FwKCJmb3JtYSIsICJSZWxhY2nDs24gZGUgYXNwZWN0byBkZWwgbWFyY28geSBwb3NpY2nDs24gZXNwYWNpYWwgZGUgbG9zIMOhcmJvbGVzIiwgIioqYSoqLCBSZWxhY2nDs24gZGUgYXNwZWN0byAobGFkbyBtYXlvci9sYWRvIG1lbm9yIGRlbCBtYXJjbykgcG9yIMOhcmJvbCwgY29tbyBpbmRpY2Fkb3IgYnVyZG8gZGUgbGEgZm9ybWEuICoqYioqLCBNZWRpYSBnZW9tw6l0cmljYSBkZWwgw6FyZWEgZGUgY2FkYSDDoXJib2wgZnJlbnRlIGEgc3UgcG9zaWNpw7NuIG5vcnRl4oCTc3VyOyB1biBwYXRyw7NuIGVzcGFjaWFsIHBvZHLDrWEgY29uZnVuZGlyc2UgY29uIGxhIGV4cG9zaWNpw7NuLiIpfQ0KZGZhIDwtIGRhdG9zWyFpcy5uYShkYXRvcyRhc3BlY3RvKSwgXTsgZGZhJGFyYm9sX2YgPC0gZmFjdG9yKGRmYSRhcmJvbCwgbGV2ZWxzID0gY29tcCRhcmJvbCkNCnBhIDwtIGdncGxvdChkZmEsIGFlcyhhcmJvbF9mLCBhc3BlY3RvLCBmaWxsID0gZXhwb3NpY2lvbikpICsgZ2VvbV9ib3hwbG90KHdpZHRoID0gLjU1LCBvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gLjUsIGNvbG91ciA9ICJncmV5MjUiLCBsaW5ld2lkdGggPSAuNCkgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IC4xMiwgaGVpZ2h0ID0gMCwgc2l6ZSA9IDEuNCwgYWxwaGEgPSAuNykgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBDT0wsIG5hbWUgPSAiRXhwb3NpY2nDs24iKSArIGxhYnMoeCA9IE5VTEwsIHkgPSAiTGFkbyBtYXlvciAvIGxhZG8gbWVub3IiKQ0KcGJkIDwtIG1lcmdlKGRlc2NfYWxsWywgYygiYXJib2wiLCAiZXhwb3NpY2lvbiIsICJnZW9tIildLCBnZW9bLCBjKCJhcmJvbCIsICJ5X20iKV0sIGJ5ID0gImFyYm9sIikNCnBiIDwtIGdncGxvdChwYmQsIGFlcyh5X20sIGdlb20sIGZpbGwgPSBleHBvc2ljaW9uKSkgKyBnZW9tX3BvaW50KHNoYXBlID0gMjEsIHNpemUgPSA0LCBjb2xvdXIgPSAiZ3JleTE1IikgKyBnZW9tX3RleHQoYWVzKGxhYmVsID0gYXJib2wpLCBudWRnZV95ID0gZGlmZihyYW5nZShwYmQkZ2VvbSkpICogLjA4ICsgLjUsIHNpemUgPSAzKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IENPTCwgZ3VpZGUgPSAibm9uZSIpICsgbGFicyh4ID0gIlBvc2ljacOzbiBub3J0ZeKAk3N1ciByZXNwZWN0byBkZWwgY2VudHJvaWRlIChtKSIsIHkgPSAiTWVkaWEgZ2VvbcOpdHJpY2EgZGVsIMOhcmVhIChjbcKyKSIpDQppZiAobnJvdyhwYmQpID49IDQpIHsgY3QgPC0gc3VwcHJlc3NXYXJuaW5ncyhjb3IudGVzdChwYmQkeV9tLCBwYmQkZ2VvbSwgbWV0aG9kID0gInNwZWFybWFuIikpOyBSJHNwX3JobyA8LSB1bm5hbWUoY3QkZXN0aW1hdGUpOyBSJHNwX3AgPC0gY3QkcC52YWx1ZSB9DQpwYSArIHBiICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiYSIpDQpgYGANCg0KYHIgcGFzdGUwKCJMYSByZWxhY2nDs24gZGUgYXNwZWN0byBkZWwgbWFyY28gZnVlICIsIGZ4KFIkYXNwX21lZGlhLCAyKSwgIiBlbiBwcm9tZWRpbyAocmFuZ28gIiwgZngoUiRhc3BfcmFuZ29bMV0sIDIpLCAi4oCTIiwgZngoUiRhc3BfcmFuZ29bMl0sIDIpLCAiKSwgcHJvcGlhIGRlIGzDoW1pbmFzIGJpbG9idWxhZGFzIGNhc2kgdGFuIGFuY2hhcyBjb21vIGxhcmdhcyIsICAgaWYgKCFpcy5uYShiQXNwJHBfd2VsY2gpKSBwYXN0ZTAoIjsgZW50cmUgZXhwb3NpY2lvbmVzIGxhIHJhesOzbiBkZSBhc3BlY3RvIGZ1ZSAiLCBmeChiQXNwJHJhem9uLCAyKSwgIiAoSUMgOTUgJTogIiwgZngoYkFzcCRsaSwgMiksICLigJMiLCBmeChiQXNwJGxzLCAyKSwgIjsgIiwgZnBwKGJBc3AkcF93ZWxjaCksICIpLCAiLCBpZmVsc2UoYkFzcCRwX3dlbGNoIDwgMC4wNSwgImluZGljaW8gZGUgdW4gY2FtYmlvIGRlIGZvcm1hIGFkZW3DoXMgZGUgdGFtYcOxbyIsICJzaW4gaW5kaWNpbyBkZSBjYW1iaW8gZGUgZm9ybWEiKSwgIi4gIikgZWxzZSAiLiAiLCAgICJFbCDDoXJib2wgbcOhcyBhbGVqYWRvIGRlbCBjZW50cm9pZGUgKCIsIFIkbGVqYW5vLCAiLCBhICIsIGZ4KFIkZGlzdF9sZWphbm8sIDApLCAiIG0pICIsIGlmICghaXMubnVsbChSJHNwX3JobykpIHBhc3RlMCgiaGFjZSBxdWUgbGEgY29ycmVsYWNpw7NuIGRlIFNwZWFybWFuIGVudHJlIGxhIHBvc2ljacOzbiBub3J0ZeKAk3N1ciB5IGVsIHRhbWHDsW8gc2VhIM+BID0gIiwgZngoUiRzcF9yaG8sIDIpLCAiICgiLCBmcHAoUiRzcF9wKSwgIiwgbiA9ICIsIG5yb3cocGJkKSwgIiwgc29sbyBleHBsb3JhdG9yaWEpLiAiKSBlbHNlICJpbXBpZGUgZXN0aW1hciB1bmEgYXNvY2lhY2nDs24gZXNwYWNpYWwgY29uIHRhbiBwb2NvcyDDoXJib2xlcy4gIiwgICAiQ29uIHRhbiBwb2NvcyDDoXJib2xlcywgbGEgZXhwb3NpY2nDs24geSBsYSB1YmljYWNpw7NuIG5vIHB1ZWRlbiBzZXBhcmFyc2UuIilgDQoNCiMgRGlzY3VzacOzbg0KDQpgYGB7ciBjYWxjX2Rpc2MsIGluY2x1ZGU9RkFMU0V9DQpSJHR4dF9kaXNjMSA8LSBpZiAoaXMubmEoYkEkcF93ZWxjaCkpICJDb24gbG9zIMOhcmJvbGVzIGRpc3BvbmlibGVzIG5vIHB1ZWRlIGVzdGltYXJzZSBlbCBjb250cmFzdGUgZW50cmUgZXhwb3NpY2lvbmVzLiIgZWxzZQ0KICBwYXN0ZTAoIkNvbiBlbCDDoXJib2wgY29tbyB1bmlkYWQgZXhwZXJpbWVudGFsLCBsYXMgaG9qYXMgZGUgbG9zIMOhcmJvbGVzIGRlIHNvbWJyYSBmdWVyb24gIiwgZngoYWJzKGJBJHJhem9uIC0gMSkgKiAxMDAsIDApLCAiICUgIiwgaWZlbHNlKGJBJHJhem9uID4gMSwgIm1heW9yZXMiLCAibWVub3JlcyIpLA0KICAgICAgICAgIiBxdWUgbGFzIGRlIHNvbCBlbiBwcm9tZWRpbyBnZW9tw6l0cmljbyAocmF6w7NuID0gIiwgZngoYkEkcmF6b24sIDIpLCAiOyBJQyA5NSAlOiAiLCBmeChiQSRsaSwgMiksICLigJMiLCBmeChiQSRscywgMiksICI7ICIsIGZwcChiQSRwX3dlbGNoKSwgIikuICIsIFIkZnJhc2VfaDEpDQpSJHR4dF9pY2NfZCA8LSBpZiAoIWlzLm51bGwoUiRpY2MpKSBwYXN0ZTAoIk3DoXMgaW5mb3JtYXRpdm8gcXVlIGVsIGNvbnRyYXN0ZSBlcyBlbCByZXBhcnRvIGRlIGxhIHZhcmlhY2nDs246IGVsICIsIGZ4KDEwMCAqIFIkaWNjJGljYywgMCksICIgJSBkZSBsYSB2YXJpYWNpw7NuIGRlbCB0YW1hw7FvIGRlIGxhcyBob2phcyBlc3TDoSBlbnRyZSDDoXJib2xlcyAoQ0NJID0gIiwgZngoUiRpY2MkaWNjLCAyKSwgIiksIGVzIGRlY2lyLCAiLA0KICAiZWwgw6FyYm9sIGVzIGxhIGZ1ZW50ZSBkZSB2YXJpYWNpw7NuIGRvbWluYW50ZSB5IGxhIGV4cG9zaWNpw7NuLCB1bmEgZGUgdmFyaWFzIHBvc2libGVzIGNhdXNhcyBkZSBlbGxhLiIpIGVsc2UgIiINClIkdHh0X3BvdF9kIDwtIGlmICghaXMubnVsbChSJHBvdCkpIHBhc3RlMCgiQ29uICIsIG1pbihSJG5fc29sLCBSJG5fc29tKSwgIiDDoXJib2xlcyBwb3IgZXhwb3NpY2nDs24sIGVsIGRpc2XDsW8gc29sbyBoYWJyw61hIGRldGVjdGFkbyByYXpvbmVzIGRlIOKJiCAiLCBmeChSJHBvdCRtZGVbUiRwb3QkbnMgPT0gbWF4KDIsIG1pbihSJG5fc29sLCBSJG5fc29tKSldLCAyKSwgIiBvIG1heW9yZXMgY29uIDgwICUgZGUgcG90ZW5jaWEuIikgZWxzZSAiIg0KYGBgDQoNCmByIFIkdHh0X2Rpc2MxYCBgciBSJHR4dF9pY2NfZGAgYHIgUiR0eHRfcG90X2RgIENvbnZpZW5lIGxlZXIgZXN0b3MgbsO6bWVyb3MgY29uIGxhcyBjYXV0ZWxhcyBxdWUgcmVjb21pZW5kYSBsYSBsaXRlcmF0dXJhIGVzdGFkw61zdGljYTogdW4gaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBxdWUgaW5jbHV5ZSBsYSBhdXNlbmNpYSBkZSBlZmVjdG8gZGVzY3JpYmUgKippbXByZWNpc2nDs24qKiwgbm8gZGVtdWVzdHJhIHF1ZSBubyBoYXlhIGVmZWN0bywgeSBsYSBkaWZlcmVuY2lhIGVudHJlIHVuIHJlc3VsdGFkbyDCq3NpZ25pZmljYXRpdm/CuyB5IG90cm8gwqtubyBzaWduaWZpY2F0aXZvwrsgbm8gZXMgZW4gc8OtIG1pc21hIHNpZ25pZmljYXRpdmEuYHIgY2l0ZSgiZ2VsbWFuMjAwNiIsICJ3YXNzZXJzdGVpbjIwMTYiLCAiYW1yaGVpbjIwMTkiKWAgUG9yIGVzbyBlc3RlIGluZm9ybWUgcHJpb3JpemEgbGFzIGVzdGltYWNpb25lcyBjb24gc3VzIGludGVydmFsb3MgeSBsYSBjb2hlcmVuY2lhIGVudHJlIGFuw6FsaXNpcyBzb2JyZSBlbCB2YWxvciBkZSAqcCogZGUgdW5hIHNvbGEgcHJ1ZWJhLg0KDQojIyBDb250cmFzdGUgY29uIGxhIGxpdGVyYXR1cmENCg0KTGEgYHIgZnJlZigibGl0ZXJhdHVyYSIpYCBjb25mcm9udGEgbGFzIHByZWRpY2Npb25lcyBkZSBhbWJhcyBoaXDDs3Rlc2lzIGNvbiBsbyBvYnNlcnZhZG8uIEgxIHNlIGFwb3lhIGVuIHF1ZSB1bmEgbWF5b3IgcmFkaWFjacOzbiBhcG9ydGEgbcOhcyBlbmVyZ8OtYSBhIGxhIGZvdG9zw61udGVzaXMgeSBlbiBxdWUsIGEgZXNjYWxhIGdsb2JhbCwgbGFzIGhvamFzIGdyYW5kZXMgcHJlZG9taW5hbiBlbiBhbWJpZW50ZXMgY8OhbGlkb3MsIGjDum1lZG9zIHkgc29sZWFkb3MuYHIgY2l0ZSgid3JpZ2h0MjAxNyIpYCBIMiBzZSBhcG95YSBlbiBsYSBjb21wZW5zYWNpw7NuIGVuIHNvbWJyYTogY29uIHBvY2EgbHV6IGxhcyBwbGFudGFzIGRlc3BsaWVnYW4gcmFzZ29zIHF1ZSBvcHRpbWl6YW4gbGEgY2FwdHVyYSBkZSBsdXogeSBtb2RpZmljYW4gbGEgbWFzYSBwb3Igw6FyZWEgeSBsYSBhc2lnbmFjacOzbiBkZSBzdXBlcmZpY2llIGZvbGlhci5gciBjaXRlKCJwb29ydGVyMjAwOSIsICJwb29ydGVyMjAxOSIpYCBBIGZhdm9yIGRlIEgyIHRhbWJpw6luIGFjdMO6YSBsYSBsaW1pdGFjacOzbiB0w6lybWljYSBlIGjDrWRyaWNhIGEgcGxlbm8gc29sOiB1bmEgbMOhbWluYSBtYXlvciBlbmdyb3NhIGxhIGNhcGEgbMOtbWl0ZSB5IGRpZmljdWx0YSBkaXNpcGFyIGNhbG9yIHkgYWd1YS5gciBjaXRlKCJwYXJraHVyc3QxOTcyIiwgIm1pY2hhbGV0ejIwMTUiKWAgQ3XDoWwgZG9taW5hIGRlcGVuZGUgZGVsIGJhbGFuY2UgZW50cmUgbHV6LCB0ZW1wZXJhdHVyYSB5IGFndWEgZW4gY2FkYSBtaWNyb3NpdGlvLCB5IHBvciBlc28gbGEgZGlyZWNjacOzbiBkZWwgZWZlY3RvIHNvYnJlIGVsIMOhcmVhIGRlIHVuYSBob2phIGRlYmUgY29udHJhc3RhcnNlIGNhc28gcG9yIGNhc28uIEFkZW3DoXMsIGVsIMOhcmVhIGRlIHVuYSBob2phIG5vIGVzIHVuYSBtZWRpZGEgZGUgcHJvZHVjY2nDs246IG5vIHNlIG1pZGllcm9uIGZvdG9zw61udGVzaXMgbmkgYmlvbWFzYSwgeSBlbCBhcHJvdmVjaGFtaWVudG8gZGUgbGEgbHV6IGRlcGVuZGUgZGUgY8OzbW8gc2Ugb3JnYW5pemEgdG9kbyBlbCBmb2xsYWplLg0KDQpgYGB7ciBmaWdfbGl0ZXJhdHVyYSwgZmlnLmhlaWdodD03LjQsIGZpZy5jYXA9ZmNhcCgibGl0ZXJhdHVyYSIsICJQcmVkaWNjaW9uZXMgZGUgbGEgbGl0ZXJhdHVyYSBmcmVudGUgYSBsbyBvYnNlcnZhZG8iLCAiKiphKiosIFJ1dGFzIGNhdXNhbGVzIHF1ZSBwbGFudGVhIGxhIHRlb3LDrWEgcGFyYSBlbCDDoXJlYSBkZSB1bmEgaG9qYSBpbmRpdmlkdWFsOyBsb3MgbsO6bWVyb3MgZW50cmUgY29yY2hldGVzIHJlbWl0ZW4gYSBsYXMgcmVmZXJlbmNpYXMuICoqYioqLCBSYXrDs24gc29tYnJhL3NvbCBvYnNlcnZhZGEgY29uIHRyZXMgYmFzZXMgZGUgZGF0b3MgKGJhcnJhczogSUMgOTUgJSkuIExhIHpvbmEgb2NyZSBlcyBsYSByZWdpw7NuIHByZWRpY2hhIHBvciBIMSAoaG9qYXMgbWF5b3JlcyBhIHBsZW5vIHNvbCk7IGxhIHpvbmEgYXp1bCwgbGEgZGUgSDIgKGhvamFzIG1heW9yZXMgZW4gc29tYnJhKS4iKX0NCnJlZl9hIDwtIHBhc3RlMCgiWyIsIGNuKCJ3cmlnaHQyMDE3IiksICJdIikNCnJlZl9iIDwtIHBhc3RlMCgiWyIsIGNuKCJwb29ydGVyMjAwOSIsICJwb29ydGVyMjAxOSIsICJ2YWxsYWRhcmVzMjAwOCIsICJnaXZuaXNoMTk4OCIpLCAiXSIpDQpyZWZfYyA8LSBwYXN0ZTAoIlsiLCBjbigicGFya2h1cnN0MTk3MiIsICJtaWNoYWxldHoyMDE1IiksICJdIikNCmNhcGEyIDwtIGMoDQogIGNhamEoMTIsIDU5LCAyNCwgMTIsICJBbHRhIGlycmFkaWFuY2lhXG4ocGxlbm8gc29sKSIsIGZpbGwgPSBhZGp1c3Rjb2xvcihDT0xbInNvbCJdLCAuMyksIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAyLjYpLA0KICBjYWphKDUwLCA1OSwgMzYsIDEzLCAiTcOhcyBlbmVyZ8OtYSBwYXJhIGxhIGZvdG9zw61udGVzaXM7XG5ob2phcyBncmFuZGVzIGVuIGFtYmllbnRlc1xuY8OhbGlkb3MsIGjDum1lZG9zIHkgc29sZWFkb3MiLCBzaXplID0gMi42KSwNCiAgY2FqYSg4NiwgNTksIDI4LCAxMiwgIkgxOiBsw6FtaW5hIG1heW9yXG5hIHBsZW5vIHNvbCIsIGZpbGwgPSBhZGp1c3Rjb2xvcihDT0xbInNvbCJdLCAuMTUpLCBzaXplID0gMi42LCBmYWNlID0gImJvbGQiKSwNCiAgY2FqYSgxMiwgMzgsIDI0LCAxMiwgIkJhamEgaXJyYWRpYW5jaWFcbihzb21icmEpIiwgZmlsbCA9IGFkanVzdGNvbG9yKENPTFsic29tYnJhIl0sIC4zKSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDIuNiksDQogIGNhamEoNTAsIDM4LCAzNiwgMTMsICJDb21wZW5zYWNpw7NuIG1vcmZvbMOzZ2ljYTpcbm3DoXMgc3VwZXJmaWNpZSBwYXJhIGNhcHRhciBsdXosXG5tZW5vciBtYXNhIHBvciB1bmlkYWQgZGUgw6FyZWEiLCBzaXplID0gMi42KSwNCiAgY2FqYSg4NiwgMzgsIDI4LCAxMiwgIkgyOiBsw6FtaW5hIG1heW9yXG5lbiBzb21icmEiLCBmaWxsID0gYWRqdXN0Y29sb3IoQ09MWyJzb21icmEiXSwgLjE1KSwgc2l6ZSA9IDIuNiwgZmFjZSA9ICJib2xkIiksDQogIGNhamEoMTIsIDE3LCAyNCwgMTIsICJDYWxvciBleGNlc2l2byBvXG5mYWx0YSBkZSBhZ3VhIChzb2wpIiwgZmlsbCA9IGFkanVzdGNvbG9yKENPTFsic29sIl0sIC4zKSwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDIuNiksDQogIGNhamEoNTAsIDE3LCAzNiwgMTMsICJDYXBhIGzDrW1pdGUgbcOhcyBncnVlc2E7XG5tw6FzIHDDqXJkaWRhIGRlIGFndWFcbnkgZGlmaWN1bHRhZCBwYXJhIGRpc2lwYXIgY2Fsb3IiLCBzaXplID0gMi42KSwNCiAgY2FqYSg4NiwgMTcsIDI4LCAxMiwgIkxpbWl0YWNpw7NuOiBsw6FtaW5hXG5tZW5vciBhIHBsZW5vIHNvbCIsIGZpbGwgPSBhZGp1c3Rjb2xvcihDT0xbInNvbCJdLCAuMTUpLCBzaXplID0gMi42LCBmYWNlID0gImJvbGQiKSwNCiAgbGlzdChmbGVjaGEoMjQuNCwgNTksIDMxLjYsIDU5KSwgZmxlY2hhKDY4LjQsIDU5LCA3MS42LCA1OSksIGZsZWNoYSgyNC40LCAzOCwgMzEuNiwgMzgpLCBmbGVjaGEoNjguNCwgMzgsIDcxLjYsIDM4KSwgZmxlY2hhKDI0LjQsIDE3LCAzMS42LCAxNyksIGZsZWNoYSg2OC40LCAxNywgNzEuNiwgMTcpLA0KICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDUwLCB5ID0gNTAsIGxhYmVsID0gcmVmX2EsIHNpemUgPSAyLjgsIGNvbG91ciA9ICJncmV5MzAiKSwgYW5ub3RhdGUoInRleHQiLCB4ID0gNTAsIHkgPSAyOSwgbGFiZWwgPSByZWZfYiwgc2l6ZSA9IDIuOCwgY29sb3VyID0gImdyZXkzMCIpLA0KICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDUwLCB5ID0gOC41LCBsYWJlbCA9IHJlZl9jLCBzaXplID0gMi44LCBjb2xvdXIgPSAiZ3JleTMwIikpLA0KICBjYWphKDUwLCAxLCA5NiwgNywgcGFzdGUwKCJPYnNlcnZhZG8gKEEpOiByYXrDs24gc29tYnJhL3NvbCA9ICIsIGZ4KGJBJHJhem9uLCAyKSwgIiBbIiwgZngoYkEkbGksIDIpLCAi4oCTIiwgZngoYkEkbHMsIDIpLCAiXVxu4oaSICIsIFIkY29uY19BKSwgZmlsbCA9ICIjZjFmM2Y0IiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDIuNykpDQpwYSA8LSBnZ3Bsb3QoKSArIGNhcGEyICsgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDEwMCksIHlsaW0gPSBjKC0zLCA2NiksIGNsaXAgPSAib2ZmIikgKyB0aGVtZV92b2lkKCkNCnBiIDwtIGdncGxvdCgpICsgdGhlbWVfdm9pZCgpDQpmYiA8LSBmcltmciR0aXBvID09ICJjb3JyZWN0byIgJiBncmVwbCgiXihBIMK3IFdlbGNofEIgwrd8QyDCtykiLCBhcy5jaGFyYWN0ZXIoZnIkbGFiZWwpKSwgXQ0KaWYgKG5yb3coZmIpID4gMCkgew0KICB4bCA8LSByYW5nZShjKGZiJGxvLCBmYiRoaSwgMC41LCAyKSwgbmEucm0gPSBUUlVFKQ0KICBwYiA8LSBnZ3Bsb3QoZmIsIGFlcyhlc3QsIGxhYmVsKSkgKw0KICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDFlLTMsIHhtYXggPSAxLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9IENPTFsic29sIl0sIGFscGhhID0gLjE0KSArDQogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMSwgeG1heCA9IDFlMywgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSBDT0xbInNvbWJyYSJdLCBhbHBoYSA9IC4xMCkgKw0KICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImdyZXk0MCIpICsNCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSBsbywgeGVuZCA9IGhpLCB5ZW5kID0gbGFiZWwpLCBsaW5ld2lkdGggPSAxLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9wb2ludChzaXplID0gMy42LCBzaGFwZSA9IDIxLCBmaWxsID0gIndoaXRlIiwgc3Ryb2tlID0gMS4xKSArDQogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gZXhwKG1lYW4obG9nKGMoeGxbMV0sIDEpKSkpLCB5ID0gbnJvdyhmYikgKyAuNDUsIGxhYmVsID0gIlJlZ2nDs24gZGUgSDEgKHNvbCA+IHNvbWJyYSkiLCBzaXplID0gMywgY29sb3VyID0gIiNhMDZhMDAiKSArDQogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gZXhwKG1lYW4obG9nKGMoMSwgeGxbMl0pKSkpLCB5ID0gbnJvdyhmYikgKyAuNDUsIGxhYmVsID0gIlJlZ2nDs24gZGUgSDIgKHNvbWJyYSA+IHNvbCkiLCBzaXplID0gMywgY29sb3VyID0gIiMwMDVhOGMiKSArDQogICAgc2NhbGVfeF9sb2cxMChicmVha3MgPSBjKC4yNSwgLjUsIDEsIDIsIDQsIDgpKSArIGNvb3JkX2NhcnRlc2lhbih4bGltID0geGwsIHlsaW0gPSBjKC41LCBucm93KGZiKSArIC44KSkgKyBsYWJzKHggPSAiUmF6w7NuIGRlIMOhcmVhcyBzb21icmEvc29sIChlc2NhbGEgbG9nKSIsIHkgPSBOVUxMKQ0KfQ0KcGEgLyBwYiArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEuNDUsIDEpKSArIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gImEiKQ0KYGBgDQoNCmBgYHtyIHRhYl9saXQsIHJlc3VsdHM9J2FzaXMnfQ0KdGwgPC0gZGF0YS5mcmFtZSgNCiAgUHJlZGljY2nDs24gPSBjKCJNw6FzIHJhZGlhY2nDs24geSBhZ3VhIHN1ZmljaWVudGUgZmF2b3JlY2VuIGzDoW1pbmFzIG1heW9yZXMgYSBwbGVubyBzb2wgKEgxKSIsICJFbiBzb21icmEsIGxhIGNvbXBlbnNhY2nDs24gbW9yZm9sw7NnaWNhIGZhdm9yZWNlIGzDoW1pbmFzIG1heW9yZXMgKEgyKSIsICJFbCBjYWxvciBleGNlc2l2byB5IGVsIGTDqWZpY2l0IGjDrWRyaWNvIGxpbWl0YW4gZWwgdGFtYcOxbyBhIHBsZW5vIHNvbCIsICJMYSBsdXogbW9kaWZpY2EgbGEgbWFzYSBwb3Igw6FyZWEgeSBsYSBhc2lnbmFjacOzbiBmb2xpYXIiLCAiTGEgdmFyaWFjacOzbiBlbnRyZSBpbmRpdmlkdW9zIGVzIGdyYW5kZSB5IG5vIHB1ZWRlIGlnbm9yYXJzZSBhbCByZXBsaWNhciIpLA0KICBGdWVudGVzID0gYyhwYXN0ZTAoIlJlZi4gIiwgY24oIndyaWdodDIwMTciKSksIHBhc3RlMCgiUmVmcy4gIiwgY24oInZhbGxhZGFyZXMyMDA4IiwgImdpdm5pc2gxOTg4IiwgInBvb3J0ZXIyMDE5IikpLCBwYXN0ZTAoIlJlZnMuICIsIGNuKCJwYXJraHVyc3QxOTcyIiwgIm1pY2hhbGV0ejIwMTUiKSksIHBhc3RlMCgiUmVmcy4gIiwgY24oInBvb3J0ZXIyMDA5IiwgInBvb3J0ZXIyMDE5IikpLCBwYXN0ZTAoIlJlZi4gIiwgY24oImh1cmxiZXJ0MTk4NCIpKSksDQogIGBFc3RlIGVzdHVkaW9gID0gYyhwYXN0ZTAoInJhesOzbiAiLCBmeChiQSRyYXpvbiwgMiksICIgKCIsIGZ4KGJBJGxpLCAyKSwgIuKAkyIsIGZ4KGJBJGxzLCAyKSwgIikiKSwgcGFzdGUwKCJyYXrDs24gIiwgZngoYkEkcmF6b24sIDIpLCAiICgiLCBmeChiQSRsaSwgMiksICLigJMiLCBmeChiQSRscywgMiksICIpIiksDQogICAgICAgICAgICAgICAgICAgICAibm8gc2VwYXJhYmxlOiBubyBzZSBtaWRpZXJvbiB0ZW1wZXJhdHVyYSBuaSBlc3RhZG8gaMOtZHJpY28iLCAibm8gbWVkaWRhIChzb2xvIMOhcmVhIGRlIGxhIGzDoW1pbmEpIiwgaWYgKCFpcy5udWxsKFIkaWNjKSkgcGFzdGUwKCJDQ0kgPSAiLCBmeChSJGljYyRpY2MsIDIpKSBlbHNlICJuL2QiKSwNCiAgVmFsb3JhY2nDs24gPSBjKFIkdmFsX2gxLCBSJHZhbF9hbHQsICJubyBldmFsdWFibGUgY29uIGVzdG9zIGRhdG9zIiwgIm5vIGV2YWx1YWJsZSBjb24gZXN0b3MgZGF0b3MiLA0KICAgICAgICAgICAgICAgICBpZiAoIWlzLm51bGwoUiRpY2MpKSBpZmVsc2UoUiRpY2MkaWNjID4gMC4zLCAiY29uc2lzdGVudGU6IGxhIHZhcmlhbnphIGVudHJlIMOhcmJvbGVzIGVzIHN1c3RhbmNpYWwiLCAibm8gZXZpZGVudGUgZW4gZXN0b3MgZGF0b3MiKSBlbHNlICJuL2QiKSwNCiAgY2hlY2submFtZXMgPSBGQUxTRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KY2F0KHRjYXAoImxpdCIsICJQcmVkaWNjaW9uZXMgZGVyaXZhZGFzIGRlIGxhIGxpdGVyYXR1cmEgeSBzdSBjb250cmFzdGUgY29uIGxvcyBkYXRvcyIsICLCq05vIGV2YWx1YWJsZcK7IHNpZ25pZmljYSBxdWUgbGEgdmFyaWFibGUgcXVlIGRpc3Rpbmd1ZSBsYSBoaXDDs3Rlc2lzIG5vIHNlIHJlZ2lzdHLDsy4iKSkNCnRhYmxhKHRsLCBhbGlnbiA9ICJsbGxsIikNCmBgYA0KDQojIyBRdcOpIGVzIHVuIHJlc3VsdGFkbyB5IHF1w6kgZXMgdW5hIGhpcMOzdGVzaXMNCg0KU2lndWllbmRvIGxhIGRpc3RpbmNpw7NuIHF1ZSBwaWRlIGxhIGd1w61hLCBjb24gdW5vcyBwb2NvcyDDoXJib2xlcyBjb252aWVuZSBzZXBhcmFyIGxvIHF1ZSBsb3MgZGF0b3MgZXN0YWJsZWNlbiBkZSBsbyBxdWUgc29sbyBzdWdpZXJlbjoNCg0KLSAgICoqUmVzdWx0YWRvcyoqIChkZXNjcmlwdGl2b3MsIGJpZW4gc3VzdGVudGFkb3MpOiBsYSBkaXN0cmlidWNpw7NuIGRlbCDDoXJlYSBwb3Igw6FyYm9sIChgciB0cmVmKCJkZXNjIilgKTsgbGEgcmVndWxhcmlkYWQgZGVsIGNvY2llbnRlIMOhcmVhL21hcmNvIHkgc3UgdXRpbGlkYWQgY29tbyBjb250cm9sIGRlIGNhbGlkYWQgKGByIFIkdHh0X3Byb3h5YCk7IHkgbGEgbWFnbml0dWQgZGUgbGEgdmFyaWFjacOzbiBlbnRyZSDDoXJib2xlcyBmcmVudGUgYSBsYSB2YXJpYWNpw7NuIGVudHJlIGhvamFzLg0KLSAgICoqSGlww7N0ZXNpcyoqIChyZXF1aWVyZW4gbcOhcyDDoXJib2xlcyk6IHF1ZSBsYSBleHBvc2ljacOzbiBjYW1iaWUgZWwgw6FyZWEgZm9saWFyIGRlICpgciBSJGVzcGVjaWVgKiB5IGVuIHF1w6kgc2VudGlkby4gYHIgUiRmcmFzZV9oMWAgRXN0YSBsZWN0dXJhIGVzIHbDoWxpZGEgw7puaWNhbWVudGUgcGFyYSBsb3MgYHIgUiRuX2FyYl9pbmZgIMOhcmJvbGVzIGFuYWxpemFkb3MuDQotICAgKipObyBldmFsdWFibGUgYXF1w60qKjogbG9zIG1lY2FuaXNtb3MgKGx1eiwgdGVtcGVyYXR1cmEsIGFndWEsIHN1ZWxvIHBhdmltZW50YWRvKSwgcG9ycXVlIG5vIHNlIG1pZGllcm9uOyBzZSByZXF1ZXJpcsOtYSByZWdpc3RyYXIgaXJyYWRpYW5jaWEsIHRlbXBlcmF0dXJhIGZvbGlhciBvIGRlbCBhaXJlLCBodW1lZGFkIGRlbCBzdWVsbyB5IG1hc2EgcG9yIMOhcmVhLg0KDQojIyBMaW1pdGFjaW9uZXMNCg0KLSAgICoqUG9jb3Mgw6FyYm9sZXMuKiogTGEgcsOpcGxpY2EgdmVyZGFkZXJhIGVzIGVsIMOhcmJvbCB5IGhheSBgciBSJG5fc29sYCBkZSBzb2wgeSBgciBSJG5fc29tYCBkZSBzb21icmEgY29uIGRhdG9zOyBsb3MgZ3JhZG9zIGRlIGxpYmVydGFkIGRlbCBjb250cmFzdGUgc29uIGxvcyBkZSBsb3Mgw6FyYm9sZXMgeSBsYSBwb3RlbmNpYSBlcyBiYWphICh2w6lhc2UgKlBvdGVuY2lhIHkgdGFtYcOxbyBkZSBtdWVzdHJhKikuDQotICAgKirDgXJib2xlcyBpbmZsdXllbnRlcyB5IGNvbmZ1c2nDs24gZXNwYWNpYWwuKiogYHIgaWYgKGlzVFJVRShSJGprX2NydXphKSkgIkFsIG9taXRpciB1biDDoXJib2wgbGEgY29uY2x1c2nDs24gY2FtYmlhIGRlIHNpZ25vOyAiIGVsc2UgIiJgbGEgZXhwb3NpY2nDs24geSBsYSBwb3NpY2nDs24gZW4gZWwgYm9zcXVlIHVyYmFubyBubyBlc3TDoW4gY3J1emFkYXMsIGRlIG1vZG8gcXVlIG5vIHNlIHB1ZWRlbiBzZXBhcmFyIHN1cyBlZmVjdG9zLg0KLSAgICoqRXhwb3NpY2nDs24gY2F0ZWfDs3JpY2EuKiogwqtTb2zCuyB5IMKrc29tYnJhwrsgc29uIGNsYXNlcyBkZWZpbmlkYXMgdmlzdWFsbWVudGUgKGx1eiBkaXJlY3RhIGxhIG1heW9yIHBhcnRlIGRlbCBkw61hIGZyZW50ZSBhIGNvYmVydHVyYSBkZSBvdHJhcyBjb3BhcyBvIGx1eiBmaWx0cmFkYSksIG5vIG1lZGlkYXMgZGUgaXJyYWRpYW5jaWE7IGVsIHNvbWJyZWFkbyB2YXLDrWEgYSBsbyBsYXJnbyBkZWwgZMOtYSB5IGRlbCBhw7FvLCB5IGxhIHNvbWJyYSBwb3IgwqtsdXogZmlsdHJhZGHCuyBlcyBoZXRlcm9nw6luZWEuDQotICAgKirDgXJlYXMgcGVuZGllbnRlcy4qKiBIYXkgYHIgUiRuX2ZhbHRhYCDDoXJlYXMgcGVuZGllbnRlcyAoYHIgZngoUiRwY3RfZmFsdGEsIDEpYCAlKS4gQ29tcGxldGFybGFzIGNvbiBlbCBtb2RlbG8gZGVsIG1hcmNvIGVzIHVuIGFydGlmaWNpbyDDunRpbCBwYXJhIGV2YWx1YXIgbGEgc2Vuc2liaWxpZGFkLCBwZXJvIG5vIHN1c3RpdHV5ZSBsYSBtZWRpY2nDs24sIHkgZWwgYW7DoWxpc2lzIGNvbiBlbCBtYXJjbyBubyBlcyB1bmEgY29uZmlybWFjacOzbiBpbmRlcGVuZGllbnRlIHBvcnF1ZSBlbCBtYXJjbyBzZSBkaWJ1amEgYSBwYXJ0aXIgZGVsIGNvbnRvcm5vIGRlIGxhIHByb3BpYSBob2phLg0KLSAgICoqRWxlY2Npw7NuIGRlIGxvcyDDoXJib2xlcy4qKiBFbCDDum5pY28gY3JpdGVyaW8gZGUgc2VsZWNjacOzbiBmdWUgcXVlIGVzdHV2aWVyYW4gZGVzYXJyb2xsYWRvcyB5IHNpbiBkYcOxbyBuaSBlbmZlcm1lZGFkIGFwYXJlbnRlOyBubyBzZSBpZ3VhbGFyb24gZWRhZCwgdGFtYcOxbyBuaSBtb3Jmb3RpcG8sIGRlIG1vZG8gcXVlIHBhcnRlIGRlIGxhIGRpZmVyZW5jaWEgYXRyaWJ1aWRhIGEgbGEgZXhwb3NpY2nDs24gcHVlZGUgcmVmbGVqYXIgZXNhcyBkaWZlcmVuY2lhcyBlbnRyZSBpbmRpdmlkdW9zLg0KLSAgICoqVW5hIHNvbGEgZXNwZWNpZSwgdW4gc29sbyBzaXRpbyB5IHVuYSBzb2xhIGZlY2hhKiogKGByIGlmICgiZmVjaGEiICVpbiUgbmFtZXMoY3J1ZG8pKSAicmVnaXN0cmFkYSIgZWxzZSAibm8gcmVnaXN0cmFkYSBlbiBsYSBiYXNlImApOiBsb3MgcmVzdWx0YWRvcyBubyBzZSBleHRyYXBvbGFuIGEgb3RyYXMgZXNwZWNpZXMgbmkgYSBvdHJhcyDDqXBvY2FzLg0KLSAgICoqTWVkaWNpw7NuLioqIExhIGRldGVjY2nDs24gZGVsIG1hcmNvIHkgZGUgbGEgZmlndXJhIGVuIGxhIGZvdG9ncmFmw61hLCB5IGVsIGRpYnVqbyBkZWwgbWFyY28gY29uIHJlZ2xhLCBpbnRyb2R1Y2VuIGVycm9yIGRlIG1lZGlkYTsgZWwgZXJyb3IgcmVzaWR1YWwgZGVsIG1vZGVsbyBkZWwgbWFyY28gKOKJiCBgciBmeCgxMDAgKiBSJHB4X3NpZ21hLCAxKWAgJSkgZXMgdW5hIGNvdGEgaW5mZXJpb3IgZGVsIGVycm9yIGRlIHByZWRpY2Npw7NuLCBubyBkZWwgZXJyb3IgZGVsIMOhcmVhLg0KDQojIE3DqXRvZG9zDQoNCioqU2l0aW8geSBlc3BlY2llLioqIEVsIGVzdHVkaW8gc2UgcmVhbGl6w7MgZW4gZWwgQm9zcXVlIFVyYmFubyBNdWx0aWNlbnRybywgdWJpY2FkbyBlbiBlbCDDoXJlYSBmb3Jlc3RhbCBwcm90ZWN0b3JhIGRlbCByw61vIE1lbMOpbmRleiwgY29tdW5hIDIyLCBDYWxpIChWYWxsZSBkZWwgQ2F1Y2EsIENvbG9tYmlhKSwgYSBgciBmeChSJGFsdGl0dWRbMV0sIDApYCBtIHMuIG4uIG0uIChhbHRpdHVkIHJlZ2lzdHJhZGEgZW4gbGEgYmFzZSkuIExhIGVzcGVjaWUgZXN0dWRpYWRhIGZ1ZSAqYHIgUiRlc3BlY2llYCouDQoNCioqU2VsZWNjacOzbiBkZSDDoXJib2xlcy4qKiBEZW50cm8gZGVsIGJvc3F1ZSB1cmJhbm8gc2UgaWRlbnRpZmljYXJvbiB6b25hcyBhYmllcnRhcyB5IHpvbmFzIGRlIGFsdGEgZGVuc2lkYWQgYXJiw7NyZWEuIFNlIGNvbnNpZGVyYXJvbiDDoXJib2xlcyBkZSAqKnNvbCoqIGxvcyBxdWUgcmVjaWJlbiBsdXogZGlyZWN0YSBsYSBtYXlvciBwYXJ0ZSBkZWwgZMOtYSB5IG5vIGVzdMOhbiBjdWJpZXJ0b3MgcG9yIG90cmFzIGNvcGFzIG5pIHBvciBlZGlmaWNhY2lvbmVzLCB5IMOhcmJvbGVzIGRlICoqc29tYnJhKiogbG9zIHF1ZSBjcmVjZW4gYmFqbyBsYSBjb2JlcnR1cmEgZGUgb3Ryb3Mgw6FyYm9sZXMgbyBlbiB6b25hcyBjb24gbHV6IGZpbHRyYWRhLiBTZSBzZWxlY2Npb25hcm9uIGByIFIkbl9hcmJgIMOhcmJvbGVzLCBgciBSJG5fc29sX3RvdGAgZGUgc29sIHkgYHIgUiRuX3NvbV90b3RgIGRlIHNvbWJyYSwgcGFyYSBvYnRlbmVyIHVuIGRpc2XDsW8gYmFsYW5jZWFkbzsgZWwgw7puaWNvIGNyaXRlcmlvIGRlIHNlbGVjY2nDs24gZnVlIHF1ZSBlc3R1dmllcmFuIGRlc2Fycm9sbGFkb3MgeSBzaW4gZGHDsW8gbmkgZW5mZXJtZWRhZCBhcGFyZW50ZS4gRGUgY2FkYSDDoXJib2wgc2UgcmVnaXN0cmFyb24gbGFzIGNvb3JkZW5hZGFzIHkgc2UgdG9tw7MgdW5hIGZvdG9ncmFmw61hIGRlIHJlZmVyZW5jaWEgcXVlIGRvY3VtZW50YSBzdSBlc3RhZG8sIHN1IGVudG9ybm8geSBzdSBncmFkbyBkZSBleHBvc2ljacOzbiBzb2xhci4NCg0KKipTZWxlY2Npw7NuIGRlIGhvamFzLioqIEVuIGNhZGEgw6FyYm9sIHNlIG11ZXN0cmVhcm9uIGByIFIkaG9qYXNfeF9hcmJvbFsyXWAgaG9qYXMgKGByIFIkbl9maWxhc2AgZW4gdG90YWwpLCBkaXN0cmlidWlkYXMgcG9yIHRvZGEgbGEgY29wYSB5IGEgZGlmZXJlbnRlcyBkaXN0YW5jaWFzLg0KDQoqKk1lZGljacOzbiBkZWwgw6FyZWEgZm9saWFyLioqIEFscmVkZWRvciBkZWwgY29udG9ybm8gZGUgY2FkYSBob2phIHNlIGRpYnVqw7MgY29uIHJlZ2xhIHVuIG1hcmNvIHJlY3Rhbmd1bGFyIHkgc2UgbWlkaWVyb24gc3VzIGRvcyBsYWRvcyBlbiBtaWzDrW1ldHJvcy4gU2UgZm90b2dyYWZpw7MgbGEgaG9qYSBjb24gc3UgbWFyY28geSB1biBzY3JpcHQgZW4gUiB1c8OzIGVsIHRhbWHDsW8gZGVsIG1hcmNvIGVuIGNhZGEgZm90b2dyYWbDrWEgY29tbyBlc2NhbGEgcGFyYSBjb252ZXJ0aXIgcMOteGVsZXMgYSBjbcKyIHkgY2FsY3VsYXIgYXPDrSBlbCDDoXJlYSBkZSBsYSBob2phLiBFbCAqKsOhcmVhIGRlbCBtYXJjbyoqIHNlIGNhbGN1bMOzIGNvbW8gbGFkbyAxIMOXIGxhZG8gMiAobW3CsikgLyAxMDAgKGNtwrIpLg0KDQoqKlByb2Nlc2FtaWVudG8geSBjb250cm9sIGRlIGNhbGlkYWQuKiogTG9zIGRhdG9zIHNlIGxleWVyb24gY29tbyB0ZXh0byB5IHNlIGNvbnZpcnRpZXJvbiBhIHRpcG9zIG51bcOpcmljb3MgY29uIHJlZ2xhcyBleHBsw61jaXRhczogZWxpbWluYWNpw7NuIGRlIGVzcGFjaW9zLCBjb21hIG8gcHVudG8gZGVjaW1hbCwgcmVjb25zdHJ1Y2Npw7NuIGRlIGNvb3JkZW5hZGFzIGVzY3JpdGFzIGNvbiBzZXBhcmFkb3IgZGUgbWlsZXMsIG5vcm1hbGl6YWNpw7NuIGRlIGxhIGV4cG9zaWNpw7NuIHkgZGUgbG9zIGlkZW50aWZpY2Fkb3Jlcy4gVW4gw6FyZWEgbWF5b3IgcXVlIHN1IG1hcmNvIGVzIGbDrXNpY2FtZW50ZSBpbXBvc2libGU7IHNpIGRpdmlkaWRhIGVudHJlIDEwMCByZXN1bHRhYmEgcGxhdXNpYmxlIChjb2NpZW50ZSBlbnRyZSAwLDIgeSAxKSBzZSBpbnRlcnByZXTDsyBjb21vIGVycm9yIGRlIHVuaWRhZCB5IHNlIGNvcnJpZ2nDszsgZW4gb3RybyBjYXNvIHNlIGV4Y2x1ecOzLiBMYXMgw6FyZWFzIGVuIGJsYW5jbyBubyBzZSBpbXB1dGFuIGVuIGVsIGFuw6FsaXNpcyBwcmltYXJpby4gTGEgYmFzZSBhbmFsw610aWNhIHByaW1hcmlhICgqKkEqKikgY29udGllbmUgbGFzIGhvamFzIGNvbiDDoXJlYSBtZWRpZGEgdsOhbGlkYSBkZSBsb3Mgw6FyYm9sZXMgY29uIGFsIG1lbm9zIGByIHBhcmFtcyRtaW5faG9qYXNfYXJib2xgIGhvamFzIG1lZGlkYXMuDQoNCioqRXN0YWTDrXN0aWNhIGRlc2NyaXB0aXZhIHkgdHJhbnNmb3JtYWNpw7NuLioqIFBvciDDoXJib2wgc2UgY2FsY3VsYXJvbiAqbiosIG1lZGlhLCBtZWRpYW5hLCBERSwgQ1YsIGVycm9yIGVzdMOhbmRhciwgSUMgOTUgJSAoKnQqKSwgbcOtbmltbywgbcOheGltbyB5IG1lZGlhIGdlb23DqXRyaWNhLiBMYSBpbmZlcmVuY2lhIHNlIGhpem8gc29icmUgZWwgbG9nYXJpdG1vIG5hdHVyYWwgZGVsIMOhcmVhIChsbiksIHBvcnF1ZSBlbCB0YW1hw7FvIGVzIG11bHRpcGxpY2F0aXZvIHkgbGEgZGlzcGVyc2nDs24gY3JlY2UgY29uIGxhIG1lZGlhOyBsYXMgZGlmZXJlbmNpYXMgZW4gbG4gc2UgcmVwb3J0YW4gY29tbyByYXpvbmVzIGRlIG1lZGlhcyBnZW9tw6l0cmljYXMuIEVuIGVsIHJlc3RvIGRlbCBpbmZvcm1lIGxvcyByZXN1bHRhZG9zIHNlIGV4cHJlc2FuIGVuIGxhIGVzY2FsYSBvcmlnaW5hbCAocmF6b25lcyBkZSB0YW1hw7FvKSB5IHNlIG9taXRlIGxhIG1lbmNpw7NuIGFsIGxvZ2FyaXRtby4NCg0KKipVbmlkYWQgZGUgYW7DoWxpc2lzIHkgY29udHJhc3RlIHNvbOKAk3NvbWJyYS4qKiBQYXJhIGNhZGEgw6FyYm9sIHNlIGNhbGN1bMOzIGVsIHByb21lZGlvIGRlIGxuKMOhcmVhKSB5IGVzb3MgcHJvbWVkaW9zIHNlIGNvbXBhcmFyb24gZW50cmUgZXhwb3NpY2lvbmVzIGNvbiBsYSBwcnVlYmEgKnQqIGRlIFdlbGNoLGByIGNpdGUoIndlbGNoMTk0NyIpYCBsYSBwcnVlYmEgZGUgV2lsY294b24gZXhhY3RhLGByIGNpdGUoIndpbGNveG9uMTk0NSIpYCB1bmEgcHJ1ZWJhIGRlIHBlcm11dGFjacOzbiBleGFjdGEgKGRpZmVyZW5jaWEgZGUgbWVkaWFzIGRlIMOhcmJvbCBiYWpvIHRvZG9zIGxvcyByZXBhcnRvcyBkZSBsYXMgZXRpcXVldGFzKSB5IHVuIGJvb3RzdHJhcCBqZXLDoXJxdWljbyBkZSBkb3MgZXRhcGFzIChgciBwYXJhbXMkQl9ib290YCByw6lwbGljYXM6IHJlbXVlc3RyZW8gZGUgw6FyYm9sZXMgZGVudHJvIGRlIGNhZGEgZXhwb3NpY2nDs24geSBkZSBob2phcyBkZW50cm8gZGUgY2FkYSDDoXJib2wpLmByIGNpdGUoImVmcm9uMTk3OSIpYCBTZSBjYWxjdWzDsyBsYSAqZyogZGUgSGVkZ2VzIGNvbiBJQyBhcHJveGltYWRvLmByIGNpdGUoImhlZGdlczE5ODEiKWAgRWwgZWZlY3RvIGRlIGRpc2XDsW8gc2UgZXN0aW3DsyBjb21vIDEgKyAoKm3MhCog4oiSIDEpwrdDQ0kuDQoNCioqTW9kZWxvcy4qKiBTZSBhanVzdMOzIGVsIG1vZGVsbyBtaXh0byBsbigqQSopIFx+IGV4cG9zaWNpw7NuICsgKDEgXHwgw6FyYm9sKSBwb3IgUkVNTCBjb24gYGxtZTRgIHkgYGxtZXJUZXN0YCAoZ2wgZGUgU2F0dGVydGh3YWl0ZSksIGNvbiBSwrIgbWFyZ2luYWwgeSBjb25kaWNpb25hbCAoTmFrYWdhd2EgeSBTY2hpZWx6ZXRoKSwgeSBlbCBBTk9WQSBhbmlkYWRvIGNvbiBsYSBleHBvc2ljacOzbiBjb250cmFzdGFkYSBjb250cmEgZWwgY3VhZHJhZG8gbWVkaW8gZGUgw6FyYm9sLiBFbCBDQ0kgc2UgZXN0aW3DsyBwb3IgQU5PVkEgZGUgdW4gZmFjdG9yIGNvbiBJQyBkZSBNY0dyYXcgeSBXb25nLCB1c2FuZG8gZWwgdGFtYcOxbyBtZWRpbyBwb25kZXJhZG8gKm4qPHN1Yj4wPC9zdWI+LiBMb3Mgc3VwdWVzdG9zIHNlIHJldmlzYXJvbiBjb24gZ3LDoWZpY29zIGRlIHJlc2lkdW9zIHkgY29uIGxhcyBwcnVlYmFzIGRlIFNoYXBpcm/igJNXaWxrIHkgRmxpZ25lcuKAk0tpbGxlZW47IGNvbW8gYWx0ZXJuYXRpdmFzIHJvYnVzdGFzIHNlIHVzYXJvbiBlbCBBTk9WQSBkZSBXZWxjaCB5IEtydXNrYWzigJNXYWxsaXMuIExhcyBjb21wYXJhY2lvbmVzIHBvciBwYXJlcyBlbnRyZSDDoXJib2xlcyB1c2Fyb24gVHVrZXkgSFNEIHksIGNvbW8gY29udHJhc3RlLCBXZWxjaCBjb24gYWp1c3RlIGRlIEhvbG0uDQoNCioqVmFsb3JlcyBhdMOtcGljb3MuKiogUmVnbGEgZGUgVHVrZXkgcG9yIMOhcmJvbCAoMSw1wrdSSUMpLCAqeiogcm9idXN0byBjb24gbGEgTUFEICh1bWJyYWwgMyw1KSwgcmVzaWR1b3Mgc3R1ZGVudGl6YWRvcyAoXHwqdCpcfCBcPiAzKSB5IGRpc3RhbmNpYSBkZSBDb29rICg0LypOKikuIExhcyBob2phcyBzaW4gY2F1c2EgZGUgbWVkaWNpw7NuIHNlIGNvbnNlcnZhbiB5IHNlIGV2YWzDumEgbGEgc2Vuc2liaWxpZGFkIGRlbCByZXN1bHRhZG8gYSBkaXN0aW50b3MgcmVzw7ptZW5lcyBkZWwgw6FyYm9sIChtZWRpYSwgbWVkaWFuYSwgbWVkaWEgcmVjb3J0YWRhLCBtZWRpYSBzaW4gYXTDrXBpY29zKS4NCg0KKipBbsOhbGlzaXMgZGUgc2Vuc2liaWxpZGFkLioqICgqKkIqKikgRWwgY29udHJhc3RlIHNlIHJlcGl0acOzIGNvbiBsbijDoXJlYSBkZWwgbWFyY28pIGRlIHRvZGFzIGxhcyBob2phcy4gKCoqQyoqKSBMYXMgw6FyZWFzIHBlbmRpZW50ZXMgc2UgZXN0aW1hcm9uIGNvbiBsYSByZWdyZXNpw7NuIGxuKMOhcmVhKSBcfiBsbihtYXJjbykgYWp1c3RhZGEgYSBsYXMgaG9qYXMgbWVkaWRhcyAoY29uIGNvcnJlY2Npw7NuIGRlIHJldHJhbnNmb3JtYWNpw7NuKSB5IHNlIHJlcGl0acOzIGVsIGNvbnRyYXN0ZTsgc3UgaW5jZXJ0aWR1bWJyZSBzZSBwcm9wYWfDsyBjb24gYHIgcGFyYW1zJE1faW1wYCBzaW11bGFjaW9uZXMgcXVlIGHDsWFkZW4gZWwgZXJyb3IgcmVzaWR1YWwgeSBlbCBkZSBlc3RpbWFjacOzbiBkZWwgbW9kZWxvLiBUYW1iacOpbiBzZSBvbWl0acOzIHVuIMOhcmJvbCBhIGxhIHZleiAoamFja2tuaWZlIHBvciDDoXJib2wpLg0KDQoqKlBvdGVuY2lhLioqIFNlIGNhbGN1bMOzIGxhIHJhesOzbiBtw61uaW1hIGRldGVjdGFibGUgKDgwICUgZGUgcG90ZW5jaWEsIM6xID0gMCwwNSwgcHJ1ZWJhICp0KiBkZSBkb3MgbXVlc3RyYXMpIGNvbiBsYSBkZXN2aWFjacOzbiBlc3TDoW5kYXIgZW50cmUgw6FyYm9sZXMgb2JzZXJ2YWRhIGRlbnRybyBkZSBjYWRhIGV4cG9zaWNpw7NuIHkgc3UgSUMgcG9yIM+HwrIuDQoNCioqU29mdHdhcmUgeSByZXByb2R1Y2liaWxpZGFkLioqIFRvZG8gZWwgYW7DoWxpc2lzIHNlIGVqZWN1dGEgZGVzZGUgZXN0ZSBkb2N1bWVudG8gY29uIGByIFIudmVyc2lvbi5zdHJpbmdgOyBsb3MgZ3LDoWZpY29zIHVzYW4gYGdncGxvdDJgLGByIGNpdGUoIndpY2toYW0yMDE2IilgIGNvbiBwYWxldGEgZGUgT2thYmXigJNJdG8gYXB0YSBwYXJhIGRhbHRvbmlzbW8sIHkgYHBhdGNod29ya2AuIFNlbWlsbGEgYWxlYXRvcmlhOiBgciBwYXJhbXMkc2VtaWxsYWAuIFBhcXVldGVzOiBnZ3Bsb3QyIGByIGFzLmNoYXJhY3RlcihwYWNrYWdlVmVyc2lvbigiZ2dwbG90MiIpKWAsIHBhdGNod29yayBgciBhcy5jaGFyYWN0ZXIocGFja2FnZVZlcnNpb24oInBhdGNod29yayIpKWAsIGxtZTQgYHIgaWYgKEhBU19MTUVSKSBhcy5jaGFyYWN0ZXIocGFja2FnZVZlcnNpb24oImxtZTQiKSkgZWxzZSAibm8gZGlzcG9uaWJsZSJgLCBsbWVyVGVzdCBgciBpZiAoSEFTX0xNRVIpIGFzLmNoYXJhY3RlcihwYWNrYWdlVmVyc2lvbigibG1lclRlc3QiKSkgZWxzZSAibm8gZGlzcG9uaWJsZSJgLmByIGNpdGUoInJjb3JlIilgIFNpIHNlIG1vZGlmaWNhIGVsIGFyY2hpdm8gZGUgZGF0b3MsIGJhc3RhIHZvbHZlciBhIGNvbXBpbGFyIGVsIGRvY3VtZW50by4NCg0KKipEaXNwb25pYmlsaWRhZCBkZSBkYXRvcyB5IGRlIGPDs2RpZ28uKiogTG9zIGRhdG9zIGFuYWxpemFkb3Mgc29uIGxvcyBkZSBgciBSJGFyY2hpdm9gLiBDYW1iaWFuZG8gZWwgcGFyw6FtZXRybyBgZ3VhcmRhcl9saW1waW9zYCBhIGBUUlVFYCBzZSBlc2NyaWJlIGxhIGJhc2UgZGVwdXJhZGEgKGBkYXRvc19saW1waW9zX2FyZWFfZm9saWFyLmNzdmApLg0KDQojIFJlZmVyZW5jaWFzIHsudW5udW1iZXJlZH0NCg0KYGBge3IgbGlzdGFfcmVmcywgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9DQpjYXQoJzxvbCBjbGFzcz0icmVmcyI+XG4nKQ0KZm9yIChrIGluIC5jaXQkb3JkZW4pIHsNCiAgciA8LSBSRUZbW2tdXQ0KICBlbmxhY2UgPC0gaWYgKCFpcy5uYShyJGRvaSkpIHBhc3RlMCgnIDxhIGhyZWY9Imh0dHBzOi8vZG9pLm9yZy8nLCByJGRvaSwgJyI+aHR0cHM6Ly9kb2kub3JnLycsIHIkZG9pLCAnPC9hPicpIGVsc2UgaWYgKCFpcy5uYShyJHVybCkpIHBhc3RlMCgnIDxhIGhyZWY9IicsIHIkdXJsLCAnIj4nLCByJHVybCwgJzwvYT4nKSBlbHNlICIiDQogIGNhdCgnPGxpPicsIHIkdGV4dG8sIGVubGFjZSwgJzwvbGk+XG4nLCBzZXAgPSAiIikNCn0NCmNhdCgnPC9vbD5cbicpDQpgYGANCg0KIyBJbmZvcm1hY2nDs24gc3VwbGVtZW50YXJpYSB7LnVubnVtYmVyZWR9DQoNCiMjIEN1bXBsaW1pZW50byBkZWwgcHJvdG9jb2xvIGRlIGxhIGd1w61hIHsudW5udW1iZXJlZH0NCg0KYGBge3IgdGFiX3Byb3RvY29sbywgcmVzdWx0cz0nYXNpcyd9DQpvayA8LSBmdW5jdGlvbih4KSBpZmVsc2UoeCwgIuKclCBjdW1wbGUiLCAi4pyYIG5vIGN1bXBsZSIpDQpuX2hvamFfYXJiIDwtIHRhYmxlKGRhdG9zJGFyYm9sKQ0KdHByIDwtIGRhdGEuZnJhbWUoDQogIFJlcXVpc2l0byA9IGMoIkFsIG1lbm9zIDIgw6FyYm9sZXMgYSBwbGVubyBzb2wgeSAyIGEgbGEgc29tYnJhIiwgIjEwIGhvamFzIHBvciDDoXJib2wiLCAiNSDDoXJib2xlcyBwb3IgZ3J1cG8iLCAiw4FyZWEgbWVkaWRhIGVuIHRvZGFzIGxhcyBob2phcyIsICJJRCBjb24gZm9ybWF0byBHI19UIyAocC4gZWouIEczX1QyKSIsDQogICAgICAgICAgICAgICAgIkNvbHVtbmFzIGRlIGxhIHBsYW50aWxsYSAoZ3J1cG8sIGlkX2FyYm9sLCBmZWNoYSwgb2JzZXJ2YWNpb25lcykiLCAiQ29vcmRlbmFkYXMgZW4gZ3JhZG9zIGRlY2ltYWxlcyBjb24gdW4gbWlzbW8gc2VwYXJhZG9yIiwgIk5pbmfDum4gw6FyYm9sIG1lZGlkbyBkb3MgdmVjZXMiKSwNCiAgRXN0YWRvID0gYyhvayhtaW4oUiRuX3NvbF90b3QsIFIkbl9zb21fdG90KSA+PSAyKSwgb2soYWxsKG5faG9qYV9hcmIgPT0gMTApKSwgb2soUiRuX2FyYiA9PSA1KSwgb2soUiRuX2ZhbHRhID09IDApLCBvayhhbGwoZ3JlcGwoIl5HWzAtOV0rX1RbMC05XSskIiwgZGF0b3MkYXJib2xfcmF3KSkpLA0KICAgICAgICAgICAgIG9rKGxlbmd0aChSJGNvbHNfcGxhbnRpbGxhX2ZhbHRhbikgPT0gMCksIG9rKFIkbl9jb29yZF9taWxlcyA9PSAwKSwgb2sobnJvdyhSJGR1cF9hcmJvbCkgPT0gMCkpLA0KICBPYnNlcnZhY2nDs24gPSBjKHBhc3RlMChSJG5fc29sX3RvdCwgIiBzb2wgLyAiLCBSJG5fc29tX3RvdCwgIiBzb21icmEiKSwgcGFzdGUwKFIkaG9qYXNfeF9hcmJvbFsxXSwgIuKAkyIsIFIkaG9qYXNfeF9hcmJvbFsyXSwgIiBob2phcyIpLCBwYXN0ZTAoUiRuX2FyYiwgIiDDoXJib2xlcyIpLA0KICAgICAgICAgICAgICAgICAgcGFzdGUwKFIkbl9mYWx0YSwgIiBwZW5kaWVudGVzIiksICJsb3MgaWRlbnRpZmljYWRvcmVzIHNvbiBUMeKAplQiLCBwYXN0ZTAoImZhbHRhbjogIiwgaWZlbHNlKGxlbmd0aChSJGNvbHNfcGxhbnRpbGxhX2ZhbHRhbiksIHBhc3RlKFIkY29sc19wbGFudGlsbGFfZmFsdGFuLCBjb2xsYXBzZSA9ICIsICIpLCAi4oCUIikpLA0KICAgICAgICAgICAgICAgICAgcGFzdGUwKFIkbl9jb29yZF9taWxlcywgIiBmaWxhcyBjb24gc2VwYXJhZG9yIGRlIG1pbGVzIChyZWNvbnN0cnVpZGFzKSIpLCBwYXN0ZTAobnJvdyhSJGR1cF9hcmJvbCksICIgcGFyZXMgYSBtZW5vcyBkZSAiLCBwYXJhbXMkZGlzdF9kdXBsaWNhZG9fbSwgIiBtIikpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQp0cHIkT2JzZXJ2YWNpw7NuWzVdIDwtIHBhc3RlMCgibG9zIGlkZW50aWZpY2Fkb3JlcyBzb24gIiwgcGFzdGUoaGVhZChzb3J0KHVuaXF1ZShkYXRvcyRhcmJvbCkpLCAzKSwgY29sbGFwc2UgPSAiLCAiKSwgIuKApiIpDQpjYXQodGNhcCgicHJvdG9jb2xvIiwgIkN1bXBsaW1pZW50byBkZSBsb3MgcmVxdWlzaXRvcyBkZSBsYSBndcOtYSBkZSBjYW1wbyIsICJMYXMgZGVzdmlhY2lvbmVzIHNlIGRlY2xhcmFuOyBubyBpbXBpZGVuIGVsIGFuw6FsaXNpcywgcGVybyBjb25kaWNpb25hbiBzdSBpbnRlcnByZXRhY2nDs24uIikpDQp0YWJsYSh0cHIsIGFsaWduID0gImxjbCIpDQpgYGANCg0KIyMgQmFzZSBkZSBkYXRvcyBob2phIGEgaG9qYSB7LnVubnVtYmVyZWR9DQoNCmBgYHtyIHRhYl9kYXRvcywgcmVzdWx0cz0nYXNpcyd9DQp0ZDIgPC0gZGF0YS5mcmFtZShBcmNoaXZvID0gZGF0b3MkYXJjaGl2bywgw4FyYm9sID0gZGF0b3MkYXJib2wsIEV4cG9zaWNpw7NuID0gYXMuY2hhcmFjdGVyKGRhdG9zJGV4cG9zaWNpb24pLCBgTGFkbyAxIChtbSlgID0gZngoZGF0b3MkbGFkbzEsIDApLCBgTGFkbyAyIChtbSlgID0gZngoZGF0b3MkbGFkbzIsIDApLA0KICAgICAgICAgICAgICAgICAgYE1hcmNvIChjbcKyKWAgPSBmeChkYXRvcyRtYXJjb19jbTIsIDEpLCBgw4FyZWEgcmVnaXN0cmFkYSAoY23CsilgID0gZngoZGF0b3MkYXJlYV9vcmlnLCAyKSwgRXN0YWRvID0gZGF0b3MkZXN0YWRvLCBgw4FyZWEgdXNhZGEgKGNtwrIpYCA9IGZ4KGRhdG9zJGFyZWFfZiwgMiksDQogICAgICAgICAgICAgICAgICBPcmlnZW4gPSBpZmVsc2UoaXMubmEoZGF0b3Mkb3JpZ2VuKSwgIuKAlCIsIGRhdG9zJG9yaWdlbiksIGNoZWNrLm5hbWVzID0gRkFMU0UsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCmNhdCh0Y2FwKCJkYXRvcyIsICJCYXNlIGRlIGRhdG9zIGRlcHVyYWRhICh1bmEgZmlsYSBwb3IgaG9qYSkiLCAiwqvDgXJlYSB1c2FkYcK7IGVzIGxhIG1lZGlkYSBvLCBzaSBlc3RhYmEgcGVuZGllbnRlLCBsYSBlc3RpbWFkYSBjb24gZWwgbW9kZWxvIGRlbCBtYXJjbyAoc29sbyBwYXJhIGVsIGFuw6FsaXNpcyBkZSBzZW5zaWJpbGlkYWQgQykuIikpDQpjYXQoJzxkaXYgc3R5bGU9Im1heC1oZWlnaHQ6NDMwcHg7b3ZlcmZsb3c6YXV0byI+XG4nKTsgdGFibGEodGQyLCBhbGlnbiA9ICJsbGNycnJybHJsIik7IGNhdCgnPC9kaXY+XG4nKQ0KYGBgDQoNCiMjIFZlcmlmaWNhY2nDs24gZGUgbG9zIERPSSBjb24gQ3Jvc3NyZWYgey51bm51bWJlcmVkfQ0KDQpgYGB7ciB0YWJfZG9pLCByZXN1bHRzPSdhc2lzJ30NCm5vcm1fdCA8LSBmdW5jdGlvbihzKSB7IHMgPC0gdG9sb3dlcihpY29udihzLCB0byA9ICJBU0NJSS8vVFJBTlNMSVQiKSk7IHMgPC0gZ3N1YigiW15hLXowLTkgXSIsICIgIiwgcyk7IHcgPC0gdW5pcXVlKHN0cnNwbGl0KHRyaW13cyhnc3ViKCIgKyIsICIgIiwgcykpLCAiICIpW1sxXV0pOyB3W25jaGFyKHcpID4gMF0gfQ0KamFjYyA8LSBmdW5jdGlvbihhLCBiKSBsZW5ndGgoaW50ZXJzZWN0KGEsIGIpKSAvIGxlbmd0aCh1bmlvbihhLCBiKSkNCi5kb2lfZW52IDwtIG5ldy5lbnYoKTsgLmRvaV9lbnYkb2ZmIDwtIEZBTFNFDQp2ZXJpZiA8LSBmdW5jdGlvbihrLCBpKSB7DQogIHIgPC0gUkVGW1trXV07IGJhc2UgPC0gZGF0YS5mcmFtZShOID0gaSwgUmVmZXJlbmNpYSA9IGssIERPSSA9IGlmZWxzZShpcy5uYShyJGRvaSksICLigJQiLCByJGRvaSksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCiAgaWYgKGlzLm5hKHIkZG9pKSkgeyBiYXNlJEVzdGFkbyA8LSAic2luIERPSSAoc2UgZW5sYXphIGEgbGEgVVJMKSI7IHJldHVybihiYXNlKSB9DQogIGlmICghaXNUUlVFKHBhcmFtcyR2ZXJpZmljYXJfZG9pKSB8fCAhSEFTX0pTT04pIHsgYmFzZSRFc3RhZG8gPC0gInZlcmlmaWNhY2nDs24gZGVzYWN0aXZhZGEiOyByZXR1cm4oYmFzZSkgfQ0KICBpZiAoLmRvaV9lbnYkb2ZmKSB7IGJhc2UkRXN0YWRvIDwtICJubyBzZSBwdWRvIGNvbnN1bHRhciAoc2luIGNvbmV4acOzbikiOyByZXR1cm4oYmFzZSkgfQ0KICByZXMgPC0gdHJ5Q2F0Y2goanNvbmxpdGU6OmZyb21KU09OKHBhc3RlMCgiaHR0cHM6Ly9hcGkuY3Jvc3NyZWYub3JnL3dvcmtzLyIsIHIkZG9pKSksIGVycm9yID0gZnVuY3Rpb24oZSkgTlVMTCkNCiAgaWYgKGlzLm51bGwocmVzKSkgLmRvaV9lbnYkb2ZmIDwtIFRSVUUNCiAgaWYgKGlzLm51bGwocmVzKSkgeyBiYXNlJEVzdGFkbyA8LSAibm8gc2UgcHVkbyBjb25zdWx0YXIgKHNpbiBjb25leGnDs24gbyBET0kgbm8gcmVzdWVsdG8pIjsgcmV0dXJuKGJhc2UpIH0NCiAgdHQgPC0gcmVzJG1lc3NhZ2UkdGl0bGVbMV0NCiAgYW4gPC0gdHJ5Q2F0Y2goYXMuaW50ZWdlcihyZXMkbWVzc2FnZSRpc3N1ZWQkYGRhdGUtcGFydHNgWzEsIDFdKSwgZXJyb3IgPSBmdW5jdGlvbihlKSBOQV9pbnRlZ2VyXykNCiAgc2ltIDwtIGphY2Mobm9ybV90KHR0KSwgbm9ybV90KHIkdGl0KSkNCiAgYmFzZSRFc3RhZG8gPC0gaWZlbHNlKHNpbSA+PSAwLjYgJiYgKGlzLm5hKGFuKSB8fCBhYnMoYW4gLSByJGFuaW8pIDw9IDEpLCAi4pyUIGNvaW5jaWRlIGNvbiBDcm9zc3JlZiIsICLinJggcmV2aXNhciIpDQogIGJhc2UNCn0NCnZ0IDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShzZXFfYWxvbmcoLmNpdCRvcmRlbiksIGZ1bmN0aW9uKGkpIHZlcmlmKC5jaXQkb3JkZW5baV0sIGkpKSkNCmNhdCh0Y2FwKCJkb2kiLCAiVmVyaWZpY2FjacOzbiBhdXRvbcOhdGljYSBkZSBsb3MgRE9JIGNpdGFkb3MiLCAiU2UgY29uc3VsdGEgbGEgQVBJIGRlIENyb3NzcmVmIHkgc2UgY29tcGFyYSBlbCB0w610dWxvIHkgZWwgYcOxbzsgcmVxdWllcmUgY29uZXhpw7NuIGEgaW50ZXJuZXQgYWwgY29tcGlsYXIuIikpDQp0YWJsYSh2dCwgYWxpZ24gPSAicmxsbGwiKQ0KYGBgDQoNCmBgYHtyIHNlc2lvbiwgZWNobz1UUlVFfQ0Kc2Vzc2lvbkluZm8oKQ0KYGBgDQo=