1 Desarrollamos las estimaciones de las tipologías de proyectos

La Tabla 1 presenta los primeros 10 registros del dataset original, que ilustran la variedad de nudos críticos identificados en las comunas del Estado Mérida durante el período de estudio. Se observa que la comuna “SIMON BOLÍVAR” registró tres nudos críticos diferentes bajo el mismo código de ubicación geográfica (UBIGEO 140102) y código de circuito comunal (CC 14-01-2007): infraestructura (drenajes), electricidad y telecomunicaciones. Esta multiplicidad de problemáticas sugiere que esta comuna enfrenta desafíos simultáneos en múltiples frentes, lo que podría requerir una intervención coordinada y multisectorial.

El sistema de codificación utilizado evidencia la estructura jerárquica de la planificación territorial. El identificador único ID_COMUNA, compuesto por la combinación de COD_UBIGEO (que identifica ubicación geográfica a nivel municipal y parroquial) y COD_CC (que identifica el circuito comunal específico), permite una georreferenciación precisa de cada proyecto y facilita el análisis territorial de las intervenciones. Estos ejemplos iniciales evidencian la heterogeneidad de nudos críticos de las comunas y la necesidad de abordajes diferenciados en la planificación de las ACA. La recurrencia de ciertas tipologías de problemas, particularmente aquellos relacionados con infraestructura básica y servicios públicos, sugiere patrones comunes que merecen atención especial en el análisis posterior de correlaciones y efectividad de proyectos.

## -------------**Creación de variables dummy y resumen por comuna**---------------------##
df_raw <- read_excel ("C:/Users/william/Desktop/monografia aca merida/datos/ACA Modelaje R Final.xlsx", 
    sheet = "Resumen") %>%
  mutate(ID_COMUNA = paste0(COD_UBIGEO, "-", COD_CC))

# Crear dummies desde las variables cualitativas
df_dummies <- df_raw %>%
  dummy_cols(
    select_columns = c(
      "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG",
      "CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION",
      "CLASIFICACION_DEL_PROYECTO"
    ),
    remove_first_dummy = FALSE
  )

# ---------------------Primera tabla - Variables originales (primeros 10 registros)---------------------
tabla1 <- df_raw %>%
  select(
    `Nudo Críticos por Tipología CFG` = CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
    `Nudos Críticos por Tipología de Gobierno` = CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
    `COD UBIGEO` = COD_UBIGEO,
    `COD CC` = COD_CC,
    COMUNA,
    `ID COMUNA` = ID_COMUNA
  ) %>%
  head(10)

kable(tabla1, caption = "Tabla 1. Primeros 10 registros de datos originales") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), font_size = 10) %>%
  footnote(general = "Nota. ID_COMUNA = Identificador único de comuna y combinación del código UBIGEO y código SITUR de cada comuna; COD_UBIGEO = Código de ubicación geográfica a nivel nacional y Mérida.",
           general_title = "")
Tabla 1. Primeros 10 registros de datos originales
Nudo Críticos por Tipología CFG Nudos Críticos por Tipología de Gobierno COD UBIGEO COD CC COMUNA ID COMUNA
INFRAESTRUCTURA DRENAJES 140102 14-01-2007 COMUNA SIMON BOLÍVAR. 140102-14-01-2007
ELECTRICIDAD ELECTRICIDAD 140102 14-01-2007 COMUNA SIMON BOLÍVAR. 140102-14-01-2007
TELECOMUNICACIONES TELECOMUNICACIONES 140102 14-01-2007 COMUNA SIMON BOLÍVAR. 140102-14-01-2007
MANEJO INTEGRAL DEL AGUA AGUA POTABLE 140102 C-MIX-2021-01-0003 COMUNA ETERNO GIGANTE 140102-C-MIX-2021-01-0003
VIVIENDA VIVIENDA 140102 C-MIX-2021-01-0003 COMUNA ETERNO GIGANTE 140102-C-MIX-2021-01-0003
MANEJO INTEGRAL DEL AGUA AGUA RESIDUAL 140102 C-MIX-2018-11-0084 COMUNA LUZ DEL ALBA 140102-C-MIX-2018-11-0084
AMBIENTE CANALIZACION 140102 C-MIX-2018-11-0084 COMUNA LUZ DEL ALBA 140102-C-MIX-2018-11-0084
INFRAESTRUCTURA VIVIENDA 140102 C-MIX-2018-11-0084 COMUNA LUZ DEL ALBA 140102-C-MIX-2018-11-0084
MANEJO INTEGRAL DEL AGUA AGUA POTABLE 140102 C-MIX-2021-02-0005 COMUNA FRANCISCO DE MIRANDA 140102-C-MIX-2021-02-0005
INFRAESTRUCTURA DRENAJES 140102 C-MIX-2021-02-0005 COMUNA FRANCISCO DE MIRANDA 140102-C-MIX-2021-02-0005
Nota. ID_COMUNA = Identificador único de comuna y combinación del código UBIGEO y código SITUR de cada comuna; COD_UBIGEO = Código de ubicación geográfica a nivel nacional y Mérida.
#------------------------Segunda tabla - Variables importantes (primeros 10 registros)--------------------
tabla2 <- df_raw %>%
  select(
    n_proyectos,
    PLAZOS,
    CLASIFICACION_DEL_PROYECTO,
    TIPOLOGIA_CFG_NUM,
    GOBERNACION_NUM,
    RATIO_ACA_PROYECTO_CULMINADO,
    Clasificacion_Actores_institucionales
  ) %>%
  head(10)

kable(tabla2, caption = "Tabla 2. Primeros 10 registros de variables de análisis principales") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), font_size = 10)
Tabla 2. Primeros 10 registros de variables de análisis principales
n_proyectos PLAZOS CLASIFICACION_DEL_PROYECTO TIPOLOGIA_CFG_NUM GOBERNACION_NUM RATIO_ACA_PROYECTO_CULMINADO Clasificacion_Actores_institucionales
4 1 3 5 5 3 2
4 1 1 4 6 1 2
4 1 1 13 17 1 2
4 2 3 6 2 3 2
4 2 1 16 21 1 1
4 1 1 6 3 1 2
4 1 1 1 4 1 1
4 1 3 5 21 3 3
4 2 1 6 2 1 2
4 2 1 5 5 1 2

Posteriormente, las variables cualitativas fueron codificadas y operacionalizadas para el análisis cuantitativo, como se detalló en el Marco Metodológico.

2 Análisis de tendencia central y de dispersión de las variables originales

Para complementar el análisis de las variables ordinales y categóricas, las Tablas de frecuencias muestra la distribución de las mismas y porcentajes de las variables clave. Los datos revelan que el 76,77% de las comunas participaron en las cuatro consultas nacionales, demostrando un compromiso sostenido con el proceso de planificación. Sin embargo, casi la mitad de los proyectos (48,99%) fueron catalogados como “No Considerados”, indicando una significativa desconexión entre la identificación de problemas y su posterior priorización ejecutiva. Solo el 25,25% de los proyectos alcanzaron el estado de “Culminados”. La planificación temporal muestra que la abrumadora mayoría de los proyectos (83,84%) se diseñaron para un horizonte de tiempo de mediano plazo (1-2 años), coherente con la naturaleza estructural de los nudos críticos. Respecto a los actores institucionales, se observa una predominancia de la gestión por parte de entidades e instituciones nacionales y estadales (51,52%), mientras que la participación de actores municipales/comunales (19,19%) y privados ( 3,54%) es considerablemente menor.

#-------------------- Análisis de tendencia central y dispersión--------------------#
analisis_tendencia <- df_raw %>%
  select(n_proyectos, PLAZOS,CLASIFICACION_DEL_PROYECTO, TIPOLOGIA_CFG_NUM, GOBERNACION_NUM, 
         RATIO_ACA_PROYECTO_CULMINADO, Clasificacion_Actores_institucionales) %>%
  psych::describe() %>%
  rownames_to_column("Variable") %>%
  select(Variable, n, mean, sd, min, max, median, skew, kurtosis)

# Análisis de frecuencias para variables categóricas n_proyectos
frecuencias_n_proyectos <- df_raw %>%
  count(n_proyectos) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2)) %>%
  rename(Frecuencia = n, Categoría = n_proyectos)
kable(frecuencias_n_proyectos, caption = "Distribución de frecuencias para la variable n_proyectos") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución de frecuencias para la variable n_proyectos
Categoría Frecuencia Porcentaje
2 6 3.03
3 40 20.20
4 152 76.77
# Análisis de frecuencias para variables categóricas Clasificación del proyecto
frecuencias_clasificacion_proyecto <- df_raw %>%
  count(CLASIFICACION_DEL_PROYECTO) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2)) %>%
  rename(Frecuencia = n, Categoría = CLASIFICACION_DEL_PROYECTO)
kable(frecuencias_clasificacion_proyecto, caption = "Distribución de frecuencias para la variable CLASIFICACION_DEL_PROYECTO") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución de frecuencias para la variable CLASIFICACION_DEL_PROYECTO
Categoría Frecuencia Porcentaje
1 97 48.99
2 3 1.52
3 48 24.24
4 50 25.25
# Análisis de frecuencias para variables categóricas Plazos
frecuencias_plazos <- df_raw %>%
  count(PLAZOS) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2)) %>%
  rename(Frecuencia = n, Categoría = PLAZOS)

kable(frecuencias_plazos, caption = "Distribución de frecuencias para la variable PLAZOS") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución de frecuencias para la variable PLAZOS
Categoría Frecuencia Porcentaje
0 6 3.03
1 26 13.13
2 166 83.84
# Análisis de RATIO_ACA_PROYECTO_CULMINADO
frecuencias_ratio <- df_raw %>%
  count(RATIO_ACA_PROYECTO_CULMINADO) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2)) %>%
  rename(Frecuencia = n, Categoría = RATIO_ACA_PROYECTO_CULMINADO)

kable(frecuencias_ratio, caption = "Distribución de frecuencias para la variable RATIO_ACA_PROYECTO_CULMINADO") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución de frecuencias para la variable RATIO_ACA_PROYECTO_CULMINADO
Categoría Frecuencia Porcentaje
1 97 48.99
2 3 1.52
3 48 24.24
4 50 25.25
# Análisis de actores institucionales
frecuencias_actores <- df_raw %>%
  count(Clasificacion_Actores_institucionales) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2)) %>%
  rename(Frecuencia = n, Categoría = Clasificacion_Actores_institucionales)

kable(frecuencias_actores, caption = "Distribución de frecuencias para la variable Clasificacion_Actores_institucionales") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Distribución de frecuencias para la variable Clasificacion_Actores_institucionales
Categoría Frecuencia Porcentaje
1 51 25.76
2 102 51.52
3 38 19.19
4 7 3.54
##--------------------------Trafico de frecuencias---------------------------

# Combinar todos los dataframes de frecuencias en uno solo
plot_data <- bind_rows(
  frecuencias_n_proyectos %>% mutate(Variable = "Número de Consultas (n_proyectos)"),
  frecuencias_clasificacion_proyecto %>% mutate(Variable = "Estado del Proyecto"),
  frecuencias_ratio %>% mutate(Variable = "Ratio de Efectividad"),
  frecuencias_plazos %>% mutate(Variable = "Plazo de Ejecución (PLAZOS)"),
  frecuencias_actores %>% mutate(Variable = "Actor Institucional Principal")
) %>%
  mutate(Categoría = as.factor(Categoría))

# Definir etiquetas descriptivas para cada categoría
plot_data <- plot_data %>%
  mutate(
    Etiqueta_Categoria = case_when(
      Variable == "Estado del Proyecto" ~ case_when(
        Categoría == 1 ~ "1 - No Considerado",
        Categoría == 2 ~ "2 - No Culminado",
        Categoría == 3 ~ "3 - En Ejecución",
        Categoría == 4 ~ "4 - Culminado"
      ),
      Variable == "Ratio de Efectividad" ~ case_when(
        Categoría == 1 ~ "1 - Muy Baja",
        Categoría == 2 ~ "2 - Baja",
        Categoría == 3 ~ "3 - Media",
        Categoría == 4 ~ "4 - Alta"
      ),
      Variable == "Plazo de Ejecución (PLAZOS)" ~ case_when(
        Categoría == 0 ~ "0 - Sin Dato",
        Categoría == 1 ~ "1 - Corto Plazo",
        Categoría == 2 ~ "2 - Mediano Plazo"
      ),
      Variable == "Actor Institucional Principal" ~ case_when(
        Categoría == 1 ~ "1 - Ministerio",
        Categoría == 2 ~ "2 - Gob. Nac/Est.",
        Categoría == 3 ~ "3 - Mun./Comunal",
        Categoría == 4 ~ "4 - Privado"
      ),
      Variable == "Número de Consultas (n_proyectos)" ~ as.character(Categoría),
      TRUE ~ as.character(Categoría)
    )
  )

# Calcular el límite superior del eje Y para asegurar que las etiquetas encajen
y_max <- max(plot_data$Frecuencia) * 1.1

# Crear el gráfico de barras con facetas mejorado
ggplot(plot_data, aes(x = Etiqueta_Categoria, y = Frecuencia, fill = Etiqueta_Categoria)) +
  geom_col(show.legend = FALSE) +  
  geom_text(aes(label = Frecuencia), vjust = -0.5, size = 3.5) +  
  facet_wrap(~ Variable, scales = "free_x", ncol = 5) + 
  scale_fill_viridis_d() + 
  labs(
    title = "Distribución de Frecuencias de Variables Clave",
    x = "Categorías",
    y = "Frecuencia (Número de Proyectos)",
    caption = "Elaboración Propia - William Gutierrez"  
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 9),  
    strip.text = element_text(face = "bold", size = 10), 
    plot.title = element_text(hjust = 0.5, face = "bold"),  
    plot.caption = element_text(hjust = 1, size = 9, face = "italic")  
  ) +
  ylim(0, y_max)  

El Gráfico de Distribución de Frecuencias de Variables Claves representa gráficamente estas distribuciones de frecuencia, permitiendo una comparación inmediata de las proporciones entre categorías.

El gráfico confirma el patrón identificado en la tabla, destacando visualmente la predominancia de: 1) la participación en cuatro consultas, 2) los proyectos no considerados, 3) los plazos de ejecución medianos, y 4) la gestión por actores nacionales/estatales. La representación gráfica facilita la identificación de desequilibrios en la distribución de las variables, particularmente la brecha entre proyectos no considerados y culminado.

3 Frecuencia global por cada tipología de CFG y Gobernación, ¿qué problema es el más común?

Para establecer cuáles son los nudos críticos más recurrentes en todo el Estado Mérida, primero calculamos la frecuencia absoluta y relativa de cada tipología CFG y de gobernación. Esto nos permite identificar las áreas de mayor concentración de problemas y priorizar las líneas de análisis posteriores.

4 Frecuencias de Consejo Federal de Gobierno (CFG)

Las Gráficas donde se presenta un gráfico de Pareto que analiza la distribución de los nudos críticos según el número de proyectos ACA identificados para cada tipología CFG, es crucial para priorizar la asignación de recursos y esfuerzos a la planificación, ya que revela que los problemas no están distribuidos de manera uniforme, sino que se concentran en unas pocas áreas críticas.

Al revisar los gráficos, se puede ver que el 62,6% de todos los proyectos se concentra en sólo cuatro tipologías. El Manejo Integral del Agua es la problemática principal, representando por sí sola más de una cuarta parte (27,27%) de todos los proyectos ACA.

Esto indica que la crisis hídrica no es un problema aislado, sino la principal prioridad de las comunidades merideñas, superando con creces a la segunda tipología, Vialidad (15,15%), por un margen de 12 puntos porcentuales. La curva de porcentaje acumulado (línea amarilla y roja del interactivo) muestra una pendiente pronunciada al inicio, que se va suavizando después de las primeras 7 tipologías, confirmando el principio de Pareto o 80/20 (El 20% de las causas explican el 80% de los efectos): aproximadamente el 80% de los proyectos (80,81%, siendo exactos) se concentra en resolver sólo el 44% de las tipologías (7 de 17), es decir, un pequeño número de causas.

Este hallazgo sugiere que una estrategia de intervención pública focalizada en estas siete áreas principales podría resolver la gran mayoría de los problemas identificados con una mayor eficiencia en el uso de recursos.

De manera similar, al realizar el análisis desde una perspectiva territorial confirma y refuerza los hallazgos del análisis por proyectos. Manejo Integral del Agua mantiene su posición dominante al afectar 43 comunas (23,76% del total), lo que indica que este problema no se limita a áreas específicas, sino que tiene carácter sistémico a nivel estatal, en la Tabla 5 existe una notable consistencia en el ordenamiento de las primeras posiciones entre ambas tablas valida la robustez del diagnóstico, las primeras 4 tipologías mantienen el mismo orden tanto por proyectos como por comunas, además las primeras 6 tipologías muestran variaciones mínimas en su posicionamiento. El 74.03% de todas las afectaciones territoriales se concentra en las primeras 6 tipologías

La distribución territorial revela que los problemas principales del Estado Mérida no son fenómenos localizados sino deficiencias estructurales generalizadas:

• Manejo Integral del Agua está presente en más del 67,18% de las comunas estudiadas

• Vialidad afecta a 27 comunas, representando una distribución territorial considerable

• Vivienda y Electricidad mantienen presencia significativa con 21 y 18 comunas respectivamente.

##-------------------------------Resumen CFG por Comuna-------------------------------##
cfg_cols <- df_dummies %>% 
  select(starts_with("CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_")) %>% 
  names()

df_cfg_summary <- df_dummies %>%
  group_by(ID_COMUNA) %>%
  summarise(
    n_proyectos = n(),
    across(all_of(cfg_cols), list(
      count = ~ sum(.x, na.rm = TRUE),
      pct = ~ sum(.x, na.rm = TRUE) / n() * 100
    ))
  ) %>%
  ungroup()

##-----------------------Resumen de Gobernación por comuna----------------------
gob_cols <- df_dummies %>% 
  select(starts_with("CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_")) %>% 
  names()

df_gob_summary <- df_dummies %>%
  group_by(ID_COMUNA) %>%
  summarise(
    n_proyectos = n(),
    across(all_of(gob_cols), list(
      count = ~ sum(.x, na.rm = TRUE),
      pct = ~ sum(.x, na.rm = TRUE) / n() * 100
    ))
  ) %>%
  ungroup()

##------------------------Análisis de frecuencias-------------------------------

# Función mejorada para análisis completo
analizar_frecuencia <- function(data, var, fill_color, line_color, titulo, tipo = "proyectos") {
  # Determinar nombre de etiqueta según tipo
  y_label <- ifelse(tipo == "proyectos", "Número de proyectos", "Número de comunas")
  
  # Frecuencias globales
  freq <- data %>%
    count({{var}}, name = "n") %>%
    arrange(desc(n)) %>%
    mutate(
      pct = n / sum(n) * 100,
      cum_pct = cumsum(pct),
      etiqueta = paste0(n, "\n(", round(pct, 1), "%)")
    )
  
  # Gráfico combinado
  plot <- ggplot(freq, 
         aes(x = reorder({{var}}, n), y = n)) +
    geom_col(fill = fill_color, alpha = 0.8) +
    geom_text(aes(label = etiqueta), 
              hjust = -0.1, size = 3.5, color = "black", lineheight = 0.8) +
    geom_line(aes(y = cum_pct * max(n) / 100), 
              group = 1, color = line_color, size = 0.8) +
    geom_point(aes(y = cum_pct * max(n) / 100), 
               color = line_color, size = 2) +
    scale_y_continuous(
      name = y_label,
      sec.axis = sec_axis(~ . * 100 / max(freq$n), 
                         name = "Porcentaje acumulado (%)",
                         labels = scales::percent_format(scale = 1))
    ) +
    coord_flip() +
    labs(
      title = titulo,
      subtitle = "Barras: frecuencia absoluta | Texto: conteo y % individual | Línea: % acumulado",
      x = NULL
    ) +
    theme_minimal(base_size = 12) +
    expand_limits(y = max(freq$n) * 1.15)
  
  return(list(freq = freq, plot = plot))
}

# Función mejorada para frecuencia por comuna
analizar_frecuencia_comuna <- function(data, var, fill_color, line_color, titulo) {
  freq_comuna <- data %>%
    distinct(ID_COMUNA, {{var}}) %>%  
    count({{var}}, name = "n_comunas") %>%
    arrange(desc(n_comunas)) %>%
    mutate(
      pct_comunas = n_comunas / sum(n_comunas) * 100,
      cum_pct = cumsum(pct_comunas),
      etiqueta = paste0(n_comunas, "\n(", round(pct_comunas, 1), "%)")
    )
  
  # Gráfico combinado
  plot <- ggplot(freq_comuna, 
         aes(x = reorder({{var}}, n_comunas), y = n_comunas)) +
    geom_col(fill = fill_color, alpha = 0.8) +
    geom_text(aes(label = etiqueta), 
              hjust = -0.1, size = 3.5, color = "black", lineheight = 0.8) +
    geom_line(aes(y = cum_pct * max(n_comunas) / 100),
              group = 1, color = line_color, size = 0.8) +
    geom_point(aes(y = cum_pct * max(n_comunas) / 100),
               color = line_color, size = 2) +
    scale_y_continuous(
      name = "Número de comunas",
      sec.axis = sec_axis(~ . * 100 / max(freq_comuna$n_comunas),
                         name = "Porcentaje acumulado (%)",
                         labels = scales::percent_format(scale = 1))
    ) +
    coord_flip() +
    expand_limits(y = max(freq_comuna$n_comunas) * 1.15) +
    labs(
      title = titulo,
      subtitle = "Barras: frecuencia absoluta | Texto: conteo y % de comunas | Línea: % acumulado",
      x = NULL
    ) +
    theme_minimal(base_size = 12)
  
  return(list(freq_comuna = freq_comuna, plot = plot))
}
## ----------------------------Análisis para CFG--------------------------------

# Conteo y proporciones globales por Tipologia CFG

cfg_global_proyectos <- analizar_frecuencia(
  df_dummies,
  CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
  "darkblue", "gold",
  "Frecuencia global de tipologías CFG (Proyectos)"
)
cfg_global_comunas <- analizar_frecuencia_comuna(
  df_dummies,
  CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
  "darkblue", "gold",
  "Frecuencia de tipologías CFG por comuna"
)


##----------------------------Mostrar resultados-------------------------------------
# Conteo y proporciones globales sobre la variable original
freq_cfg <- df_dummies %>%
  count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "n") %>%
  arrange(desc(n)) %>%
  mutate(
    pct     = n / sum(n) * 100,
    cum_pct = cumsum(pct)
  )
#-------------------------Top 10 barras simples--------------------------------
freq_cfg %>%
  slice(1:10) %>%
  ggplot(aes(
    x = reorder(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, n),
    y = n
  )) +
    geom_col(fill = "darkblue") +
    coord_flip() +
    labs(
      title = "Top 10 tipologías CFG más frecuentes",
      x     = "Tipología CFG",
      y     = "Número de proyectos"
    ) +
    theme_minimal()

##--------------------Grafico de frecuencias de tipologías CFG------------------
print(cfg_global_proyectos$plot)

#--------Frecuencia absoluta y relativa de comunas por tipología CFG---------
freq_cfg_comuna <- df_dummies %>%
  distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG) %>%
  count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "n_comunas") %>%
  arrange(desc(n_comunas)) %>%
  mutate(
    pct_comunas = n_comunas / sum(n_comunas) * 100,
    cum_pct     = cumsum(pct_comunas)
  )

#---------------------------------Top 10 comunas--------------------------------
freq_cfg_comuna %>%
  slice(1:10) %>%
  ggplot(aes(
    x = reorder(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, n_comunas),
    y = n_comunas
  )) +
    geom_col(fill = "darkblue") +
    coord_flip() +
    labs(
      title = "Top 10 tipologías CFG por número de comunas",
      x     = "Tipología CFG",
      y     = "Número de comunas"
    ) +
    theme_minimal()

##----------------Grafico de frecuencias de tipologías CFG--------------------
print(cfg_global_comunas$plot)

# ==============================================================================
#  TABLA COMPLETA DE FRECUENCIAS CFG POR PROYECTOS
# ==============================================================================

crear_tabla_cfg_proyectos <- function(data) {
  
  # Calcular frecuencias
  tabla_cfg <- data %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "n_proyectos") %>%
    arrange(desc(n_proyectos)) %>%
    mutate(
      porcentaje = round(n_proyectos / sum(n_proyectos) * 100, 2),
      pct_acumulado = round(cumsum(porcentaje), 2),
      ranking = row_number()
    ) %>%
    rename(
      "Ranking" = ranking,
      "Tipología CFG" = CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
      "N° Proyectos" = n_proyectos,
      "Porcentaje (%)" = porcentaje,
      "% Acumulado" = pct_acumulado
    )
  
  # Crear tabla formateada con kableExtra
  tabla_final <- tabla_cfg %>%
    kable(
      caption = "Tabla 4.1: Distribución de Frecuencias de Tipologías CFG por Número de Proyectos",
      align = c("c", "l", "c", "c", "c"),
      format = "html"
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 12
    ) %>%
    column_spec(1, bold = TRUE, color = "white", background = "#2c3e50") %>%
    column_spec(2, width = "20em") %>%
    column_spec(3:5, width = "8em") %>%
    row_spec(1:4, background = "#e8f4fd") %>%  # Resaltar top 4
    add_header_above(c(" " = 2, "Frecuencias Absolutas y Relativas" = 3)) %>%
    footnote(
      general = c(
        "Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025",
        "Nota: Las primeras 4 tipologías concentran el 62.6% de todos los nudos críticos"
      ),
      general_title = "",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = tabla_cfg, tabla = tabla_final))
}

# ==============================================================================
#  TABLA COMPLETA DE FRECUENCIAS CFG POR COMUNAS
# ==============================================================================

crear_tabla_cfg_comunas <- function(data) {
  
  # Calcular frecuencias por comuna (sin repetir comunas)
  tabla_cfg_comunas <- data %>%
    distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG) %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "n_comunas") %>%
    arrange(desc(n_comunas)) %>%
    mutate(
      porcentaje = round(n_comunas / sum(n_comunas) * 100, 2),
      pct_acumulado = round(cumsum(porcentaje), 2),
      ranking = row_number()
    ) %>%
    rename(
      "Ranking" = ranking,
      "Tipología CFG" = CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
      "N° Comunas" = n_comunas,
      "Porcentaje (%)" = porcentaje,
      "% Acumulado" = pct_acumulado
    )
  
  # Crear tabla formateada
  tabla_final <- tabla_cfg_comunas %>%
    kable(
      caption = "Tabla 4.2: Distribución de Frecuencias de Tipologías CFG por Número de Comunas Afectadas",
      align = c("c", "l", "c", "c", "c"),
      format = "html"
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 12
    ) %>%
    column_spec(1, bold = TRUE, color = "white", background = "#2c3e50") %>%
    column_spec(2, width = "20em") %>%
    column_spec(3:5, width = "8em") %>%
    row_spec(1:4, background = "#e8f4fd") %>%  # Resaltar top 4
    add_header_above(c(" " = 2, "Distribución Territorial" = 3)) %>%
    footnote(
      general = c(
        "Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025",
        "Nota: Una comuna puede tener múltiples tipologías, pero se cuenta una sola vez por tipología"
      ),
      general_title = "",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = tabla_cfg_comunas, tabla = tabla_final))
}

# ==============================================================================
# TABLA COMPARATIVA CFG: PROYECTOS VS COMUNAS
# ==============================================================================

crear_tabla_comparativa_cfg <- function(data) {
  
  # Datos por proyectos
  cfg_proyectos <- data %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "n_proyectos") %>%
    mutate(pct_proyectos = round(n_proyectos / sum(n_proyectos) * 100, 2))
  
  # Datos por comunas
  cfg_comunas <- data %>%
    distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG) %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "n_comunas") %>%
    mutate(pct_comunas = round(n_comunas / sum(n_comunas) * 100, 2))
  
  # Unir ambas tablas
  tabla_comparativa <- cfg_proyectos %>%
    inner_join(cfg_comunas, by = "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG") %>%
    arrange(desc(n_proyectos)) %>%
    mutate(
      ranking = row_number(),
      intensidad = round(n_proyectos / n_comunas, 2)  # Proyectos por comuna promedio
    ) %>%
    select(
      ranking,
      CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
      n_proyectos, pct_proyectos,
      n_comunas, pct_comunas,
      intensidad
    ) %>%
    rename(
      "Rank" = ranking,
      "Tipología CFG" = CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
      "N° Proy." = n_proyectos,
      "% Proy." = pct_proyectos,
      "N° Com." = n_comunas,
      "% Com." = pct_comunas,
      "Intensidad" = intensidad
    )
  
  # Crear tabla formateada
  tabla_final <- tabla_comparativa %>%
    kable(
      caption = "Tabla 4.3: Análisis Comparativo CFG - Proyectos vs Comunas Afectadas",
      align = c("c", "l", rep("c", 5)),
      format = "html",
      digits = 2
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 11
    ) %>%
    column_spec(1, bold = TRUE, color = "white", background = "#2c3e50", width = "3em") %>%
    column_spec(2, width = "15em") %>%
    column_spec(3:7, width = "6em") %>%
    add_header_above(c(" " = 2, "Por Proyectos" = 2, "Por Comunas" = 2, "Indicador" = 1)) %>%
    row_spec(1:3, background = "#ffe6e6") %>%  # Top 3 en rojo suave
    row_spec(4:7, background = "#fff2e6") %>%  # Siguientes 4 en naranja suave
    footnote(
      general = c(
        "Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025",
        "Intensidad = N° Proyectos / N° Comunas (promedio de proyectos por comuna por tipología)"
      ),
      general_title = "",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = tabla_comparativa, tabla = tabla_final))
}

# ==============================================================================
#  TABLA RESUMEN EJECUTIVO CFG (TOP 10)
# ==============================================================================

crear_tabla_resumen_cfg <- function(data) {
  
  # Calcular estadísticas resumidas
  total_proyectos <- nrow(data)
  total_comunas <- n_distinct(data$ID_COMUNA)
  
  resumen_cfg <- data %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "proyectos") %>%
    arrange(desc(proyectos)) %>%
    slice(1:10) %>%  # Solo top 10
    mutate(
      pct_proyectos = round(proyectos / total_proyectos * 100, 1),
      pct_acum = round(cumsum(pct_proyectos), 1)
    ) %>%
    # Agregar datos de comunas
    left_join(
      data %>%
        distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG) %>%
        count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, name = "comunas"),
      by = "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG"
    ) %>%
    mutate(
      pct_comunas = round(comunas / total_comunas * 100, 1),
      posicion = row_number(),
      categoria = case_when(
        posicion <= 3 ~ "🔴 Crítico",
        posicion <= 7 ~ "🟡 Alto",
        TRUE ~ "🟢 Medio"
      )
    ) %>%
    select(
      posicion, categoria,
      CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
      proyectos, pct_proyectos, pct_acum,
      comunas, pct_comunas
    ) %>%
    rename(
      "Pos." = posicion,
      "Nivel" = categoria,
      "Tipología CFG" = CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
      "Proy." = proyectos,
      "%" = pct_proyectos,
      "% Acum." = pct_acum,
      "Com." = comunas,
      "% Com." = pct_comunas
    )
  
  # Crear tabla formateada
  tabla_final <- resumen_cfg %>%
    kable(
      caption = "Tabla 4.4: Resumen Ejecutivo - Top 10 Tipologías CFG Más Críticas",
      align = c("c", "c", "l", rep("c", 5)),
      format = "html"
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 11
    ) %>%
    column_spec(1, bold = TRUE, width = "3em") %>%
    column_spec(2, width = "8em") %>%
    column_spec(3, width = "15em") %>%
    column_spec(4:8, width = "5em") %>%
    add_header_above(c(" " = 3, "Análisis por Proyectos" = 3, "Por Comunas" = 2)) %>%
    footnote(
      general = paste0(
        "Total analizado: ", total_proyectos, " proyectos en ", total_comunas, " comunas. ",
        "El Top 10 concentra el ", round(sum(resumen_cfg$`%`), 1), "% de todos los nudos críticos."
      ),
      general_title = "Nota:",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = resumen_cfg, tabla = tabla_final))
}

## Graficos intereactivos de las frecuencias de Pareto

##=======================Frecuencia Global CFG - Proyectos========================##


# Función CORREGIDA para gráfico interactivo de Pareto HORIZONTAL
crear_pareto_horizontal_interactivo <- function(data, variable, titulo, color_barras = "#2E86AB", color_linea = "#E69F00") {
    
    # Convertir variable a símbolo y luego a nombre
    var_sym <- ensym(variable)
    var_name <- as.character(var_sym)
    
    # Calcular frecuencias usando evaluación tidy
    freq_data <- data %>%
        count(!!var_sym) %>%
        arrange(desc(n)) %>%
        mutate(
            porcentaje = n / sum(n) * 100,
            acumulado = cumsum(porcentaje),
            etiqueta = paste0(
                "Frecuencia: ", n, "\n",
                "Porcentaje: ", round(porcentaje, 1), "%\n",
                "Acumulado: ", round(acumulado, 1), "%"
            ),
            # Crear variable ordenada para el eje Y (horizontal)
            variable_ordenada = reorder(!!var_sym, n)
        )
    
    # Para plotly horizontal, necesitamos Y como categorías ordenadas y X como valores
    freq_data$variable_char <- as.character(freq_data$variable_ordenada)
    freq_data$variable_char <- factor(freq_data$variable_char, 
                                      levels = levels(freq_data$variable_ordenada))
    
    # Calcular el máximo para escalar la línea correctamente
    max_frecuencia <- max(freq_data$n)
    escala_linea <- max_frecuencia / 100
    
    # Crear gráfico interactivo HORIZONTAL
    plot_ly(freq_data) %>%
        add_bars(
            y = ~variable_char,  # Eje Y para las categorías (horizontal)
            x = ~n,              # Eje X para los valores (horizontal)
            name = "Frecuencia",
            orientation = 'h',   # ¡IMPORTANTE: gráfico horizontal!
            marker = list(
                color = color_barras,
                line = list(color = '#1a5276', width = 1)
            ),
            text = ~etiqueta,
            hoverinfo = "text",
            textposition = "none"
        ) %>%
        add_trace(
            y = ~variable_char,
            x = ~acumulado * escala_linea,  # Escalar la línea al mismo rango que las barras
            name = "Porcentaje Acumulado",
            type = 'scatter',
            mode = 'lines+markers',
            line = list(
                color = color_linea, 
                width = 3,
                dash = 'solid'
            ),
            marker = list(
                color = color_linea,
                size = 6,
                symbol = 'circle'
            ),
            yaxis = "y",
            xaxis = "x",
            hoverinfo = "x+text",
            text = ~paste("Acumulado: ", round(acumulado, 1), "%")
        ) %>%
        layout(
            title = list(
                text = titulo,
                x = 0.05,
                font = list(size = 16, color = "#2c3e50")
            ),
            yaxis = list(
                title = "",
                showgrid = FALSE,
                tickfont = list(size = 11)
            ),
            xaxis = list(
                title = "Frecuencia de Proyectos",
                showgrid = TRUE,
                gridcolor = "#f0f0f0",
                side = "bottom"
            ),
            showlegend = TRUE,
            legend = list(
                x = 0.02, 
                y = 0.98,
                bgcolor = "rgba(255,255,255,0.8)",
                font = list(size = 12)
            ),
            margin = list(l = 150, r = 50, b = 80, t = 60),  # Margen izquierdo mayor para etiquetas largas
            hoverlabel = list(
                bgcolor = "white",
                bordercolor = "black",
                font = list(size = 12)
            ),
            # Eje secundario para el porcentaje (parte superior)
            xaxis2 = list(
                title = "Porcentaje Acumulado (%)",
                overlaying = "x",
                side = "top",
                range = c(0, 100),
                showgrid = FALSE,
                tickfont = list(color = color_linea)
            )
        ) %>%
        config(
            displayModeBar = TRUE,
            modeBarButtonsToRemove = c("pan2d", "lasso2d", "select2d"),
            displaylogo = FALSE
        )
}

# Gráfico interactivo para CFG por proyectos - VERSIÓN HORIZONTAL CORREGIDA
crear_pareto_horizontal_interactivo(
    df_dummies,
    CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
    "Distribución de Tipologías CFG - Pareto por Número de Proyectos",
    "#3498db", "#e74c3c"
)
##=======================Frecuencia Global CFG - Comunas========================##

# Función para Pareto por comunas (HORIZONTAL)
crear_pareto_comunas_interactivo <- function(data, variable, titulo, color_barras = "#2c3e50", color_linea = "#f39c12") {
    
    # Convertir variable a símbolo
    var_sym <- ensym(variable)
    
    # Calcular frecuencias por comuna (sin repetir comunas)
    freq_data <- data %>%
        distinct(ID_COMUNA, !!var_sym) %>%  
        count(!!var_sym, name = "n_comunas") %>%
        arrange(desc(n_comunas)) %>%
        mutate(
            porcentaje = n_comunas / sum(n_comunas) * 100,
            acumulado = cumsum(porcentaje),
            etiqueta = paste0(
                "Comunas: ", n_comunas, "\n",
                "Porcentaje: ", round(porcentaje, 1), "%\n",
                "Acumulado: ", round(acumulado, 1), "%"
            ),
            # Crear variable ordenada para el eje Y (horizontal)
            variable_ordenada = reorder(!!var_sym, n_comunas)
        )
    
    # Preparar datos para plotly horizontal
    freq_data$variable_char <- as.character(freq_data$variable_ordenada)
    freq_data$variable_char <- factor(freq_data$variable_char, 
                                      levels = levels(freq_data$variable_ordenada))
    
    # Calcular el máximo para escalar la línea correctamente
    max_comunas <- max(freq_data$n_comunas)
    escala_linea <- max_comunas / 100
    
    # Crear gráfico interactivo HORIZONTAL
    plot_ly(freq_data) %>%
        add_bars(
            y = ~variable_char,
            x = ~n_comunas,
            name = "Número de Comunas",
            orientation = 'h',
            marker = list(
                color = color_barras,
                line = list(color = '#1c2833', width = 1)
            ),
            text = ~etiqueta,
            hoverinfo = "text",
            textposition = "none"
        ) %>%
        add_trace(
            y = ~variable_char,
            x = ~acumulado * escala_linea,
            name = "Porcentaje Acumulado",
            type = 'scatter',
            mode = 'lines+markers',
            line = list(
                color = color_linea, 
                width = 3,
                dash = 'solid'
            ),
            marker = list(
                color = color_linea,
                size = 6,
                symbol = 'circle'
            ),
            hoverinfo = "x+text",
            text = ~paste("Acumulado: ", round(acumulado, 1), "%")
        ) %>%
        layout(
            title = list(
                text = titulo,
                x = 0.05,
                font = list(size = 16, color = "#2c3e50")
            ),
            yaxis = list(
                title = "",
                showgrid = FALSE,
                tickfont = list(size = 11)
            ),
            xaxis = list(
                title = "Número de Comunas Afectadas",
                showgrid = TRUE,
                gridcolor = "#f0f0f0"
            ),
            showlegend = TRUE,
            legend = list(
                x = 0.02, 
                y = 0.98,
                bgcolor = "rgba(255,255,255,0.8)"
            ),
            margin = list(l = 150, r = 50, b = 80, t = 60),
            hoverlabel = list(
                bgcolor = "white",
                bordercolor = "black",
                font = list(size = 12)
            ),
            xaxis2 = list(
                title = "Porcentaje Acumulado (%)",
                overlaying = "x",
                side = "top",
                range = c(0, 100),
                showgrid = FALSE,
                tickfont = list(color = color_linea)
            )
        ) %>%
        config(
            displayModeBar = TRUE,
            modeBarButtonsToRemove = c("pan2d", "lasso2d", "select2d"),
            displaylogo = FALSE
        )
}

# Gráfico interactivo para CFG por comunas
crear_pareto_comunas_interactivo(
    df_dummies,
    CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG,
    "Distribución de Tipologías CFG - Pareto por Número de Comunas Afectadas",
    "#2c3e50", "#f39c12"
)

5 Análisis de Tipologías CFG: Tablas Descriptivas

En esta sección presentamos el análisis detallado de las tipologías CFG mediante tablas descriptivas que permiten visualizar la distribución, frecuencia e impacto territorial de los nudos críticos identificados.

Este revela una distribución altamente concentrada de los nudos críticos, donde Manejo Integral del Agua emerge inequívocamente como el problema más común del Estado Mérida. Con 54 proyectos representando el 27,27% del total, esta tipología supera por un margen considerable a todas las demás categorías, estableciendo una brecha significativa de 12 puntos porcentuales con respecto a Vialidad, que ocupa el segundo lugar con 30 proyectos (15,15%).

El análisis del porcentaje acumulado demuestra la aplicación práctica del principio de Pareto en la problemática estatal:

• Las primeras 4 tipologías (Manejo Integral del Agua, Vialidad, Vivienda y Electricidad) concentran el 62,63% de todos los nudos críticos

• Las primeras 7 tipologías alcanzan el 80,81% del total, confirmando que aproximadamente el 80% de los problemas se concentra en menos del 50% de las categorías. Esta concentración indica que una estrategia de intervención focalizada en estas áreas principales podría atender la mayoría de los problemas identificados con una eficiencia considerable en el uso de recursos públicos.

La distribución permite establecer tres niveles de criticidad claramente diferenciados: Nivel Crítico Alto (Posiciones 1-4): Manejo Integral del Agua, Vialidad, Vivienda y Electricidad representan los servicios básicos fundamentales del estado, con frecuencias que van desde 54 hasta 19 proyectos.

Nivel Crítico Medio (Posiciones 5-7): Salud, Infraestructura y Ambiente configuran un segundo grupo de problemas significativos, con frecuencias entre 14 y 10 proyectos.

Nivel Crítico Bajo (Posiciones 8-16): Las nueve tipologías restantes presentan frecuencias menores a 10 proyectos cada una, representando problemas importantes, pero de menor escala relativa.

5.1 Tabla de Distribución de Frecuencias de Tipologías CFG por Número de Proyectos

Tabla 4.1: Distribución de Frecuencias de Tipologías CFG por Número de Proyectos
Frecuencias Absolutas y Relativas
Tipología CFG N° Proyectos Porcentaje (%) % Acumulado Ranking
MANEJO INTEGRAL DEL AGUA 54 27.27 27.27 1
VIALIDAD 30 15.15 42.42 2
VIVIENDA 21 10.61 53.03 3
ELECTRICIDAD 19 9.60 62.63 4
SALUD 14 7.07 69.70 5
INFRAESTRUCTURA 12 6.06 75.76 6
AMBIENTE 10 5.05 80.81 7
EDUCACIÓN 9 4.55 85.36 8
TRANSPORTE 7 3.54 88.90 9
TELECOMUNICACIONES 6 3.03 91.93 10
MUROS 5 2.53 94.46 11
SOCIO PRODUCTIVO 4 2.02 96.48 12
SEGURIDAD 3 1.52 98.00 13
CANALIZACION 2 1.01 99.01 14
ORGANIZACION COMUNAL 1 0.51 99.52 15
PROCESOS INDUSTRIALES 1 0.51 100.03 16
Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025 Nota: Las primeras 4 tipologías concentran el 62.6% de todos los nudos críticos

Nota: La tabla muestra la distribución absoluta y relativa de las tipologías CFG según el número de proyectos asociados.

5.2 Tabla de Distribución de Frecuencias de Tipologías CFG por Número de Comunas Afectadas

Tabla 4.2: Distribución de Frecuencias de Tipologías CFG por Número de Comunas Afectadas
Distribución Territorial
Tipología CFG N° Comunas Porcentaje (%) % Acumulado Ranking
MANEJO INTEGRAL DEL AGUA 43 23.63 23.63 1
VIALIDAD 27 14.84 38.47 2
VIVIENDA 21 11.54 50.01 3
ELECTRICIDAD 18 9.89 59.90 4
SALUD 14 7.69 67.59 5
INFRAESTRUCTURA 11 6.04 73.63 6
AMBIENTE 10 5.49 79.12 7
EDUCACIÓN 9 4.95 84.07 8
TRANSPORTE 7 3.85 87.92 9
TELECOMUNICACIONES 6 3.30 91.22 10
MUROS 5 2.75 93.97 11
SOCIO PRODUCTIVO 4 2.20 96.17 12
SEGURIDAD 3 1.65 97.82 13
CANALIZACION 2 1.10 98.92 14
ORGANIZACION COMUNAL 1 0.55 99.47 15
PROCESOS INDUSTRIALES 1 0.55 100.02 16
Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025 Nota: Una comuna puede tener múltiples tipologías, pero se cuenta una sola vez por tipología

Nota: Esta tabla representa la distribución territorial de las tipologías, contabilizando cuántas comunas están afectadas por cada tipo de nudo crítico.

5.3 Tabla de Análisis Comparativo CFG - Proyectos vs Comunas Afectadas

Tabla 4.3: Análisis Comparativo CFG - Proyectos vs Comunas Afectadas
Por Proyectos
Por Comunas
Indicador
Rank Tipología CFG N° Proy. % Proy. N° Com. % Com. Intensidad
1 MANEJO INTEGRAL DEL AGUA 54 27.27 43 23.63 1.26
2 VIALIDAD 30 15.15 27 14.84 1.11
3 VIVIENDA 21 10.61 21 11.54 1.00
4 ELECTRICIDAD 19 9.60 18 9.89 1.06
5 SALUD 14 7.07 14 7.69 1.00
6 INFRAESTRUCTURA 12 6.06 11 6.04 1.09
7 AMBIENTE 10 5.05 10 5.49 1.00
8 EDUCACIÓN 9 4.55 9 4.95 1.00
9 TRANSPORTE 7 3.54 7 3.85 1.00
10 TELECOMUNICACIONES 6 3.03 6 3.30 1.00
11 MUROS 5 2.53 5 2.75 1.00
12 SOCIO PRODUCTIVO 4 2.02 4 2.20 1.00
13 SEGURIDAD 3 1.52 3 1.65 1.00
14 CANALIZACION 2 1.01 2 1.10 1.00
15 ORGANIZACION COMUNAL 1 0.51 1 0.55 1.00
16 PROCESOS INDUSTRIALES 1 0.51 1 0.55 1.00
Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025 Intensidad = N° Proyectos / N° Comunas (promedio de proyectos por comuna por tipología)

Nota: El indicador de intensidad (proyectos/comuna) permite identificar tipologías con mayor concentración de problemas por territorio.

5.4 Tabla de Resumen Ejecutivo - Top 10 Tipologías CFG Más Críticas

Tabla 4.4: Resumen Ejecutivo - Top 10 Tipologías CFG Más Críticas
Análisis por Proyectos
Por Comunas
Pos. Nivel Tipología CFG Proy. % % Acum. Com. % Com.
1 🔴 Crítico MANEJO INTEGRAL DEL AGUA 54 27.3 27.3 43 72.9
2 🔴 Crítico VIALIDAD 30 15.2 42.5 27 45.8
3 🔴 Crítico VIVIENDA 21 10.6 53.1 21 35.6
4 🟡 Alto ELECTRICIDAD 19 9.6 62.7 18 30.5
5 🟡 Alto SALUD 14 7.1 69.8 14 23.7
6 🟡 Alto INFRAESTRUCTURA 12 6.1 75.9 11 18.6
7 🟡 Alto AMBIENTE 10 5.1 81.0 10 16.9
8 🟢 Medio EDUCACIÓN 9 4.5 85.5 9 15.3
9 🟢 Medio TRANSPORTE 7 3.5 89.0 7 11.9
10 🟢 Medio TELECOMUNICACIONES 6 3.0 92.0 6 10.2
Nota: Total analizado: 198 proyectos en 59 comunas. El Top 10 concentra el 92% de todos los nudos críticos.

Nota: Clasificación por nivel de criticidad basado en la frecuencia de aparición y distribución territorial.

6 Frecuencias de Gobernación

Se observa una clara distribución de Pareto, donde las mismas cuatro categorías principales, la cartera de proyectos de la Gobernación está dominada por una clara priorización de los servicios básicos. Las cuatro primeras categorías (Agua Potable – 14,14%, Vivienda – 11,62%, Electricidad – 9,60%, Vialidad – 9,09%) concentran 44,45% de todos los proyectos. Esto indica que la estrategia institucional se centra en atender los déficits más esenciales para la calidad de vida y el desarrollo: acceso al agua, vivienda digna, energía y conectividad.

Un segundo grupo de categorías recibe una atención significativa, aunque menor. “Equipamiento Salud” (7,07%), “Agua Residual” (6,57%), “Drenajes” (6,57%) y “Equipamiento Educativo” (6,06%) representan un 26,27% adicional de los proyectos. La línea de porcentaje acumulado muestra que se necesitan las primeras 8 categorías para alcanzar aproximadamente el 70% de los proyectos. Las 13 categorías restantes constituyen una “larga cola” de problemáticas que, si bien son críticas para las comunidades que las padecen, representan una porción menor de la cartera global de la Gobernación.

La distribución sigue un principio de Pareto, donde una minoría de categorías concentra la mayoría de los esfuerzos institucionales.

#----------------------------Resumen Gobernación por Comuna----------------------
## Análisis para Gobernación ----
# Conteo y proporciones globales por Tipologia de Gobernación
freq_gob <- df_dummies %>%
  count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "n") %>%
  arrange(desc(n)) %>%
  mutate(pct = n / sum(n) * 100)


#  Gráfico de barras (Top 10) de gobernación por proyectos
freq_gob %>%
  slice(1:10) %>%
  ggplot(aes(x = reorder(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, n),
             y = n)) +
    geom_col(fill = "darkred") +
    coord_flip() +
    labs(
      title = "Top 10 categorías de Gobernación más frecuentes",
      x     = "Categoría de Gobernación",
      y     = "Número de proyectos"
    ) +
    theme_minimal()

# Frecuencia absoluta y relativa por comuna
freq_gob_comuna <- df_dummies %>%
  distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION) %>%  
  count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "n_comunas") %>%
  arrange(desc(n_comunas)) %>%
  mutate(
    pct_comunas = n_comunas / sum(n_comunas) * 100,
    cum_pct     = cumsum(pct_comunas)
  )


#----------------------------Gráfico de top 10 por comuna---------------------------
freq_gob_comuna %>%
  slice(1:10) %>%
  ggplot(aes(
    x = reorder(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, n_comunas),
    y = n_comunas
  )) +
  geom_col(fill = "darkred") +
  coord_flip() +
  labs(
    title = "Top 10 categorías de Gobernación por número de comunas",
    x     = "Categoría de Gobernación",
    y     = "Número de comunas"
  ) +
  theme_minimal()

# ------------------------Global - Proyectos-------------------------------------------
gob_global_proyectos <- analizar_frecuencia(
  df_raw,
  CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
  "darkred", "gold",
  "Frecuencia global de categorías de Gobernación (Proyectos)",
  "proyectos"
)

# -------------------------Global - Comunas--------------------------------------------
gob_global_comunas <- analizar_frecuencia_comuna(
  df_raw,
  CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
  "darkred", "gold",
  "Frecuencia de categorías de Gobernación por comuna"
)

#----------------------Grafico de frecuencias de categorías de Gobernación-------------
print(gob_global_proyectos$plot)

#----Grafico Frecuencia absoluta y relativa de comunas por categoría de Gobernación----
print(gob_global_comunas$plot)

# ==============================================================================
#  TABLA COMPLETA DE FRECUENCIAS GOBERNACIÓN POR PROYECTOS
# ==============================================================================
crear_tabla_gob_proyectos <- function(data) {
  
  # Calcular frecuencias
  tabla_gob <- data %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "n_proyectos") %>%
    arrange(desc(n_proyectos)) %>%
    mutate(
      porcentaje = round(n_proyectos / sum(n_proyectos) * 100, 2),
      pct_acumulado = round(cumsum(porcentaje), 2),
      ranking = row_number()
    ) %>%
    rename(
      "Ranking" = ranking,
      "Categoría Gobernación" = CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
      "N° Proyectos" = n_proyectos,
      "Porcentaje (%)" = porcentaje,
      "% Acumulado" = pct_acumulado
    )
  
  # Crear tabla formateada con kableExtra
  tabla_final <- tabla_gob %>%
    kable(
      caption = "Tabla 5.1: Distribución de Frecuencias de Categorías de Gobernación por Número de Proyectos",
      align = c("c", "l", "c", "c", "c"),
      format = "html"
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 12
    ) %>%
    column_spec(1, bold = TRUE, color = "white", background = "#8B0000") %>%
    column_spec(2, width = "20em") %>%
    column_spec(3:5, width = "8em") %>%
    row_spec(1:4, background = "#ffebee") %>%  # Resaltar top 4
    add_header_above(c(" " = 2, "Frecuencias Absolutas y Relativas" = 3)) %>%
    footnote(
      general = c(
        "Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025",
        "Nota: Las primeras 4 categorías concentran el 51.5% de todos los proyectos"
      ),
      general_title = "",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = tabla_gob, tabla = tabla_final))
}

# ==============================================================================
#  TABLA COMPLETA DE FRECUENCIAS GOBERNACIÓN POR COMUNAS
# ==============================================================================
crear_tabla_gob_comunas <- function(data) {
  
  # Calcular frecuencias por comuna (sin repetir comunas)
  tabla_gob_comunas <- data %>%
    distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION) %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "n_comunas") %>%
    arrange(desc(n_comunas)) %>%
    mutate(
      porcentaje = round(n_comunas / sum(n_comunas) * 100, 2),
      pct_acumulado = round(cumsum(porcentaje), 2),
      ranking = row_number()
    ) %>%
    rename(
      "Ranking" = ranking,
      "Categoría Gobernación" = CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
      "N° Comunas" = n_comunas,
      "Porcentaje (%)" = porcentaje,
      "% Acumulado" = pct_acumulado
    )
  
  # Crear tabla formateada
  tabla_final <- tabla_gob_comunas %>%
    kable(
      caption = "Tabla 5.2: Distribución de Frecuencias de Categorías de Gobernación por Número de Comunas Afectadas",
      align = c("c", "l", "c", "c", "c"),
      format = "html"
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 12
    ) %>%
    column_spec(1, bold = TRUE, color = "white", background = "#8B0000") %>%
    column_spec(2, width = "20em") %>%
    column_spec(3:5, width = "8em") %>%
    row_spec(1:4, background = "#ffebee") %>%  # Resaltar top 4
    add_header_above(c(" " = 2, "Distribución Territorial" = 3)) %>%
    footnote(
      general = c(
        "Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025",
        "Nota: Una comuna puede tener múltiples categorías, pero se cuenta una sola vez por categoría"
      ),
      general_title = "",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = tabla_gob_comunas, tabla = tabla_final))
}

# ==============================================================================
# TABLA COMPARATIVA GOBERNACIÓN: PROYECTOS VS COMUNAS
# ==============================================================================
crear_tabla_comparativa_gob <- function(data) {
  
  # Datos por proyectos
  gob_proyectos <- data %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "n_proyectos") %>%
    mutate(pct_proyectos = round(n_proyectos / sum(n_proyectos) * 100, 2))
  
  # Datos por comunas
  gob_comunas <- data %>%
    distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION) %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "n_comunas") %>%
    mutate(pct_comunas = round(n_comunas / sum(n_comunas) * 100, 2))
  
  # Unir ambas tablas
  tabla_comparativa <- gob_proyectos %>%
    inner_join(gob_comunas, by = "CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION") %>%
    arrange(desc(n_proyectos)) %>%
    mutate(
      ranking = row_number(),
      intensidad = round(n_proyectos / n_comunas, 2)  # Proyectos por comuna promedio
    ) %>%
    select(
      ranking,
      CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
      n_proyectos, pct_proyectos,
      n_comunas, pct_comunas,
      intensidad
    ) %>%
    rename(
      "Rank" = ranking,
      "Categoría Gobernación" = CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
      "N° Proy." = n_proyectos,
      "% Proy." = pct_proyectos,
      "N° Com." = n_comunas,
      "% Com." = pct_comunas,
      "Intensidad" = intensidad
    )
  
  # Crear tabla formateada
  tabla_final <- tabla_comparativa %>%
    kable(
      caption = "Tabla 5.3: Análisis Comparativo Gobernación - Proyectos vs Comunas Afectadas",
      align = c("c", "l", rep("c", 5)),
      format = "html",
      digits = 2
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 11
    ) %>%
    column_spec(1, bold = TRUE, color = "white", background = "#8B0000", width = "3em") %>%
    column_spec(2, width = "15em") %>%
    column_spec(3:7, width = "6em") %>%
    add_header_above(c(" " = 2, "Por Proyectos" = 2, "Por Comunas" = 2, "Indicador" = 1)) %>%
    row_spec(1:3, background = "#ffcdd2") %>%  # Top 3 en rojo suave
    row_spec(4:7, background = "#ffecb3") %>%  # Siguientes 4 en amarillo suave
    footnote(
      general = c(
        "Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025",
        "Intensidad = N° Proyectos / N° Comunas (promedio de proyectos por comuna por categoría)"
      ),
      general_title = "",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = tabla_comparativa, tabla = tabla_final))
}

# ==============================================================================
#  TABLA RESUMEN EJECUTIVO GOBERNACIÓN (TOP 10)
# ==============================================================================
crear_tabla_resumen_gob <- function(data) {
  
  # Calcular estadísticas resumidas
  total_proyectos <- nrow(data)
  total_comunas <- n_distinct(data$ID_COMUNA)
  
  resumen_gob <- data %>%
    count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "proyectos") %>%
    arrange(desc(proyectos)) %>%
    slice(1:10) %>%  # Solo top 10
    mutate(
      pct_proyectos = round(proyectos / total_proyectos * 100, 1),
      pct_acum = round(cumsum(pct_proyectos), 1)
    ) %>%
    # Agregar datos de comunas
    left_join(
      data %>%
        distinct(ID_COMUNA, CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION) %>%
        count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION, name = "comunas"),
      by = "CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION"
    ) %>%
    mutate(
      pct_comunas = round(comunas / total_comunas * 100, 1),
      posicion = row_number(),
      categoria = case_when(
        posicion <= 3 ~ "🔴 Crítico",
        posicion <= 7 ~ "🟡 Alto",
        TRUE ~ "🟢 Medio"
      )
    ) %>%
    select(
      posicion, categoria,
      CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
      proyectos, pct_proyectos, pct_acum,
      comunas, pct_comunas
    ) %>%
    rename(
      "Pos." = posicion,
      "Nivel" = categoria,
      "Categoría Gobernación" = CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
      "Proy." = proyectos,
      "%" = pct_proyectos,
      "% Acum." = pct_acum,
      "Com." = comunas,
      "% Com." = pct_comunas
    )
  
  # Crear tabla formateada
  tabla_final <- resumen_gob %>%
    kable(
      caption = "Tabla 5.4: Resumen Ejecutivo - Top 10 Categorías de Gobernación Más Críticas",
      align = c("c", "c", "l", rep("c", 5)),
      format = "html"
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover", "condensed", "responsive"),
      full_width = FALSE,
      position = "center",
      font_size = 11
    ) %>%
    column_spec(1, bold = TRUE, width = "3em") %>%
    column_spec(2, width = "8em") %>%
    column_spec(3, width = "15em") %>%
    column_spec(4:8, width = "5em") %>%
    add_header_above(c(" " = 3, "Análisis por Proyectos" = 3, "Por Comunas" = 2)) %>%
    footnote(
      general = paste0(
        "Total analizado: ", total_proyectos, " proyectos en ", total_comunas, " comunas. ",
        "El Top 10 concentra el ", round(sum(resumen_gob$`%`), 1), "% de todos los proyectos."
      ),
      general_title = "Nota:",
      footnote_as_chunk = TRUE
    )
  
  return(list(datos = resumen_gob, tabla = tabla_final))
}
##======================= Frecuencia Global Gobernación - Proyectos ========================##

# Gráfico interactivo de Pareto HORIZONTAL para Gobernación - Proyectos
crear_pareto_horizontal_interactivo(
    df_dummies,
    CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
    "Distribución de Tipologías de Gobernación - Pareto por Número de Proyectos",
    "#16a085", "#d35400"   # Colores personalizados (verde/rojo quemado)
)
##======================= Frecuencia Global Gobernación - Comunas ========================##

# Gráfico interactivo de Pareto HORIZONTAL para Gobernación - Comunas
crear_pareto_comunas_interactivo(
    df_dummies,
    CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION,
    "Distribución de Tipologías de Gobernación - Pareto por Número de Comunas Afectadas",
    "#34495e", "#f1c40f"   # Colores personalizados (gris oscuro/amarillo)
)

7 Análisis de Categorías de Gobernación: Tablas Descriptivas

En esta sección presentamos el análisis detallado de las categorías de gobernación mediante tablas descriptivas que permiten visualizar la distribución, frecuencia e impacto territorial de los nudos críticos identificados.

Las tablas revelan una distribución de problemas más diversificada que en el análisis CFG, pero con una clara concentración en las primeras posiciones. AGUA POTABLE emerge como la categoría más crítica, con 28 proyectos que representan el 14,14% del total, consolidando la problemática hídrica como prioridad absoluta en la gestión gubernamental.

La distribución sigue un patrón de Pareto modificado, donde las primeras 4 categorías (AGUA POTABLE, VIVIENDA, ELECTRICIDAD y VIALIDAD) concentran el 44,45% de todos los proyectos, las otras primeras 8 categorías alcanzan el 70,72% del total, confirmando que el 70% de los proyectos se enfoca en resolver el 38% de las categorías (8 de 21).

Esta distribución permite establecer tres niveles de criticidad claramente diferenciados:

Nivel Crítico Alto (Posiciones 1-4):

• AGUA POTABLE (28 proyectos, 14.14%)

• VIVIENDA (23 proyectos, 11.62%)

• ELECTRICIDAD (19 proyectos, 9.60%)

• VIALIDAD (18 proyectos, 9.09%)

Nivel Crítico Medio (Posiciones 5-8):

• EQUIPAMIENTO SALUD (14 proyectos, 7.07%)

• AGUA RESIDUAL (13 proyectos, 6.57%)

• DRENAJES (13 proyectos, 6.57%)

• EQUIPAMIENTO EDUCATIVO (12 proyectos, 6.06%)

Nivel Crítico Bajo (Posiciones 9-21):

Las trece categorías restantes presentan frecuencias menores a 10 proyectos cada una.

no de los hallazgos claves es la consistencia en el ranking y validación de la priorización, el orden de las categorías principales es notablemente consistente con el análisis por números de proyectos, ahora los resultados por número de comunas es consistente, ya que el Agua Potable (13,61%), Vivienda (11,52%), Electricidad (9,42%) y Vialidad (8,90%**) vuelven a ocupar los cuatro primeros lugares. Esta consistencia es un hallazgo ya que demuestra que los problemas en los que la Gobernación más se enfoca (mayor número de proyectos) son precisamente los que están más generalizados en el territorio (afectan a más comunas). Valida que la priorización institucional es acertada y está alineada con la realidad geográfica de las carencias.

8 Análisis de Categorías de Gobernación: Tablas Descriptivas

Desde la perspectiva de la Gobernación, el principio de Pareto se mantiene, pero con una distribución ligeramente más diversificada. Las primeras 4 categorías (Agua Potable, Vivienda, Electricidad, Vialidad), que constituyen el 19% del total (4 de 21), acaparan el 44,45% de los proyectos institucionales. La regla del 80/20 se cumple al considerar que las primeras 8 categorías (38% del total) explican el 70,72% de la cartera de proyectos gubernamentales.

8.1 Tabla de Distribución de Frecuencias de Categorías de Gobernación por Número de Proyectos

Tabla 5.1: Distribución de Frecuencias de Categorías de Gobernación por Número de Proyectos
Frecuencias Absolutas y Relativas
Categoría Gobernación N° Proyectos Porcentaje (%) % Acumulado Ranking
AGUA POTABLE 28 14.14 14.14 1
VIVIENDA 23 11.62 25.76 2
ELECTRICIDAD 19 9.60 35.36 3
VIALIDAD 18 9.09 44.45 4
EQUIPAMIENTO SALUD 14 7.07 51.52 5
AGUA RESIDUAL 13 6.57 58.09 6
DRENAJES 13 6.57 64.66 7
EQUIPAMIENTO EDUCATIVO 12 6.06 70.72 8
CANALIZACION 10 5.05 75.77 9
TRANSPORTE 8 4.04 79.81 10
VIALIDAD AGRICOLA 8 4.04 83.85 11
TELECOMUNICACIONES 6 3.03 86.88 12
INFRAESTRUCTURA 5 2.53 89.41 13
MUROS 5 2.53 91.94 14
SOCIO PRODUCTIVO 4 2.02 93.96 15
EQUIPAMIENTO SEGURIDAD 3 1.52 95.48 16
PUENTE 3 1.52 97.00 17
SISTEMAS DE RIEGO 3 1.52 98.52 18
AGUA 1 0.51 99.03 19
GAS 1 0.51 99.54 20
ORGANIZACION COMUNAL 1 0.51 100.05 21
Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025 Nota: Las primeras 4 categorías concentran el 51.5% de todos los proyectos

Nota: La tabla muestra la distribución absoluta y relativa de las categorías de gobernación según el número de proyectos asociados.

8.2 Tabla de Distribución de Frecuencias de Categorías de Gobernación por Número de Comunas Afectadas

Tabla 5.2: Distribución de Frecuencias de Categorías de Gobernación por Número de Comunas Afectadas
Distribución Territorial
Categoría Gobernación N° Comunas Porcentaje (%) % Acumulado Ranking
AGUA POTABLE 26 13.54 13.54 1
VIVIENDA 22 11.46 25.00 2
ELECTRICIDAD 18 9.38 34.38 3
VIALIDAD 17 8.85 43.23 4
EQUIPAMIENTO SALUD 14 7.29 50.52 5
DRENAJES 13 6.77 57.29 6
AGUA RESIDUAL 12 6.25 63.54 7
EQUIPAMIENTO EDUCATIVO 12 6.25 69.79 8
CANALIZACION 10 5.21 75.00 9
TRANSPORTE 8 4.17 79.17 10
VIALIDAD AGRICOLA 8 4.17 83.34 11
TELECOMUNICACIONES 6 3.12 86.46 12
INFRAESTRUCTURA 5 2.60 89.06 13
MUROS 5 2.60 91.66 14
SOCIO PRODUCTIVO 4 2.08 93.74 15
EQUIPAMIENTO SEGURIDAD 3 1.56 95.30 16
PUENTE 3 1.56 96.86 17
SISTEMAS DE RIEGO 3 1.56 98.42 18
AGUA 1 0.52 98.94 19
GAS 1 0.52 99.46 20
ORGANIZACION COMUNAL 1 0.52 99.98 21
Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025 Nota: Una comuna puede tener múltiples categorías, pero se cuenta una sola vez por categoría

Nota: Esta tabla representa la distribución territorial de las categorías de gobernación, contabilizando cuántas comunas están afectadas por cada tipo de nudo crítico.

8.3 Tabla de Análisis Comparativo Gobernación - Proyectos vs Comunas Afectadas

Tabla 5.3: Análisis Comparativo Gobernación - Proyectos vs Comunas Afectadas
Por Proyectos
Por Comunas
Indicador
Rank Categoría Gobernación N° Proy. % Proy. N° Com. % Com. Intensidad
1 AGUA POTABLE 28 14.14 26 13.54 1.08
2 VIVIENDA 23 11.62 22 11.46 1.05
3 ELECTRICIDAD 19 9.60 18 9.38 1.06
4 VIALIDAD 18 9.09 17 8.85 1.06
5 EQUIPAMIENTO SALUD 14 7.07 14 7.29 1.00
6 AGUA RESIDUAL 13 6.57 12 6.25 1.08
7 DRENAJES 13 6.57 13 6.77 1.00
8 EQUIPAMIENTO EDUCATIVO 12 6.06 12 6.25 1.00
9 CANALIZACION 10 5.05 10 5.21 1.00
10 TRANSPORTE 8 4.04 8 4.17 1.00
11 VIALIDAD AGRICOLA 8 4.04 8 4.17 1.00
12 TELECOMUNICACIONES 6 3.03 6 3.12 1.00
13 INFRAESTRUCTURA 5 2.53 5 2.60 1.00
14 MUROS 5 2.53 5 2.60 1.00
15 SOCIO PRODUCTIVO 4 2.02 4 2.08 1.00
16 EQUIPAMIENTO SEGURIDAD 3 1.52 3 1.56 1.00
17 PUENTE 3 1.52 3 1.56 1.00
18 SISTEMAS DE RIEGO 3 1.52 3 1.56 1.00
19 AGUA 1 0.51 1 0.52 1.00
20 GAS 1 0.51 1 0.52 1.00
21 ORGANIZACION COMUNAL 1 0.51 1 0.52 1.00
Fuente: Elaboración propia basada en datos del Estado Mérida 2019-2025 Intensidad = N° Proyectos / N° Comunas (promedio de proyectos por comuna por categoría)

Nota: El indicador de intensidad (proyectos/comuna) permite identificar categorías con mayor concentración de problemas por territorio.

8.4 Tabla de Resumen Ejecutivo - Top 10 Categorías de Gobernación Más Críticas

Tabla 5.4: Resumen Ejecutivo - Top 10 Categorías de Gobernación Más Críticas
Análisis por Proyectos
Por Comunas
Pos. Nivel Categoría Gobernación Proy. % % Acum. Com. % Com.
1 🔴 Crítico AGUA POTABLE 28 14.1 14.1 26 44.1
2 🔴 Crítico VIVIENDA 23 11.6 25.7 22 37.3
3 🔴 Crítico ELECTRICIDAD 19 9.6 35.3 18 30.5
4 🟡 Alto VIALIDAD 18 9.1 44.4 17 28.8
5 🟡 Alto EQUIPAMIENTO SALUD 14 7.1 51.5 14 23.7
6 🟡 Alto AGUA RESIDUAL 13 6.6 58.1 12 20.3
7 🟡 Alto DRENAJES 13 6.6 64.7 13 22.0
8 🟢 Medio EQUIPAMIENTO EDUCATIVO 12 6.1 70.8 12 20.3
9 🟢 Medio CANALIZACION 10 5.1 75.9 10 16.9
10 🟢 Medio TRANSPORTE 8 4.0 79.9 8 13.6
Nota: Total analizado: 198 proyectos en 59 comunas. El Top 10 concentra el 79.9% de todos los proyectos.

Nota: Clasificación por nivel de criticidad basado en la frecuencia de aparición y distribución territorial.

9 Índice Shannon y Pielou por Comunas y Tipología CFG y de Gobernación

El índice de Shannon se utiliza como una herramienta cuantitativa para medir la diversidad de tipologías de conflicto y la diversidad institucional (gobernación), cuantifica la diversidad de categorías en una comunidad considerando tanto la riqueza (número de categorías) como la uniformidad en su distribución involucradas en los proyectos analizados.

\[ H^\prime = - \sum_{i=1}^{S} p_i \ln(p_i) \]

Leyenda:

Explicación rápida de los símbolos:

𝐻→ Índice de Shannon.

𝑆 → Número total de categorías (o tipologías de nudos críticos).

𝑝𝑖 → Proporción de la categoría

i respecto al total.

Se utiliza los índices de Shannon y Pielou como herramientas para:

  1. Medir la diversidad de problemáticas (CFG) y actores (Gobernación) en comunas merideñas.

  2. Interpretar su significado mediante el marco de hipótesis (Tabla de Hipótesis 1), que contrasta escenarios de capacidad vs. disfunción.

  3. Diseñar políticas diferenciadas según el perfil de cada comuna (coordinación interinstitucional para H’ alto, asesoría técnica para H’ bajo con baja J’).

Para abordar de manera efectica el indice Shannon-Pieolou, nos vamos a plantear unas hipotesis:

Valor de Shannon ALTO (H’ > 1.5)

  • Las comunidades tienen capacidad de diagnóstico y organización, esto es una comuna con visión integral, capaz de mapear completamente sus problemáticas. -

  • Existe síntomas de Abandono Institucional, refleja carencias generalizadas. La comuna documenta todo por desesperación. Proyectos repetitivos que no se resuelven. Baja tasa de culminación.Podría subestimarse una genuina capacidad organizativa.

Valor de Shannon BAJO (H’ < 1.0)

  • Tienen una Focalización Estratégica, Las comunas prioriza de manera pragmática los problemas más críticos y viables. Problemas claramente identificados como primordiales. Mayores tasas de éxito. Puede ignorar problemáticas “menores”.

  • Desconexión e Inviabilidad, las comunas persigue soluciones monumentales e inviables. Proyectos de escala nacional/estadal. Persistencia del mismo problema sin evolución. Baja efectividad.

knitr::opts_chunk$set(echo = TRUE)

conflict_prefer("select", "dplyr")
conflict_prefer("filter", "dplyr")


#--------------------------Crear mapeo único de ID_COMUNA a COMUNA-----------------------------
commune_map <- df_raw %>%
  distinct(ID_COMUNA, COMUNA) %>%
  mutate(COMUNA = str_trim(COMUNA))  # Limpiar espacios extras

## Detectar dinámicamente las columnas dummy
cfg_cols <- grep("^CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_", 
                 names(df_dummies), value = TRUE)
gob_cols <- grep("^CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_", 
                 names(df_dummies), value = TRUE)

## Calcular diversidad para las Tipología CFG con nombres de comunas
div_cfg <- df_dummies %>%
  group_by(ID_COMUNA) %>%
  summarise(
    n_proyectos = n(),
    across(all_of(cfg_cols), sum, na.rm = TRUE)
  ) %>%
  ungroup() %>%
  # Agregar nombres de comunas
  left_join(commune_map, by = "ID_COMUNA") %>%
  # Calcular índices de diversidad
  {
    cnts <- select(., all_of(cfg_cols))
    tib <- select(., ID_COMUNA, COMUNA, n_proyectos)
    H <- vegan::diversity(cnts, index = "shannon")
    richesse <- rowSums(cnts > 0)
    J <- ifelse(richesse > 0, H / log(richesse), NA_real_)
    bind_cols(tib, H_shannon = H, pielou = J)
  }

# Crear columna combinada para mostrar en tablas
div_cfg <- div_cfg %>%
  mutate(COMUNA_ID_NOMBRE = paste(ID_COMUNA, "-", COMUNA))

# Tabla: Top 10 comunas más diversas (con ID y nombre)
top10_cfg <- div_cfg %>%
  arrange(desc(H_shannon)) %>%
  slice(1:10) %>%
  select(COMUNA_ID_NOMBRE, H_shannon, pielou, n_proyectos)

# Tabla: Top 10 comunas menos diversas (con ID y nombre)
bottom10_cfg <- div_cfg %>%
  arrange(H_shannon) %>%
  slice(1:10) %>%
  select(COMUNA_ID_NOMBRE, H_shannon, pielou, n_proyectos)

# Mostrar tablas en formato kable para Tipología CFG
cat("\n\n**10 comunas con mayor diversidad (Shannon_CFG)**\n")
## 
## 
## **10 comunas con mayor diversidad (Shannon_CFG)**
knitr::kable(top10_cfg, 
             col.names = c("Comuna (ID - Nombre)", "H_CFG (Shannon)", "J_CFG (Pielou)", "N° Proyectos"),
             digits = 3,
             caption = "Top 10 comunas con mayor índice de Shannon para CFG")
Top 10 comunas con mayor índice de Shannon para CFG
Comuna (ID - Nombre) H_CFG (Shannon) J_CFG (Pielou) N° Proyectos
141212-C-MIX-2016-02-0018 - 26. Comuna Prócer José Félix Ribas 1.831 0.941 9
141701-C-RUR-2018-11-0003 - COMUNA SOCIOPRODUCTIVA ALTO DE LA CARBONERA 1.792 1.000 6
141203-CEC-ME-025 - 18. PARROQUIA CARACCIOLO PARRA PÉREZ - COMUNA EN CONSTRUCCIÓN LAS HEROÍNAS DE MERIDA 1.609 1.000 5
141705-14-17-0000 - 25. Comuna El Paso de Bolívar 1813 1.609 1.000 5
141206-C-MIX-2018-11-0158 - COMUNA EN CONSTRUCCIÓN MUCUJÚN 1.561 0.970 6
141211-14-12-0001 - 7. Consejo Comunal Milla Parte Media 1.330 0.959 6
141211-14-12-0001 - 30. Consejo Comunal Unión Social 10 de Febrero 1.330 0.959 6
140101-C-MIX-2018-11-0147 - 8. COMUNA FIELES A CHÁVEZ 1.099 1.000 3
140101-C-RUR-2018-11-0018 - 14. COMUNA TIERRA DE ZAMORA 1.099 1.000 3
140101-C-RUR-2018-11-0019 - 12. COMUNA MANUELITA SÁENZ 1.099 1.000 3
cat("\n\n**10 comunas con menor diversidad (Shannon_CFG)**\n")
## 
## 
## **10 comunas con menor diversidad (Shannon_CFG)**
knitr::kable(bottom10_cfg,
             col.names = c("Comuna (ID - Nombre)", "H_CFG (Shannon)", "J_CFG (Pielou)", "N° Proyectos"),
             digits = 3,
             caption = "Top 10 comunas con menor índice de Shannon para CFG")
Top 10 comunas con menor índice de Shannon para CFG
Comuna (ID - Nombre) H_CFG (Shannon) J_CFG (Pielou) N° Proyectos
140101-C-URB-2018-11-0018 - 11. COMUNA UNIÓN DE CHÁVEZ 0.637 0.918 3
140103-14-01-0005 - 19. COMUNA El PASO DE LOS ANDES 0.637 0.918 3
140602-C-MIX-2021-05-0007 - COMUNA SU LEGADO ES NUESTRA FORTALEZA SIMON PABLO FIGUEROA. 0.637 0.918 3
140605-14-06-0001 - 20. COMUNA LOMAS UNIDAS MACHO CAPAZ 0.637 0.918 3
140606-C-RUR-2021-03-0002 - COMUNA IGNACIO FERNÁNDEZ PEÑA 0.637 0.918 3
141704-CEC-ME-108 - 27. Comuna en Construcción de Escaguey 0.637 0.918 3
142102-C-MIX-2021-10-0011 - COMUNA LOS IDEALES DE CHÁVEZ 0.637 0.918 3
142104-14-21-0002 - COMUNA PATRIA NUEVA. 0.637 0.918 3
140102-C-MIX-2021-01-0003 - COMUNA ETERNO GIGANTE 0.693 1.000 2
142006-C-MIX-2016-05-0006 - COMUNA SAN JUAN DE LOS LIBERTADORES COMANDANTE SUPREMO 0.868 0.790 6
## Preparar datos para gráfico consolidado para CFG
tabla_extremos_cfg <- bind_rows(
  top10_cfg  %>% mutate(tipo = "Top 10 ↑") %>% rename(COMUNA = COMUNA_ID_NOMBRE),
  bottom10_cfg %>% mutate(tipo = "Top 10 ↓") %>% rename(COMUNA = COMUNA_ID_NOMBRE)
) %>%
  # Crear etiqueta ordenada por H_shannon
  mutate(COMUNA_ORD = reorder(COMUNA, H_shannon))

#---------------Gráfico: Shannon (barras) + Pielou (línea) para CFG------------------------#
maxH <- max(tabla_extremos_cfg$H_shannon)

# Ajustar el gráfico con dimensiones específicas
cfg_plot <- ggplot(tabla_extremos_cfg, aes(x = COMUNA_ORD, y = H_shannon, fill = tipo)) +
  geom_line(aes(y = pielou * maxH, group = 1), 
            color = "#E69F00", size = 1.0, linetype = "dashed") +
  geom_point(aes(y = pielou * maxH), 
             color = "#D55E00", size = 2.5, shape = 18) +
  # Etiquetas de Pielou desplazadas a la derecha
  geom_text(aes(y = pielou * maxH, label = sprintf("J=%.2f", pielou)),
            hjust = -0.3, size = 2.5, color = "#D55E00") +  # Ajustado hjust

  geom_col(width = 0.7, alpha = 0.9) +
  geom_text(aes(y = H_shannon, label = sprintf("%.2f (%.1f)", H_shannon, exp(H_shannon))),
            hjust = 1.1, size = 2.8, color = "white", fontface = "bold") +  # Tamaño ajustado
  facet_wrap(~ tipo, scales = "free_y", ncol = 1) +
  coord_flip() +
  scale_y_continuous(
    name = "Índice de Shannon (H)",
    limits = c(0, maxH * 1.15), 
    sec.axis = sec_axis(~ . / maxH, name = "Índice de Pielou (J)",
                        labels = scales::number_format(accuracy = 0.1))
  ) +
  scale_fill_manual(values = c("Top 10 ↑" = "#56B4E9", "Top 10 ↓" = "#CC79A7")) +
  labs(
    title = "Diversidad de Tipologías CFG por Comuna",
    subtitle = "Top 10 comunas con mayor y menor diversidad | Barras: Shannon (H) | Línea: Pielou (J)",
    x = "Comuna (ID - Nombre)",
    caption = "Fuente: Elaboración propia datos de proyectos ACA - William Gutierrez"
  ) +
  theme_minimal(base_size = 10) +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(size = 10, color = "gray40", hjust = 0.5),
    axis.title.y = element_text(margin = margin(r = 10)),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.text.y = element_text(size = 8),  # Reducir tamaño texto eje Y
    panel.grid.major.y = element_blank(),
    strip.text = element_text(face = "bold", size = 11),
    legend.position = "none",
    plot.margin = margin(1, 2, 1, 1, "cm")  # Aumentar margen derecho
  )

# Guardar con dimensiones específicas
ggsave("cfg_diversity_plot.png", cfg_plot, width = 14, height = 10, dpi = 300)
print(cfg_plot)

## Calcular diversidad para Tipología de Gobernación con nombres
div_gob <- df_dummies %>%
  group_by(ID_COMUNA) %>%
  summarise(
    n_proyectos = n(),
    across(all_of(gob_cols), sum, na.rm = TRUE)
  ) %>%
  ungroup() %>%
  # Agregar nombres de comunas
  left_join(commune_map, by = "ID_COMUNA") %>%
  # Calcular índices de diversidad
  {
    cnts <- select(., all_of(gob_cols))
    tib <- select(., ID_COMUNA, COMUNA, n_proyectos)
    H <- vegan::diversity(cnts, index = "shannon")
    richesse <- rowSums(cnts > 0)
    J <- ifelse(richesse > 0, H / log(richesse), NA_real_)
    bind_cols(tib, H_shannon = H, pielou = J)
  }

# Crear columna combinada para mostrar en tablas
div_gob <- div_gob %>%
  mutate(COMUNA_ID_NOMBRE = paste(ID_COMUNA, "-", COMUNA))

## Mostrar tablas con nombres
top10_gob <- div_gob %>% 
  arrange(desc(H_shannon)) %>% 
  slice(1:10) %>%
  select(COMUNA_ID_NOMBRE, n_proyectos, H_shannon, pielou)

bottom10_gob <- div_gob %>% 
  arrange(H_shannon) %>% 
  slice(1:10) %>%
  select(COMUNA_ID_NOMBRE, n_proyectos, H_shannon, pielou)

cat("\n\n**Top 10 comunas con mayor diversidad (Shannon) de Gobernación**\n")
## 
## 
## **Top 10 comunas con mayor diversidad (Shannon) de Gobernación**
knitr::kable(top10_gob,
             col.names = c("Comuna (ID - Nombre)", "N° Proyectos", "H_GOB (Shannon)", "J_GOB (Pielou)"),
             digits = 3, 
             caption = "Top 10 comunas con mayor índice de Shannon para Gobernación")
Top 10 comunas con mayor índice de Shannon para Gobernación
Comuna (ID - Nombre) N° Proyectos H_GOB (Shannon) J_GOB (Pielou)
141212-C-MIX-2016-02-0018 - 26. Comuna Prócer José Félix Ribas 9 2.197 1.000
141206-C-MIX-2018-11-0158 - COMUNA EN CONSTRUCCIÓN MUCUJÚN 6 1.792 1.000
141203-CEC-ME-025 - 18. PARROQUIA CARACCIOLO PARRA PÉREZ - COMUNA EN CONSTRUCCIÓN LAS HEROÍNAS DE MERIDA 5 1.609 1.000
141705-14-17-0000 - 25. Comuna El Paso de Bolívar 1813 5 1.609 1.000
141701-C-RUR-2018-11-0003 - COMUNA SOCIOPRODUCTIVA ALTO DE LA CARBONERA 6 1.561 0.970
142006-C-MIX-2016-05-0006 - COMUNA SAN JUAN DE LOS LIBERTADORES COMANDANTE SUPREMO 6 1.561 0.970
141211-14-12-0001 - 7. Consejo Comunal Milla Parte Media 6 1.330 0.959
141211-14-12-0001 - 30. Consejo Comunal Unión Social 10 de Febrero 6 1.330 0.959
140101-C-MIX-2018-11-0147 - 8. COMUNA FIELES A CHÁVEZ 3 1.099 1.000
140101-C-RUR-2018-11-0018 - 14. COMUNA TIERRA DE ZAMORA 3 1.099 1.000
cat("\n\n**Top 10 comunas con menor diversidad (Shannon) de Gobernación**\n")
## 
## 
## **Top 10 comunas con menor diversidad (Shannon) de Gobernación**
knitr::kable(bottom10_gob,
             col.names = c("Comuna (ID - Nombre)", "N° Proyectos", "H_GOB (Shannon)", "J_GOB (Pielou)"),
             digits = 3, 
             caption = "Top 10 comunas con menor índice de Shannon para Gobernación")
Top 10 comunas con menor índice de Shannon para Gobernación
Comuna (ID - Nombre) N° Proyectos H_GOB (Shannon) J_GOB (Pielou)
140101-C-URB-2018-11-0018 - 11. COMUNA UNIÓN DE CHÁVEZ 3 0.637 0.918
141704-CEC-ME-108 - 27. Comuna en Construcción de Escaguey 3 0.637 0.918
140102-C-MIX-2021-01-0003 - COMUNA ETERNO GIGANTE 2 0.693 1.000
140101-C-MIX-2018-11-0147 - 8. COMUNA FIELES A CHÁVEZ 3 1.099 1.000
140101-C-RUR-2018-11-0018 - 14. COMUNA TIERRA DE ZAMORA 3 1.099 1.000
140101-C-RUR-2018-11-0019 - 12. COMUNA MANUELITA SÁENZ 3 1.099 1.000
140102-14-01-0006 - COMUNA SOCIALISTA EZEQUIEL ZAMORA 3 1.099 1.000
140102-14-01-2007 - COMUNA SIMON BOLÍVAR. 3 1.099 1.000
140102-C-MIX-2018-11-0019 - COMUNA PRESIDENTE OBRERO 3 1.099 1.000
140102-C-MIX-2018-11-0084 - COMUNA LUZ DEL ALBA 3 1.099 1.000
## Preparar datos para gráfico de Gobernación
tabla_extremos_gob <- bind_rows(
  top10_gob %>% mutate(tipo = "Top 10 ↑") %>% rename(COMUNA = COMUNA_ID_NOMBRE),
  bottom10_gob %>% mutate(tipo = "Top 10 ↓") %>% rename(COMUNA = COMUNA_ID_NOMBRE)
) %>%
  # Crear etiqueta ordenada por H_shannon
  mutate(COMUNA_ORD = reorder(COMUNA, H_shannon))


#-------------------------Gráfica de tipología de gobernación-----------------------------#
maxH_gob <- max(tabla_extremos_gob$H_shannon)

gob_plot <- ggplot(tabla_extremos_gob, aes(x = COMUNA_ORD, y = H_shannon, fill = tipo)) +
  geom_line(aes(y = pielou * maxH_gob, group = 1), 
            color = "#E69F00", size = 1.0, linetype = "dashed") +
  geom_point(aes(y = pielou * maxH_gob), 
             color = "#D55E00", size = 2.5, shape = 18) +
  # Etiquetas de Pielou desplazadas a la derecha
  geom_text(aes(y = pielou * maxH_gob, label = sprintf("J=%.2f", pielou)),
            hjust = -0.2, size = 2.5, color = "#D55E00") +
  # Luego dibujar las barras de Shannon
  geom_col(width = 0.7, alpha = 0.9) +
  geom_text(aes(y = H_shannon, label = sprintf("%.2f (%.1f)", H_shannon, exp(H_shannon))),
            hjust = 1.1, size = 2.8, color = "white", fontface = "bold") +
  facet_wrap(~ tipo, scales = "free_y", ncol = 1) +
  coord_flip() +
  scale_y_continuous(
    name = "Índice de Shannon (H)",
    limits = c(0, maxH_gob * 1.15),
    sec.axis = sec_axis(~ . / maxH_gob, name = "Índice de Pielou (J)",
                        labels = scales::number_format(accuracy = 0.1))
  ) +
  scale_fill_manual(values = c("Top 10 ↑" = "#56B4E9", "Top 10 ↓" = "#CC79A7")) +
  labs(
    title = "Diversidad Institucional (Gobernación) por Comuna",
    subtitle = "Top 10 comunas con mayor y menor diversidad | Barras: Shannon (H) | Línea: Pielou (J)",
    x = "Comuna (ID - Nombre)",
    caption = "Fuente: Elaboración propia datos de proyectos ACA - William Gutierrez"
  ) +
  theme_minimal(base_size = 10) +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(size = 10, color = "gray40", hjust = 0.5),
    axis.title.y = element_text(margin = margin(r = 10)),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.text.y = element_text(size = 8),  # Reducir tamaño texto eje Y
    panel.grid.major.y = element_blank(),
    strip.text = element_text(face = "bold", size = 11),
    legend.position = "none",
    plot.margin = margin(1, 2, 1, 1, "cm")  # Aumentar margen derecho
  )

# Guardar con dimensiones específicas
ggsave("gob_diversity_plot.png", gob_plot, width = 14, height = 10, dpi = 300)
print(gob_plot)

# ---------------------------------------------------
# CFG: gráfico con tooltips y ajuste para Pielou
# ---------------------------------------------------
maxH <- max(tabla_extremos_cfg$H_shannon, na.rm = TRUE)

cfg_plot2 <- ggplot(tabla_extremos_cfg, 
                    aes(x = COMUNA_ORD, 
                        y = H_shannon,
                        fill = tipo)) +
  # BARRAS con tooltip (text)
  geom_col(aes(text = paste0(
                    "Comuna: ", COMUNA, "\n",
                    "H = ", sprintf("%.2f", H_shannon), 
                    " (exp=", sprintf("%.1f", exp(H_shannon)), ")\n",
                    "J = ", sprintf("%.2f", pielou), "\n",
                    "N = ", n_proyectos
                )),
           width = 0.7, alpha = 0.95) +
  # LINEA y PUNTOS de Pielou (escalados)
  geom_line(aes(y = pielou * maxH, group = 1), 
            color = "#E69F00", size = 1.0, linetype = "dashed") +
  geom_point(aes(y = pielou * maxH,
                 text = paste0("Comuna: ", COMUNA, "\n",
                               "J = ", sprintf("%.2f", pielou), "\n",
                               "H = ", sprintf("%.2f", H_shannon))),
             color = "#D55E00", size = 3, shape = 18) +
  
  # Etiquetas de Pielou: colocadas ligeramente hacia la derecha (hjust negativo)
  geom_text(aes(y = pielou * maxH, label = sprintf("J=%.2f", pielou)),
            hjust = -0.08, size = 2.8, color = "#D55E00") +
  # Etiquetas dentro de las barras (H y exp(H))
  geom_text(aes(y = H_shannon, 
                label = sprintf("%.2f (%.1f)", H_shannon, exp(H_shannon))),
            hjust = 1.05, size = 2.9, color = "white", fontface = "bold") +
  facet_wrap(~ tipo, scales = "free_y", ncol = 1) +
  coord_flip() +
  scale_y_continuous(
    name = "Índice de Shannon (H)",
    limits = c(0, maxH * 1.30),   # aumentar para dar espacio a Pielou
    sec.axis = sec_axis(~ . / maxH, name = "Índice de Pielou (J)",
                        labels = scales::number_format(accuracy = 0.01))
  ) +
  scale_fill_manual(values = c("Top 10 ↑" = "#56B4E9", "Top 10 ↓" = "#CC79A7")) +
  labs(
    title = "Diversidad de Tipologías CFG por Comuna",
    subtitle = "Top 10 comunas con mayor y menor diversidad | Barras: Shannon (H) | Línea: Pielou (J)",
    x = "Comuna (ID - Nombre)",
    caption = "Fuente: Elaboración propia datos de proyectos ACA - William Gutierrez"
  ) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(size = 10, color = "gray40", hjust = 0.5),
    axis.text.y = element_text(size = 8),
    panel.grid.major.y = element_blank(),
    strip.text = element_text(face = "bold", size = 11),
    legend.position = "none",
    plot.margin = margin(t = 12, r = 120, b = 12, l = 180),  # margen derecho grande
    panel.spacing = unit(1, "lines"),
    panel.clip = "off"    # <-- permite que textos fuera del panel no se corten (ggplot2 >=3.4)
  )

# Guardar opcional (si quieres la imagen estática)
ggsave("cfg_diversity_plot_adj.png", cfg_plot2, width = 14, height = 10, dpi = 300)

# ---------------------------------------------------
# GOB: gráfico con tooltips y ajuste para Pielou
# ---------------------------------------------------
maxH_gob <- max(tabla_extremos_gob$H_shannon, na.rm = TRUE)

gob_plot2 <- ggplot(tabla_extremos_gob, aes(x = COMUNA_ORD, y = H_shannon, fill = tipo)) +
  geom_col(aes(text = paste0(
                    "Comuna: ", COMUNA, "\n",
                    "H = ", sprintf("%.2f", H_shannon), 
                    " (exp=", sprintf("%.1f", exp(H_shannon)), ")\n",
                    "J = ", sprintf("%.2f", pielou), "\n",
                    "N = ", n_proyectos
                )),
           width = 0.7, alpha = 0.95) +
  geom_line(aes(y = pielou * maxH_gob, group = 1), 
            color = "#E69F00", size = 1.0, linetype = "dashed") +
  geom_point(aes(y = pielou * maxH_gob,
                 text = paste0("Comuna: ", COMUNA, "\n",
                               "J = ", sprintf("%.2f", pielou), "\n",
                               "H = ", sprintf("%.2f", H_shannon))),
             color = "#D55E00", size = 3, shape = 18) +
  geom_text(aes(y = pielou * maxH_gob, label = sprintf("J=%.2f", pielou)),
            hjust = -0.08, size = 2.8, color = "#D55E00") +
  geom_text(aes(y = H_shannon, label = sprintf("%.2f (%.1f)", H_shannon, exp(H_shannon))),
            hjust = 1.05, size = 2.9, color = "white", fontface = "bold") +
  facet_wrap(~ tipo, scales = "free_y", ncol = 1) +
  coord_flip() +
  scale_y_continuous(
    name = "Índice de Shannon (H)",
    limits = c(0, maxH_gob * 1.30),
    sec.axis = sec_axis(~ . / maxH_gob, name = "Índice de Pielou (J)",
                        labels = scales::number_format(accuracy = 0.01))
  ) +
  scale_fill_manual(values = c("Top 10 ↑" = "#56B4E9", "Top 10 ↓" = "#CC79A7")) +
  labs(
    title = "Diversidad Institucional (Gobernación) por Comuna",
    subtitle = "Top 10 comunas con mayor y menor diversidad | Barras: Shannon (H) | Línea: Pielou (J)",
    x = "Comuna (ID - Nombre)",
    caption = "Fuente: Elaboración propia datos de proyectos ACA - William Gutierrez"
  ) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(size = 10, color = "gray40", hjust = 0.5),
    axis.text.y = element_text(size = 8),
    panel.grid.major.y = element_blank(),
    strip.text = element_text(face = "bold", size = 11),
    legend.position = "none",
    plot.margin = margin(t = 12, r = 120, b = 12, l = 180),
    panel.spacing = unit(1, "lines"),
    panel.clip = "off"
  )

# ---------------------------------------------------
# Convertir a plotly con dimensiones fijas y mostrar
# ---------------------------------------------------
plotly_fix_size <- function(ggobj, width = 1600, height = 800, margin = list(l = 180, r = 120, b = 100, t = 90)) {
  p <- ggplotly(ggobj, tooltip = "text")
  p <- p %>% layout(autosize = FALSE, width = width, height = height, margin = margin)
  # Aumentar botones útiles
  p <- p %>% config(displayModeBar = TRUE,
                    modeBarButtonsToAdd = list("toImage", "zoom2d", "resetScale2d"))
  return(p)
}

cfg_plotly <- plotly_fix_size(cfg_plot2, width = 1600, height = 800)
gob_plotly <- plotly_fix_size(gob_plot2, width = 1600, height = 800)

# Render (en R Markdown se mostrarán los dos en orden)
cfg_plotly
htmltools::tagList(htmltools::tags$br(), htmltools::tags$br())


gob_plotly
##================Tabla interpretativa del indice Shannon============================##
tbl <- tibble::tibble(
  Comuna = c(
    "141212 - Comuna Prócer José Félix Ribas",
    "141701 - Comuna Socioproductiva Alto de la Carbonera",
    "141203 - Comuna en Construcción Las Heroínas de Mérida",
    "142006 - Comuna San Juan de los Libertadores",
    "140101 - Comuna Unión de Chávez"
  ),
  H_CFG = c(1.831, 1.792, 1.609, 0.868, 0.637),
  e_CFG = round(exp(c(1.831, 1.792, 1.609, 0.868, 0.637)), 2),
  H_GOB = c(2.197, 1.561, 1.609, 1.561, 0.637),
  e_GOB = round(exp(c(2.197, 1.561, 1.609, 1.561, 0.637)), 2),
  Interpretacion = c(
    "Alta complejidad: ≈6 tipologías y ≈9 instituciones efectivas → coord. multisectorial requerida.",
    "Diversa y equilibrada: ≈6 tipologías y ≈4.77 instituciones → priorizar gobernanza compartida.",
    "Perfil multifuncional: ≈5 tipologías e instituciones efectivas → intervenciones integradas.",
    "Concentración moderada (≈2.38 tipologías) pero red institucional amplia (≈4.77) → revisar duplicidades.",
    "Fuerte focalización: ≈1.89 tipologías e instituciones → intervenciones focales de alto impacto."
  ),
  stringsAsFactors = FALSE
)

knitr::kable(
  tbl,
  caption = "Resumen: H' y Número efectivo (e^{H'}) — CFG vs Gobernación (5 comunas)",
  digits = 2,
  align = c("l", "r", "r", "r", "r", "l")
) %>%
  kableExtra::kable_styling(full_width = FALSE, bootstrap_options = c("striped", "condensed", "responsive"))
Resumen: H’ y Número efectivo (e^{H’}) — CFG vs Gobernación (5 comunas)
Comuna H_CFG e_CFG H_GOB e_GOB Interpretacion stringsAsFactors
141212 - Comuna Prócer José Félix Ribas 1.83 6.24 2.20 9.00 Alta complejidad: ≈6 tipologías y ≈9 instituciones efectivas → coord. multisectorial requerida. FALSE
141701 - Comuna Socioproductiva Alto de la Carbonera 1.79 6.00 1.56 4.76 Diversa y equilibrada: ≈6 tipologías y ≈4.77 instituciones → priorizar gobernanza compartida. FALSE
141203 - Comuna en Construcción Las Heroínas de Mérida 1.61 5.00 1.61 5.00 Perfil multifuncional: ≈5 tipologías e instituciones efectivas → intervenciones integradas. FALSE
142006 - Comuna San Juan de los Libertadores 0.87 2.38 1.56 4.76 Concentración moderada (≈2.38 tipologías) pero red institucional amplia (≈4.77) → revisar duplicidades. FALSE
140101 - Comuna Unión de Chávez 0.64 1.89 0.64 1.89 Fuerte focalización: ≈1.89 tipologías e instituciones → intervenciones focales de alto impacto. FALSE

10 Interpretación del Índice de Shannon (H′) y Pielou (J)

El análisis de diversidad (Índice de Shannon, H′) y de equitatividad (Índice de Pielou, J) permite caracterizar de forma compacta cómo cada comuna distribuye sus nudos críticos y qué implicaciones prácticas tiene esa distribución para la planificación y ejecución de proyectos.

-Veamos este ejemplo la Comunas con H′ alto (ej. 1.83 — 1.60): como 141212 - Comuna Prócer José Félix Ribas (H′=1.831, J=0.941, n=9) o 141701 - Alto de la Carbonera (H′=1.792, J=1.000, n=6), muestran alta diversidad temática y una distribución relativamente equilibrada (J cercano a 1)

Pueden representar (a) capacidad diagnóstica genuina, la comuna identifica múltiples problemáticas relevantes o (b) acumulación de carencias (abandono institucional). Para decidir entre (a) y (b) conviene cruzar H′ con indicadores de ejecución (Ratio ACA) y la intensidad de proyectos, además de entrevistas en directamente las comunas, una elemento importante no hecho en este trabajo.

  • Ahora con las Comunas con H′ bajo (como por ejemplos de 0.63 — 0.87): como varias entradas como 140101-C-URB-2018-11-0018 - 11. COMUNA UNIÓN DE CHÁVEZ del top menor (H′ ≈ 0.637, J ≈ 0.918), revelan focalización temática, una gran cantidad de comunas tienen esta focalización.

Puede tratarse de (a) priorización estratégica, concentración en problemas viables y mayor probabilidad de culminación o (b) desconexión/inviabilidad, cuando la baja diversidad responde a proyectos monumentales o a la repetición de un mismo problema sin avance real.

Nuevamente, el cruce con tasas de culminación y la escala de los proyectos permite distinguir estos escenarios.

  • Uso práctico: proponemos usar reglas simples para diagnóstico rápido:

    1. H′ alto + J alto + Ratio ACA bajo → señal de acumulación/abandono (requiere atención institucional y revisión de actores responsables).

    2. H′ alto + Ratio ACA altogestión integral efectiva (priorizar escalamiento de buenas prácticas).

    3. H′ bajo + Ratio ACA altofocalización estratégica efectiva (modelo replicable).

    4. H′ bajo + Ratio ACA bajoriesgo de inviabilidad (reformular alcance y actor responsable).

    En síntesis: H′ y J son indicadores sintéticos y útiles para clasificar comunas rápidamente; su valor real para la toma de decisiones aparece cuando se combinan con métricas de ejecución (Ratio ACA) y con la revisión cualitativa in situ.

La tabla muestra H′ (Shannon) y su conversión a número efectivo \(e^{H'}\) para las dimensiones CFG (tipologías) y Gobernación (actores).

Valores altos de \(e^{H'}\) indican una mayor carga de coordinación y complejidad operativa (ej. Comuna Prócer José Félix Ribas: ≈6 tipologías y ≈9 instituciones efectivas), por lo que requieren mecanismos de gobernanza integrados. Valores bajos señalan focalización temática y permiten intervenciones más directas y replicables (ej. Unión de Chávez: ≈1.9 tipologías).

En práctica, priorizar recursos donde \(e^{H'}\) es alto y replicar modelos de gestión en comunas con \(e^{H'}\) moderado/óptimo maximiza eficiencia.

11 Indice Shannon de ratio de proyecto por tipologías

La aplicación del índice de Shannon a la variable Ratio ACA Proyecto Culminado permite evaluar la diversidad de resultados o estados de culminación de los proyectos dentro de cada comuna. A diferencia de los análisis anteriores que medían la variedad de problemas o actores, este índice cuantifica aquí la heterogeneidad en la efectividad.

Como se hace en el primer análisis de Shannon, nos planteamos las siguiente hipótesis:

Valor de Shannon ALTO (H’ > 1,0)

  • Gestión Realista y Transparente, La comuna documenta de manera honesta un panorama mixto de éxitos, proyectos en curso y fracasos. La diversidad refleja una gestión activa de múltiples “micro demandas” con resultados variables. Número moderado-alto de proyectos.

  • Fragmentación e Inconsistencia, La diversidad de resultados es síntoma de una ejecución errática, donde el éxito depende de factores volátiles (actor institucional específico, recursos intermitentes), no de una estrategia coherente. - Baja efectividad promedio a pesar de la diversidad. Podría subestimarse el esfuerzo de gestionar realidades complejas.

Valor del Shannon BAJO (H’ < 0)

  • Efectividad Homogénea y Predecible, Todos los proyectos de la comuna comparten un mismo estado de alto éxito (“ALTA”), lo que indica una gestión excepcionalmente eficaz y consistente. Número viable de proyectos.

  • Falla Estructural y Desconexión, Todos los proyectos de la comuna están estancados en un mismo estado de baja efectividad (“MUY BAJA”/“BAJA”). Revela una desconexión total entre la planificación y la ejecución, o la insistencia en macroproyectos inviables. Proyectos ambiciosos o repetitivos. La comunidad podría percibirlo como abandono institucional.

knitr::opts_chunk$set(echo = TRUE)

        conflict_prefer("select", "dplyr")
        conflict_prefer("filter", "dplyr")

        ## **Indice Shannon de ratio de proyecto por tipologías**

        # Filtrar y preparar datos para Ratio
        df_ratio_clean <- df_raw %>% 
          filter(!is.na(RATIO_ACA_PROYECTO_CULMINADO)) %>%  
          mutate(
            RATIO_ACA_PROYECTO_CULMINADO = factor(
              RATIO_ACA_PROYECTO_CULMINADO,
              levels = 1:4,
              labels = c("MUY BAJA", "BAJA", "MEDIA", "ALTA")
            )
          )

        # Crear datos wide para diversidad
        df_ratio_wide <- df_ratio_clean %>%
          group_by(ID_COMUNA, RATIO_ACA_PROYECTO_CULMINADO) %>%
          summarise(n = n(), .groups = "drop") %>%
          complete(ID_COMUNA, RATIO_ACA_PROYECTO_CULMINADO, fill = list(n = 0)) %>%
          pivot_wider(
            names_from = RATIO_ACA_PROYECTO_CULMINADO, 
            values_from = n, 
            names_prefix = "ratio_"
          )

        # Asegurar que todas las columnas de ratio existan
        ratio_cols <- c("ratio_MUY BAJA", "ratio_BAJA", "ratio_MEDIA", "ratio_ALTA")
        for (col in ratio_cols) {
          if (!col %in% names(df_ratio_wide)) {
            df_ratio_wide[[col]] <- 0
          }
        }

        # Calcular diversidad para Ratio
        div_ratio <- df_ratio_wide %>%
          left_join(commune_map, by = "ID_COMUNA") %>%
          mutate(n_proyectos_ratio = rowSums(select(., all_of(ratio_cols)))) %>%
          {
            cnts <- select(., all_of(ratio_cols))
            tib <- select(., ID_COMUNA, COMUNA, n_proyectos_ratio)
            H <- vegan::diversity(cnts, index = "shannon")
            richesse <- rowSums(cnts > 0)
            J <- ifelse(richesse > 0, H / log(richesse), NA_real_)
            bind_cols(tib, H_shannon = H, pielou = J)
          } %>%
          mutate(COMUNA_ID_NOMBRE = paste(ID_COMUNA, "-", COMUNA))

        # Crear top y bottom 10
        top10_ratio <- div_ratio %>%
          arrange(desc(H_shannon)) %>%
          slice(1:10) %>%
          select(COMUNA_ID_NOMBRE, n_proyectos_ratio, H_shannon, pielou)

        bottom10_ratio <- div_ratio %>%
          arrange(H_shannon) %>%
          slice(1:10) %>%
          select(COMUNA_ID_NOMBRE, n_proyectos_ratio, H_shannon, pielou)

        # Preparar datos para gráfico
        tabla_extremos_ratio <- bind_rows(
          top10_ratio %>% 
            mutate(tipo = "Mayor diversidad (Top 10)") %>% 
            rename(COMUNA = COMUNA_ID_NOMBRE),
          bottom10_ratio %>% 
            mutate(tipo = "Menor diversidad (Bottom 10)") %>% 
            rename(COMUNA = COMUNA_ID_NOMBRE)
        ) %>%
          mutate(
            etiqueta_H = sprintf("H: %.2f", H_shannon),
            etiqueta_J = sprintf("J: %.2f", pielou)
          )
        ## Tabla completa (Todas las comunas)
        div_ratio_completo <- div_ratio %>%
          select(COMUNA_ID_NOMBRE, n_proyectos_ratio, H_shannon, pielou) %>%
          arrange(desc(H_shannon)) %>%
          mutate(
            H_shannon = round(H_shannon, 3),
            pielou = round(pielou, 3),
            # Interpretación rápida
            Interpretacion = case_when(
              H_shannon < 0.5 ~ "Baja diversidad",
              H_shannon >= 0.5 & H_shannon < 1.0 ~ "Diversidad media",
              H_shannon >= 1.0 ~ "Alta diversidad"
            )
          )

        # Mostrar tabla completa ordenada por diversidad
        cat("\n\n**Diversidad de Ratio ACA en todas las comunas**\n")
## 
## 
## **Diversidad de Ratio ACA en todas las comunas**
        knitr::kable(
          div_ratio_completo,
          col.names = c("Comuna (ID - Nombre)", "Proyectos", "H (Shannon)", "J (Pielou)", "Interpretación"),
          digits = 3,
          caption = "Diversidad de estados de culminación en todas las comunas"
        )
Diversidad de estados de culminación en todas las comunas
Comuna (ID - Nombre) Proyectos H (Shannon) J (Pielou) Interpretación
141212-C-MIX-2016-02-0018 - 26. Comuna Prócer José Félix Ribas 9 1.311 0.946 Alta diversidad
140101-C-RUR-2018-11-0019 - 12. COMUNA MANUELITA SÁENZ 3 1.099 1.000 Alta diversidad
140102-C-MIX-2018-11-0019 - COMUNA PRESIDENTE OBRERO 3 1.099 1.000 Alta diversidad
140103-14-01-0002 - COMUNA AGRARIA SOCIALISTA GUACHARE 3 1.099 1.000 Alta diversidad
140103-14-01-0005 - 19. COMUNA El PASO DE LOS ANDES 3 1.099 1.000 Alta diversidad
140301-C-MIX-2018-02-0043 - 28. Comuna Socialista Agroindustrial de Paiva 3 1.099 1.000 Alta diversidad
140301-C-RUR-2021-10-0022 - COMUNA AGROTURÍSTICA LA NEBLINA DE SALINAS 3 1.099 1.000 Alta diversidad
140802-C-MIX-2018-02-0019 - COMUNA CARRIZALES UNIDOS 3 1.099 1.000 Alta diversidad
141207-C-MIX-2015-11-0005 - COMUNA SAN JACINTO ABRIENDO BRECHA 3 1.099 1.000 Alta diversidad
141601-C-RUR-2018-11-0024 - COMUNA PRODUCTIVA AMANECER CAMPESINO 3 1.099 1.000 Alta diversidad
141601-C-RUR-2018-11-0027 - COMUNA LA PIEDRA QUE CRECE EN REVOLUCIÓN 3 1.099 1.000 Alta diversidad
141901-C-MIX-2018-06-0007 - 15. COMUNA ECOSOCIALISTA, AGROTURÍSTICA Y CULTURAL MUCUY 3 1.099 1.000 Alta diversidad
142104-14-21-0002 - COMUNA PATRIA NUEVA. 3 1.099 1.000 Alta diversidad
141203-CEC-ME-025 - 18. PARROQUIA CARACCIOLO PARRA PÉREZ - COMUNA EN CONSTRUCCIÓN LAS HEROÍNAS DE MERIDA 5 1.055 0.960 Alta diversidad
141206-C-MIX-2018-11-0158 - COMUNA EN CONSTRUCCIÓN MUCUJÚN 6 1.011 0.921 Alta diversidad
141701-C-RUR-2018-11-0003 - COMUNA SOCIOPRODUCTIVA ALTO DE LA CARBONERA 6 1.011 0.921 Alta diversidad
142006-C-MIX-2016-05-0006 - COMUNA SAN JUAN DE LOS LIBERTADORES COMANDANTE SUPREMO 6 1.011 0.921 Alta diversidad
140102-C-MIX-2021-01-0003 - COMUNA ETERNO GIGANTE 2 0.693 1.000 Diversidad media
141211-14-12-0001 - 7. Consejo Comunal Milla Parte Media 6 0.693 1.000 Diversidad media
141211-14-12-0001 - 30. Consejo Comunal Unión Social 10 de Febrero 6 0.693 1.000 Diversidad media
141705-14-17-0000 - 25. Comuna El Paso de Bolívar 1813 5 0.673 0.971 Diversidad media
140101-C-RUR-2018-11-0018 - 14. COMUNA TIERRA DE ZAMORA 3 0.637 0.918 Diversidad media
140102-14-01-0006 - COMUNA SOCIALISTA EZEQUIEL ZAMORA 3 0.637 0.918 Diversidad media
140102-14-01-2007 - COMUNA SIMON BOLÍVAR. 3 0.637 0.918 Diversidad media
140102-C-MIX-2018-11-0084 - COMUNA LUZ DEL ALBA 3 0.637 0.918 Diversidad media
140102-C-MIX-2021-02-0004 - COMUNA ROSA LUXEMBURGO 3 0.637 0.918 Diversidad media
140102-C-MIX-2021-02-0005 - COMUNA FRANCISCO DE MIRANDA 3 0.637 0.918 Diversidad media
140103-14-01-0003 - COMUNA INDIA CARIBAY 3 0.637 0.918 Diversidad media
140303-14-03-0000 - Comuna La Cafetalera 3 0.637 0.918 Diversidad media
140601-C-MIX-2021-04-0012 - COMUNA PASO DE BOLIVAR POR LOS ANDES. 3 0.637 0.918 Diversidad media
140601-C-URB-2021-03-0010 - 17. COMUNA El GRAN CAÑAVERAL 3 0.637 0.918 Diversidad media
140602-C-MIX-2021-05-0007 - COMUNA SU LEGADO ES NUESTRA FORTALEZA SIMON PABLO FIGUEROA. 3 0.637 0.918 Diversidad media
140602-C-MIX-2021-05-0008 - 10. COMUNA YUBÁN ORTEGA SEMBRADOR DE ESPERANZAS 3 0.637 0.918 Diversidad media
140602-C-URB-2021-05-0008 - Comuna Socialista Libertadores de Conciencia Bolívar y Chávez 3 0.637 0.918 Diversidad media
140603-C-MIX-2018-11-0077 - 13. COMUNA AGROECOLÓGICA CULTURAL DE MONTAÑA KLÉBER RAMÍREZ ROJAS 3 0.637 0.918 Diversidad media
140605-14-06-0001 - 20. COMUNA LOMAS UNIDAS MACHO CAPAZ 3 0.637 0.918 Diversidad media
140606-C-RUR-2021-03-0002 - COMUNA IGNACIO FERNÁNDEZ PEÑA 3 0.637 0.918 Diversidad media
141201-C-URB-2021-07-0004 - COMUNA FANNY PRIETO. 3 0.637 0.918 Diversidad media
141204-14-12-0000 - COMUNA BICENTENARIA 16 DE SEPTIEMBRE. 3 0.637 0.918 Diversidad media
141207-14-12-0003 - COMUNA VALLE DEL CHAMA 3 0.637 0.918 Diversidad media
141207-14-12-0005 - COMUNA DON SIMÓN RODRÍGUEZ 3 0.637 0.918 Diversidad media
141303-C-MIX-2018-11-0113 - COMUNA VALLE DE LA VENTA 3 0.637 0.918 Diversidad media
141403-C-RUR-2017-04-0001 - 22. Comuna Socialista Una Esperanza Viva 3 0.637 0.918 Diversidad media
141601-CEC-ME-002 - CONSEJO COMUNAL LLANO GRANDE PARTE ALTA 3 0.637 0.918 Diversidad media
141704-CEC-ME-108 - 27. Comuna en Construcción de Escaguey 3 0.637 0.918 Diversidad media
141801-14-18-0000 - COMUNA SOCIALISTA PARAMO DE MARIÑO TIERRA DE LAGUNAS Y ENCANTOS 3 0.637 0.918 Diversidad media
141801-C-RUR-2018-11-0043 - COMUNA TRADICIONES Y VIVENCIAS DE BODOQUE 3 0.637 0.918 Diversidad media
142001-C-MIX-2018-08-0037 - COMUNA AGROECOLOGICA DOÑA SIMONA 3 0.637 0.918 Diversidad media
142101-14-21-0001 - COMUNA VENCEDORES EL AMPARO 3 0.637 0.918 Diversidad media
142102-C-MIX-2021-04-0013 - COMUNA TODOS JUNTOS VENCEREMOS 3 0.637 0.918 Diversidad media
142102-C-MIX-2021-10-0011 - COMUNA LOS IDEALES DE CHÁVEZ 3 0.637 0.918 Diversidad media
142104-14-21-0000 - Comuna Mucutíes 3 0.637 0.918 Diversidad media
140101-C-MIX-2018-11-0147 - 8. COMUNA FIELES A CHÁVEZ 3 0.000 NaN Baja diversidad
140101-C-URB-2018-11-0018 - 11. COMUNA UNIÓN DE CHÁVEZ 3 0.000 NaN Baja diversidad
140301-C-MIX-2021-10-0006 - COMUNA LA NUEVA FUERZA DE CHÁVEZ 3 0.000 NaN Baja diversidad
140301-CEC-ME-062 - Sector Comunal Casco Central 3 0.000 NaN Baja diversidad
140603-C-URB-2021-06-0003 - 8. COMUNA BRISAS DE MONTALBÁN. 3 0.000 NaN Baja diversidad
141301-C-MIX-2018-11-0168 - COMUNA VALLE DEL MOTATÁN 3 0.000 NaN Baja diversidad
141403-C-RUR-2017-02-0003 - 24. PENSAMIENTO CAMPESINO 3 0.000 NaN Baja diversidad
141403-C-RUR-2017-03-0002 - 23. Comuna El Sueño de Nuestro Comandante Eterno 3 0.000 NaN Baja diversidad
        # Preparar datos para gráfico (sin crear etiquetas pre-definidas)
        tabla_extremos_ratio <- bind_rows(
          top10_ratio %>% 
            mutate(tipo = "Mayor diversidad (Top 10)") %>% 
            rename(COMUNA = COMUNA_ID_NOMBRE),
          bottom10_ratio %>% 
            mutate(tipo = "Menor diversidad (Bottom 10)") %>% 
            rename(COMUNA = COMUNA_ID_NOMBRE)
        )
        # Nota: Removimos las etiquetas pre-definidas etiqueta_H y etiqueta_J

        # Calcular maxH_ratio
        maxH_ratio <- max(tabla_extremos_ratio$H_shannon, na.rm = TRUE) * 1.3

        # Crear gráfico con valores exponenciales en las etiquetas
        ratio_plot <- ggplot(tabla_extremos_ratio, aes(x = reorder(COMUNA, H_shannon), y = H_shannon, fill = tipo)) +
          geom_col(alpha = 0.85, width = 0.7) +
          
          # Etiquetas de Shannon con valor exponencial
          geom_text(
            aes(label = sprintf("%.2f (%.1f)", H_shannon, exp(H_shannon)), y = H_shannon * 0.5), 
            color = "white", 
            fontface = "bold",
            size = 2.8  # Reducido ligeramente
          ) +
          
          # Etiquetas de Pielou
          geom_text(
            aes(label = sprintf("J=%.2f", pielou), y = H_shannon + 0.05 * maxH_ratio),
            color = "#D55E00",
            size = 2.8,  # Reducido
            hjust = 0
          ) +
          
          # Línea y puntos de Pielou
          geom_line(
            aes(y = pielou * maxH_ratio, group = tipo), 
            color = "#E69F00", 
            linewidth = 1.2, 
            linetype = "solid"
          ) +
          geom_point(
            aes(y = pielou * maxH_ratio), 
            color = "#D55E00", 
            size = 3, 
            shape = 18
          ) +
          
          # Configuración del gráfico
          facet_wrap(
            ~ tipo, 
            scales = "free_y", 
            ncol = 1,
            strip.position = "top"
          ) +
          coord_flip() +
          scale_y_continuous(
            name = "Índice de Shannon (H)",
            sec.axis = sec_axis(
              ~ . / maxH_ratio, 
              name = "Índice de Pielou (J)",
              labels = scales::number_format(accuracy = 0.1)
            ),
            expand = expansion(mult = c(0, 0.15))
          ) +
          scale_fill_manual(values = c(
            "Mayor diversidad (Top 10)" = "#1b9e77", 
            "Menor diversidad (Bottom 10)" = "#d95f02"
          )) +
          labs(
            title = "Diversidad de estados de culminación de proyectos",
            subtitle = "Comunas con mayor y menor diversidad en estados de proyectos (Ratio ACA)",
            x = "Comuna (ID - Nombre)",
            caption = "Fuente: Elaboración propia - Proyectos ACA (2022-2025)\nNota: Barras = Shannon (H) con valor exponencial, Línea = Pielou (J)"
          ) +
          theme_minimal(base_size = 11) +  # Base size reducido
          theme(
            plot.title = element_text(face = "bold", size = 14, hjust = 0.5),  # Título más pequeño
            plot.subtitle = element_text(size = 11, color = "gray30", hjust = 0.5),
            axis.title.y = element_text(margin = margin(r = 15)),
            axis.title.x = element_text(margin = margin(t = 10)),
            axis.text.y = element_text(size = 8),  # Texto del eje Y más pequeño
            panel.grid.major.y = element_blank(),
            strip.text = element_text(face = "bold", size = 11, color = "white"),
            strip.background = element_rect(fill = "gray25", color = NA),
            legend.position = "none",
            panel.spacing = unit(1, "lines"),
            plot.margin = margin(1, 2, 1, 1, "cm")  # Margen derecho aumentado
          )

        # Guardar con dimensiones específicas
        ggsave("ratio_diversity_plot.png", ratio_plot, width = 14, height = 10, dpi = 300)
        print(ratio_plot)

 # Crear gráfico interactivo para diversidad de Ratio ACA (Top/Bottom) con e^{H'} y ajustes de presentación
# Nota: asume que df_raw y commune_map ya existen (como en tu chunk anterior).

# --- 1. Preparar datos (recrea el procedimiento de ratio y calcula e^{H'})
df_ratio_clean <- df_raw %>% 
  filter(!is.na(RATIO_ACA_PROYECTO_CULMINADO)) %>%  
  mutate(
    RATIO_ACA_PROYECTO_CULMINADO = factor(
      RATIO_ACA_PROYECTO_CULMINADO,
      levels = 1:4,
      labels = c("MUY BAJA", "BAJA", "MEDIA", "ALTA")
    )
  )

df_ratio_wide <- df_ratio_clean %>%
  group_by(ID_COMUNA, RATIO_ACA_PROYECTO_CULMINADO) %>%
  summarise(n = n(), .groups = "drop") %>%
  complete(ID_COMUNA, RATIO_ACA_PROYECTO_CULMINADO, fill = list(n = 0)) %>%
  pivot_wider(
    names_from = RATIO_ACA_PROYECTO_CULMINADO, 
    values_from = n, 
    names_prefix = "ratio_"
  )

# Asegurar columnas ratio
ratio_cols <- c("ratio_MUY BAJA", "ratio_BAJA", "ratio_MEDIA", "ratio_ALTA")
for (col in ratio_cols) {
  if (!col %in% names(df_ratio_wide)) df_ratio_wide[[col]] <- 0
}

div_ratio <- df_ratio_wide %>%
  left_join(commune_map, by = "ID_COMUNA") %>%
  mutate(n_proyectos_ratio = rowSums(select(., all_of(ratio_cols)))) %>%
  {
    cnts <- select(., all_of(ratio_cols))
    tib <- select(., ID_COMUNA, COMUNA, n_proyectos_ratio)
    H <- vegan::diversity(cnts, index = "shannon")
    richesse <- rowSums(cnts > 0)
    J <- ifelse(richesse > 0, H / log(richesse), NA_real_)
    bind_cols(tib, H_shannon = H, pielou = J)
  } %>%
  mutate(COMUNA_ID_NOMBRE = paste(ID_COMUNA, "-", COMUNA)) %>%
  # calcular exponencial para interpretación
  mutate(e_H = round(exp(H_shannon), 2))

# Top / Bottom 10
top10_ratio <- div_ratio %>% arrange(desc(H_shannon)) %>% slice(1:10) %>% 
  select(COMUNA_ID_NOMBRE, n_proyectos_ratio, H_shannon, pielou, e_H)

bottom10_ratio <- div_ratio %>% arrange(H_shannon) %>% slice(1:10) %>% 
  select(COMUNA_ID_NOMBRE, n_proyectos_ratio, H_shannon, pielou, e_H)

tabla_extremos_ratio <- bind_rows(
  top10_ratio  %>% mutate(tipo = "Mayor diversidad (Top 10)")  %>% rename(COMUNA = COMUNA_ID_NOMBRE),
  bottom10_ratio %>% mutate(tipo = "Menor diversidad (Bottom 10)") %>% rename(COMUNA = COMUNA_ID_NOMBRE)
) %>%
  # crear texto para tooltip
  mutate(
    tooltip = paste0(
      "Comuna: ", COMUNA, "\n",
      "Proyectos: ", n_proyectos_ratio, "\n",
      "H = ", sprintf("%.3f", H_shannon), "  |  e^{H} = ", sprintf("%.2f", e_H), "\n",
      "J = ", sprintf("%.3f", pielou)
    )
  )

# --- 2. Gráfico (ggplot) con ajuste para evitar clipping y espacio para etiquetas ---
maxH_ratio <- max(tabla_extremos_ratio$H_shannon, na.rm = TRUE)
maxH_plot <- maxH_ratio * 1.3

ratio_plot2 <- ggplot(tabla_extremos_ratio, aes(x = reorder(COMUNA, H_shannon), y = H_shannon, fill = tipo)) +
  geom_col(aes(text = tooltip), alpha = 0.88, width = 0.72) +
  # etiquetas H + e^H dentro de la barra (posicionado más cerca del centro para no solaparse)
  geom_text(aes(y = H_shannon * 0.45, label = sprintf("%.2f (%.1f)", H_shannon, e_H)),
            color = "white", fontface = "bold", size = 2.8) +
  # Pielou: texto ligeramente por encima de la barra (y = H + offset)
  geom_text(aes(y = H_shannon + 0.04 * maxH_plot, label = sprintf("J=%.2f", pielou)),
            color = "#D55E00", size = 2.8, hjust = 0) +
  # Linea y puntos de Pielou escalada
  geom_line(aes(y = pielou * maxH_plot, group = tipo), color = "#E69F00", linewidth = 1.1) +
  geom_point(aes(y = pielou * maxH_plot), color = "#D55E00", size = 3, shape = 18) +
  facet_wrap(~ tipo, scales = "free_y", ncol = 1, strip.position = "top") +
  coord_flip() +
  scale_y_continuous(
    name = "Índice de Shannon (H)",
    limits = c(0, maxH_plot),
    sec.axis = sec_axis(~ . / maxH_plot, name = "Índice de Pielou (J)", labels = scales::number_format(accuracy = 0.01))
  ) +
  scale_fill_manual(values = c("Mayor diversidad (Top 10)" = "#1b9e77", "Menor diversidad (Bottom 10)" = "#d95f02")) +
  labs(
    title = "Diversidad de estados de culminación de proyectos (Ratio ACA)",
    subtitle = "Top 10 mayor y menor diversidad | Barras: H (con e^{H}) | Línea: J",
    x = "Comuna (ID - Nombre)",
    caption = "Fuente: Elaboración propia - Proyectos ACA (2022-2025)"
  ) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(size = 11, color = "gray30", hjust = 0.5),
    axis.text.y = element_text(size = 8),
    panel.grid.major.y = element_blank(),
    strip.text = element_text(face = "bold", size = 10, color = "white"),
    strip.background = element_rect(fill = "gray25", color = NA),
    legend.position = "none",
    panel.spacing = unit(1, "lines"),
    # márgenes y clip off para que etiquetas no se corten
    plot.margin = margin(t = 12, r = 120, b = 12, l = 180),
    panel.clip = "off"
  )

# --- 3. Convertir a plotly con tamaño fijo 1600x800 y mostrar ---
plotly_fix_size <- function(ggobj, width = 1600, height = 800, margin = list(l = 200, r = 120, b = 100, t = 90)) {
  p <- ggplotly(ggobj, tooltip = "text")
  p <- p %>% layout(autosize = FALSE, width = width, height = height, margin = margin)
  p <- p %>% config(displayModeBar = TRUE, modeBarButtonsToAdd = list("toImage", "zoom2d", "resetScale2d"))
  return(p)
}

ratio_plotly <- plotly_fix_size(ratio_plot2, width = 1600, height = 800)
ratio_plotly

Diversidad de estados de culminación (Ratio ACA)

El índice de Shannon aplicado al Ratio ACA sintetiza cuán dispersos o concentrados están los resultados de los proyectos dentro de cada comuna. Valores altos de H’ (por ejemplo, Comuna Prócer José Félix Ribas, H’ = 1.311 → eH’3.71) indican que la comuna concentra resultados en casi 4 categorías distintas de efectividad, lo que refleja heterogeneidad operativa: puede ser gestión activa y variada o ejecución errática. Valores medios (H’ ≈ 0.637 → eH’1.89) muestran que la mayoría de comunas operan con menos de 2 estados efectivos, lo que sugiere concentración de resultados (habitualmente en “MUY BAJA/BAJA”). Valores nulos (H′ = 0) equivalen a 1 estado efectivo: situación crítica que demanda reingeniería urgente.

El hallazgo más alarmante es la existencia de ocho (8) comunas con diversidad nula (H’ = 0,000), donde el 100% de sus proyectos comparten el mismo estado de culminación. Dado el contexto socio institucional venezolano, es altamente probable que el estado común sea “MUY BAJA” o “BAJA”. Esto confirma de manera contundente la Hipótesis 4 (Falla Estructural y Desconexión). Comunas como Unión de Chávez y Pensamiento Campesino representan el caso más crítico: el instrumento de las ACA ha fallado por completo en generar avances tangibles, evidenciando una parálisis total de la gestión proyectiva ya sea por el abandono institucional o la obstinación en macroproyectos inviables.

Reglas operativas (resumen):
- eH’ ≈ 1 → intervención urgente y reingeniería.
- 1 < eH’ < 3 → consolidación y auditoría de procesos.
- eH’ ≥ 3 → análisis cualitativo para distinguir complejidad gestionable vs. fragmentación institucional. “)

\[ H' = -\sum_{i=1}^{S} p_i \ln(p_i) \]

\[ \text{Número efectivo} = e^{H'} \]

Interpretación por comunas

  • Comuna Prócer José Félix Ribas\(H' = 1.311\)\(e^{H'} \approx 3.71\) — 9 proyectos. Alta heterogeneidad: se comporta como si tuviera ≈ 4 tipos de resultado (desde proyectos culminados hasta no considerados); requiere coordinación multisectorial.

  • Comuna Las Heroínas de Mérida\(H' = 1.055\)\(e^{H'} \approx 2.87\) — 5 proyectos. Diversidad notable: ≈ 3 tipos de resultado; conviene investigar qué explica la mezcla de éxitos y fracasos.

  • Comuna Mucujún\(H' = 1.011\)\(e^{H'} \approx 2.75\) — 6 proyectos. Complejidad moderada: ≈ 2–3 tipos efectivos; hacer un análisis cualitativo.

  • Comuna Alto de la Carbonera\(H' = 1.011\)\(e^{H'} \approx 2.75\) — 6 proyectos. Variabilidad similar a Mucujún; priorizar coordinación institucional.

  • Comuna Manuelita Sáenz\(H' = 1.099\)\(e^{H'} \approx 3.00\) — 3 proyectos. Alta diversidad pese al bajo número de proyectos; investigar la causa de la variabilidad.

  • Comuna El Paso de Bolívar 1813\(H' = 0.673\)\(e^{H'} \approx 1.96\) — 5 proyectos. Diversidad moderada: ≈ 2 tipos de resultado; buen candidato para intervenciones focales.

  • Comuna Eterno Gigante\(H' = 0.693\)\(e^{H'} \approx 2.00\) — 2 proyectos. Resultados concentrados en ~2 clases; acciones puntuales pueden tener alto impacto.

  • Comuna Unión de Chávez\(H' = 0.000\)\(e^{H'} = 1.00\) — 3 proyectos. Diversidad nula: todos los proyectos comparten el mismo estado → intervención urgente (reingeniería y apoyo técnico).

12 Aplicación de normalidad

Para determinar la relación entre las variables de estudio, es fundamental seleccionar la prueba estadística adecuada. La elección entre un método paramétrico (como el coeficiente de correlación de Pearson) y uno no paramétrico (como el coeficiente de correlación de Spearman) depende crucialmente de si los datos cumplen con el supuesto de normalidad. La violación de este supuesto puede llevar a conclusiones erróneas, afectando la validez del análisis estadístico. Por ello, antes de proceder con el análisis correlacional, se realizó una prueba de bondad de ajuste para evaluar la distribución de las variables clave de la investigación.

Para evaluar la normalidad de los datos, se seleccionó la prueba de Shapiro-Wilk. Esta elección se fundamenta en su reconocida potencia para detectar desviaciones de la normalidad (Arce & Rosales, 2015), si bien esta se restringió originalmente para tamaños de muestra pequeña (n < 50), esta prueba es la más potente y común su uso en el análisis de normalidad de los datos de cualquier estudio.

## Preparación de los datos
 # Eliminar valores nulos si es necesario
df_clean <- df_raw %>% filter(!is.na(n_proyectos) & !is.na(PLAZOS) & !is.na(CLASIFICACION_DEL_PROYECTO)& !is.na(RATIO_ACA_PROYECTO_CULMINADO)& !is.na(Clasificacion_Actores_institucionales)& !is.na(TIPOLOGIA_CFG_NUM)& !is.na(GOBERNACION_NUM))

# Función para crear un panel de diagnóstico de normalidad
create_normality_diagnostic <- function(data, variable, variable_name) {
  # Datos para la variable
  x <- data[[variable]]
  
  # Histograma con curva de densidad
  p1 <- ggplot(data, aes_string(x = variable)) +
    geom_histogram(aes(y = ..density..), bins = 30, fill = "lightblue", color = "black", alpha = 0.7) +
    geom_density(color = "red", linewidth = 1) +
    stat_function(fun = dnorm, 
                 args = list(mean = mean(x, na.rm = TRUE), 
                           sd = sd(x, na.rm = TRUE)),
                 color = "blue", linewidth = 1, linetype = "dashed") +
    labs(title = paste("Histograma y Densidad -", variable_name),
         x = variable_name, y = "Densidad") +
    theme_minimal()
  
  # Q-Q plot
  p2 <- ggplot(data, aes(sample = x)) +
    stat_qq() +
    stat_qq_line(color = "red") +
    labs(title = paste("Q-Q Plot -", variable_name)) +
    theme_minimal()
  
  # Combinar los gráficos
  gridExtra::grid.arrange(p1, p2, ncol = 2)
}

# Lista de variables para analizar
variables_to_analyze <- list(
  "n_proyectos" = "Número de Proyectos",
  "RATIO_ACA_PROYECTO_CULMINADO" = "Ratio ACA",
  "TIPOLOGIA_CFG_NUM" = "Tipología CFG",
  "GOBERNACION_NUM" = "Gobernación",
  "PLAZOS" = "Plazos",
  "CLASIFICACION_DEL_PROYECTO" = "Clasificación del Proyecto",
  "Clasificacion_Actores_institucionales" = "Actores Institucionales"
)

# Crear un panel para cada variable
for(var in names(variables_to_analyze)) {
  cat("\n\nAnálisis de normalidad para:", variables_to_analyze[[var]], "\n")
  print(create_normality_diagnostic(df_clean, var, variables_to_analyze[[var]]))
  
  # Imprimir resultados del test de Shapiro-Wilk
  sw_test <- shapiro.test(df_clean[[var]])
  cat("\nTest de Shapiro-Wilk:\n")
  cat("W =", round(sw_test$statistic, 4), "\n")
  cat("p-value =", format.pval(sw_test$p.value, digits = 4), "\n")
  cat("-----------------------------------\n")
}
## 
## 
## Análisis de normalidad para: Número de Proyectos

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.5502 
## p-value = < 2.2e-16 
## -----------------------------------
## 
## 
## Análisis de normalidad para: Ratio ACA

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.7444 
## p-value = < 2.2e-16 
## -----------------------------------
## 
## 
## Análisis de normalidad para: Tipología CFG

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.8753 
## p-value = 1.027e-11 
## -----------------------------------
## 
## 
## Análisis de normalidad para: Gobernación

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.8601 
## p-value = 1.622e-12 
## -----------------------------------
## 
## 
## Análisis de normalidad para: Plazos

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.4559 
## p-value = < 2.2e-16 
## -----------------------------------
## 
## 
## Análisis de normalidad para: Clasificación del Proyecto

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.7444 
## p-value = < 2.2e-16 
## -----------------------------------
## 
## 
## Análisis de normalidad para: Actores Institucionales

## TableGrob (1 x 2) "arrange": 2 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 
## Test de Shapiro-Wilk:
## W = 0.8347 
## p-value = 9.828e-14 
## -----------------------------------
# Preparar el espacio para múltiples gráficos
par(mfrow = c(2, 4))  # 2 filas x 4 columnas para acomodar todos los Q-Q plots

# Crear Q-Q plots para cada variable con títulos descriptivos
qqnorm(df_clean$n_proyectos, main="Q-Q Plot: N° Proyectos",
       col = "blue", pch = 19)
qqline(df_clean$n_proyectos, col = "red")

qqnorm(df_clean$RATIO_ACA_PROYECTO_CULMINADO, main="Q-Q Plot: Ratio ACA",
       col = "green4", pch = 19)
qqline(df_clean$RATIO_ACA_PROYECTO_CULMINADO, col = "red")

qqnorm(df_clean$TIPOLOGIA_CFG_NUM, main="Q-Q Plot: Tipología CFG",
       col = "purple", pch = 19)
qqline(df_clean$TIPOLOGIA_CFG_NUM, col = "red")

qqnorm(df_clean$GOBERNACION_NUM, main="Q-Q Plot: Gobernación",
       col = "orange", pch = 19)
qqline(df_clean$GOBERNACION_NUM, col = "red")

qqnorm(df_clean$PLAZOS, main="Q-Q Plot: Plazos",
       col = "brown", pch = 19)
qqline(df_clean$PLAZOS, col = "red")

qqnorm(df_clean$CLASIFICACION_DEL_PROYECTO, main="Q-Q Plot: Clasificación",
       col = "darkgreen", pch = 19)
qqline(df_clean$CLASIFICACION_DEL_PROYECTO, col = "red")

qqnorm(df_clean$Clasificacion_Actores_institucionales, 
       main="Q-Q Plot: Actores Institucionales",
       col = "darkblue", pch = 19)
qqline(df_clean$Clasificacion_Actores_institucionales, col = "red")

# Restaurar la configuración original de gráficos
par(mfrow = c(1, 1))

# Resumen estadístico de las pruebas de normalidad
normality_summary <- data.frame(
  Variable = names(variables_to_analyze),
  W_statistic = sapply(names(variables_to_analyze), 
                      function(x) shapiro.test(df_clean[[x]])$statistic),
  p_value = sapply(names(variables_to_analyze), 
                   function(x) shapiro.test(df_clean[[x]])$p.value)
) %>%
  mutate(
    Normalidad = ifelse(p_value < 0.05, "No Normal", "Normal"),
    Variable_Name = unlist(variables_to_analyze)
  )

# Mostrar tabla resumen
kable(normality_summary %>% 
        select(Variable_Name, W_statistic, p_value, Normalidad),
      col.names = c("Variable", "Estadístico W", "Valor p", "Conclusión"),
      caption = "Resumen de Pruebas de Normalidad Shapiro-Wilk") %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Resumen de Pruebas de Normalidad Shapiro-Wilk
Variable Estadístico W Valor p Conclusión
n_proyectos.W Número de Proyectos 0.5501951 0 No Normal
RATIO_ACA_PROYECTO_CULMINADO.W Ratio ACA 0.7444145 0 No Normal
TIPOLOGIA_CFG_NUM.W Tipología CFG 0.8753315 0 No Normal
GOBERNACION_NUM.W Gobernación 0.8601242 0 No Normal
PLAZOS.W Plazos 0.4559052 0 No Normal
CLASIFICACION_DEL_PROYECTO.W Clasificación del Proyecto 0.7444145 0 No Normal
Clasificacion_Actores_institucionales.W Actores Institucionales 0.8346786 0 No Normal

Para cada variable analizada, se plantearon las siguientes hipótesis, siguiendo el procedimiento estándar para una prueba de normalidad:

Hipótesis Nula (H₀): Los datos de la variable siguen una distribución normal.

Hipótesis Alternativa Hₐ: Los datos de la variable no siguen una distribución normal.

En todos los casos analizados, el p-valor obtenido es extremadamente bajo (por ejemplo, < 2.2e-16), lo cual es significativamente inferior a cualquier nivel de significancia estándar (comúnmente α = 0.05). De acuerdo con la regla de decisión, cuando el p-valor es menor que el nivel de significancia, se rechaza la hipótesis nula. Por lo tanto, se rechaza la hipótesis nula de normalidad para todas las variables clave del estudio. Esto confirma que los datos no se distribuyen de manera normal.

Dado que las pruebas de normalidad de Shapiro-Wilk indican de manera concluyente que las variables de la investigación no siguen una distribución normal, no se cumplen los supuestos para la aplicación de pruebas paramétricas. En consecuencia, para analizar la relación entre las variables ordinales de este estudio, se opta por un método no paramétrico. Específicamente, se utilizará el coeficiente de correlación de Spearman (ρ), ya que es la herramienta ideal para cuantificar el grado de asociación entre variables ordinales o cuantitativas que no presentan una distribución normal.

13 4.7 Modelo de Correlación General entre Proyectos Comunitarios y Puntos Críticos

Para guiar el análisis de correlación entre los proyectos comunitarios de las Agendas Concretas de Acción y los nudos críticos en el Estado Mérida, se adoptó un enfoque no paramétrico mediante el coeficiente de correlación de Spearman. Esta decisión metodológica se fundamentó en la ausencia de normalidad detectada en las variables cuantitativas a través de la prueba de Shapiro-Wilk, donde todos los p-valores resultaron menores a 0.001.

El coeficiente de Spearman es particularmente apropiado para este análisis porque no asume distribuciones normales y es robusto ante la presencia de valores atípicos, características presentes en nuestros datos. Este coeficiente mide el grado de asociación monotónica entre dos variables, permitiéndonos identificar tanto relaciones lineales como no lineales.

# ===============================================================================
# MODELO DE CORRELACIÓN DE SPEARMAN PARA PROYECTOS COMUNALES ACA
# ===============================================================================

# 1. Preparación de datos (IGUAL)
top10_cfg <- df_dummies %>% count(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG) %>% arrange(desc(n)) %>% slice(1:10) %>% pull(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG)
top10_gob <- df_dummies %>% count(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION) %>% arrange(desc(n)) %>% slice(1:10) %>% pull(CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION)
cfg_dummy_cols <- paste0("CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_", gsub(" ", "_", top10_cfg))
gob_dummy_cols <- paste0("CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_", gsub(" ", "_", top10_gob))
cfg_dummy_cols <- intersect(cfg_dummy_cols, names(df_dummies))
gob_dummy_cols <- intersect(gob_dummy_cols, names(df_dummies))
vars_resultado <- c("RATIO_ACA_PROYECTO_CULMINADO", "CLASIFICACION_DEL_PROYECTO", "PLAZOS", "Clasificacion_Actores_institucionales")

# 2. CREAR df_cor CORREGIDO (SIN case_when)
df_cor <- df_dummies %>%
  select(all_of(vars_resultado), all_of(cfg_dummy_cols), all_of(gob_dummy_cols))
  # ↑ ELIMINADO el mutate() con case_when porque la variable ya está correcta (1,2,3,4)

# 3. Cálculo de correlaciones de Spearman (IGUAL)
calcular_cor_spearman <- function(data) {
  n_vars <- ncol(data)
  cor_matrix <- matrix(NA, nrow = n_vars, ncol = n_vars)
  p_matrix <- matrix(NA, nrow = n_vars, ncol = n_vars)
  for (i in 1:n_vars) {
    for (j in 1:n_vars) {
      if (i != j) {
        temp <- data[, c(i, j)] %>% na.omit()
        if (nrow(temp) > 10) {
          test <- suppressWarnings(cor.test(temp[[1]], temp[[2]], method = "spearman", exact = FALSE))
          cor_matrix[i, j] <- test$estimate
          p_matrix[i, j] <- test$p.value
        }
      } else {
        cor_matrix[i, j] <- 1
      }
    }
  }
  rownames(cor_matrix) <- colnames(cor_matrix) <- colnames(data)
  rownames(p_matrix) <- colnames(p_matrix) <- colnames(data)
  return(list(cor = cor_matrix, p = p_matrix))
}
set.seed(123)
cor_results <- calcular_cor_spearman(df_cor)

# 4. Procesamiento de resultados y nombres cortos (IGUAL)
acortar_nombres <- function(nombres) {
  nombres <- gsub("CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_", "CFG: ", nombres)
  nombres <- gsub("CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_", "GOB: ", nombres)
  nombres <- gsub("_", " ", nombres)
  substr(nombres, 1, 28)
}
colnames(cor_results$cor) <- rownames(cor_results$cor) <- acortar_nombres(colnames(df_cor))
colnames(cor_results$p) <- rownames(cor_results$p) <- acortar_nombres(colnames(df_cor))

cor_df <- as.data.frame(cor_results$cor) %>%
  tibble::rownames_to_column("Variable1") %>%
  pivot_longer(-Variable1, names_to = "Variable2", values_to = "Correlacion") %>%
  left_join(
    as.data.frame(cor_results$p) %>%
      tibble::rownames_to_column("Variable1") %>%
      pivot_longer(-Variable1, names_to = "Variable2", values_to = "p_valor"),
    by = c("Variable1", "Variable2")
  ) %>%
  filter(!is.na(Correlacion), Variable1 != Variable2) %>%
  mutate(
    Significativa = ifelse(p_valor < 0.05, "Sí", "No"),
    Magnitud = case_when(
      abs(Correlacion) > 0.6 ~ "Muy fuerte",
      abs(Correlacion) > 0.4 ~ "Fuerte",
      abs(Correlacion) > 0.2 ~ "Moderada",
      TRUE ~ "Débil"
    )
  )

# 4. TABLA COMPLETA DE COEFICIENTES DE SPEARMAN
tabla_coef_spearman <- cor_df %>%
  select(Variable1, Variable2, Correlacion, p_valor, Significativa, Magnitud) %>%
  arrange(desc(abs(Correlacion)))

kable(tabla_coef_spearman,
      caption = "Coeficientes de Correlación de Spearman entre variables clave (ACA)",
      col.names = c("Variable 1", "Variable 2", "Rho (ρ)", "p-valor", "Significativa", "Magnitud"),
      align = "l") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(which(tabla_coef_spearman$Significativa == "Sí" & tabla_coef_spearman$Magnitud != "Débil"), bold = TRUE, color = "white", background = "#1b9e77") %>%
  row_spec(which(tabla_coef_spearman$Significativa == "Sí" & tabla_coef_spearman$Magnitud == "Débil"), color = "black", background = "#e6f2e6") %>%
  row_spec(which(tabla_coef_spearman$Significativa == "No"), color = "gray40", background = "#f7f7f7")
Coeficientes de Correlación de Spearman entre variables clave (ACA)
Variable 1 Variable 2 Rho (ρ) p-valor Significativa Magnitud
RATIO ACA PROYECTO CULMINADO CLASIFICACION DEL PROYECTO 1.0000000 0.0000000 Muy fuerte
CLASIFICACION DEL PROYECTO RATIO ACA PROYECTO CULMINADO 1.0000000 0.0000000 Muy fuerte
CFG: ELECTRICIDAD GOB: ELECTRICIDAD 1.0000000 0.0000000 Muy fuerte
CFG: AMBIENTE GOB: CANALIZACION 1.0000000 0.0000000 Muy fuerte
GOB: ELECTRICIDAD CFG: ELECTRICIDAD 1.0000000 0.0000000 Muy fuerte
GOB: CANALIZACION CFG: AMBIENTE 1.0000000 0.0000000 Muy fuerte
CFG: VIVIENDA GOB: VIVIENDA 0.9501193 0.0000000 Muy fuerte
GOB: VIVIENDA CFG: VIVIENDA 0.9501193 0.0000000 Muy fuerte
CFG: TRANSPORTE GOB: TRANSPORTE 0.9329624 0.0000000 Muy fuerte
GOB: TRANSPORTE CFG: TRANSPORTE 0.9329624 0.0000000 Muy fuerte
CFG: VIALIDAD GOB: VIALIDAD 0.7483315 0.0000000 Muy fuerte
GOB: VIALIDAD CFG: VIALIDAD 0.7483315 0.0000000 Muy fuerte
Clasificacion Actores instit CFG: VIVIENDA -0.3677849 0.0000001 Moderada
CFG: VIVIENDA Clasificacion Actores instit -0.3677849 0.0000001 Moderada
Clasificacion Actores instit GOB: VIVIENDA -0.3535836 0.0000003 Moderada
GOB: VIVIENDA Clasificacion Actores instit -0.3535836 0.0000003 Moderada
Clasificacion Actores instit CFG: VIALIDAD 0.1910140 0.0070251 Débil
CFG: VIALIDAD Clasificacion Actores instit 0.1910140 0.0070251 Débil
PLAZOS CFG: INFRAESTRUCTURA -0.1854281 0.0089121 Débil
CFG: INFRAESTRUCTURA PLAZOS -0.1854281 0.0089121 Débil
RATIO ACA PROYECTO CULMINADO GOB: TRANSPORTE 0.1667478 0.0188767 Débil
CLASIFICACION DEL PROYECTO GOB: TRANSPORTE 0.1667478 0.0188767 Débil
GOB: TRANSPORTE RATIO ACA PROYECTO CULMINADO 0.1667478 0.0188767 Débil
GOB: TRANSPORTE CLASIFICACION DEL PROYECTO 0.1667478 0.0188767 Débil
Clasificacion Actores instit CFG: AMBIENTE -0.1552753 0.0289366 Débil
Clasificacion Actores instit GOB: CANALIZACION -0.1552753 0.0289366 Débil
CFG: AMBIENTE Clasificacion Actores instit -0.1552753 0.0289366 Débil
GOB: CANALIZACION Clasificacion Actores instit -0.1552753 0.0289366 Débil
CFG: VIALIDAD GOB: VIVIENDA -0.1531972 0.0311804 Débil
GOB: VIVIENDA CFG: VIALIDAD -0.1531972 0.0311804 Débil
CFG: VIALIDAD CFG: VIVIENDA -0.1455556 0.0407474 Débil
CFG: VIVIENDA CFG: VIALIDAD -0.1455556 0.0407474 Débil
RATIO ACA PROYECTO CULMINADO CFG: TRANSPORTE 0.1394358 0.0500900 No Débil
CLASIFICACION DEL PROYECTO CFG: TRANSPORTE 0.1394358 0.0500900 No Débil
CFG: TRANSPORTE RATIO ACA PROYECTO CULMINADO 0.1394358 0.0500900 No Débil
CFG: TRANSPORTE CLASIFICACION DEL PROYECTO 0.1394358 0.0500900 No Débil
CFG: VIALIDAD CFG: ELECTRICIDAD -0.1376754 0.0530862 No Débil
CFG: VIALIDAD GOB: ELECTRICIDAD -0.1376754 0.0530862 No Débil
CFG: ELECTRICIDAD CFG: VIALIDAD -0.1376754 0.0530862 No Débil
GOB: ELECTRICIDAD CFG: VIALIDAD -0.1376754 0.0530862 No Débil
Clasificacion Actores instit GOB: TRANSPORTE 0.1259022 0.0771572 No Débil
GOB: TRANSPORTE Clasificacion Actores instit 0.1259022 0.0771572 No Débil
CFG: ELECTRICIDAD GOB: VIVIENDA -0.1181123 0.0974648 No Débil
GOB: VIVIENDA CFG: ELECTRICIDAD -0.1181123 0.0974648 No Débil
GOB: VIVIENDA GOB: ELECTRICIDAD -0.1181123 0.0974648 No Débil
GOB: ELECTRICIDAD GOB: VIVIENDA -0.1181123 0.0974648 No Débil
CFG: VIALIDAD CFG: SALUD -0.1165631 0.1019688 No Débil
CFG: SALUD CFG: VIALIDAD -0.1165631 0.1019688 No Débil
GOB: VIVIENDA GOB: VIALIDAD -0.1146423 0.1077797 No Débil
GOB: VIALIDAD GOB: VIVIENDA -0.1146423 0.1077797 No Débil
CFG: VIVIENDA CFG: ELECTRICIDAD -0.1122208 0.1154725 No Débil
CFG: VIVIENDA GOB: ELECTRICIDAD -0.1122208 0.1154725 No Débil
CFG: ELECTRICIDAD CFG: VIVIENDA -0.1122208 0.1154725 No Débil
GOB: ELECTRICIDAD CFG: VIVIENDA -0.1122208 0.1154725 No Débil
CFG: VIALIDAD GOB: DRENAJES -0.1120190 0.1161323 No Débil
GOB: DRENAJES CFG: VIALIDAD -0.1120190 0.1161323 No Débil
RATIO ACA PROYECTO CULMINADO CFG: AMBIENTE -0.1119048 0.1165071 No Débil
RATIO ACA PROYECTO CULMINADO GOB: CANALIZACION -0.1119048 0.1165071 No Débil
CLASIFICACION DEL PROYECTO CFG: AMBIENTE -0.1119048 0.1165071 No Débil
CLASIFICACION DEL PROYECTO GOB: CANALIZACION -0.1119048 0.1165071 No Débil
CFG: AMBIENTE RATIO ACA PROYECTO CULMINADO -0.1119048 0.1165071 No Débil
CFG: AMBIENTE CLASIFICACION DEL PROYECTO -0.1119048 0.1165071 No Débil
GOB: CANALIZACION RATIO ACA PROYECTO CULMINADO -0.1119048 0.1165071 No Débil
GOB: CANALIZACION CLASIFICACION DEL PROYECTO -0.1119048 0.1165071 No Débil
CFG: VIVIENDA GOB: VIALIDAD -0.1089239 0.1266271 No Débil
GOB: VIALIDAD CFG: VIVIENDA -0.1089239 0.1266271 No Débil
CFG: VIALIDAD CFG: INFRAESTRUCTURA -0.1073347 0.1322928 No Débil
CFG: INFRAESTRUCTURA CFG: VIALIDAD -0.1073347 0.1322928 No Débil
Clasificacion Actores instit CFG: SALUD -0.1042387 0.1438877 No Débil
CFG: SALUD Clasificacion Actores instit -0.1042387 0.1438877 No Débil
CFG: INFRAESTRUCTURA GOB: DRENAJES 0.1035873 0.1464227 No Débil
GOB: DRENAJES CFG: INFRAESTRUCTURA 0.1035873 0.1464227 No Débil
PLAZOS GOB: VIVIENDA -0.1035622 0.1465214 No Débil
GOB: VIVIENDA PLAZOS -0.1035622 0.1465214 No Débil
CFG: ELECTRICIDAD GOB: VIALIDAD -0.1030268 0.1486312 No Débil
GOB: ELECTRICIDAD GOB: VIALIDAD -0.1030268 0.1486312 No Débil
GOB: VIALIDAD CFG: ELECTRICIDAD -0.1030268 0.1486312 No Débil
GOB: VIALIDAD GOB: ELECTRICIDAD -0.1030268 0.1486312 No Débil
CFG: SALUD GOB: VIVIENDA -0.1000000 0.1609954 No Débil
GOB: VIVIENDA CFG: SALUD -0.1000000 0.1609954 No Débil
RATIO ACA PROYECTO CULMINADO CFG: TELECOMUNICACIONES -0.0996781 0.1623544 No Débil
CLASIFICACION DEL PROYECTO CFG: TELECOMUNICACIONES -0.0996781 0.1623544 No Débil
CFG: TELECOMUNICACIONES RATIO ACA PROYECTO CULMINADO -0.0996781 0.1623544 No Débil
CFG: TELECOMUNICACIONES CLASIFICACION DEL PROYECTO -0.0996781 0.1623544 No Débil
CFG: VIALIDAD CFG: AMBIENTE -0.0974601 0.1719525 No Débil
CFG: VIALIDAD GOB: CANALIZACION -0.0974601 0.1719525 No Débil
CFG: AMBIENTE CFG: VIALIDAD -0.0974601 0.1719525 No Débil
GOB: CANALIZACION CFG: VIALIDAD -0.0974601 0.1719525 No Débil
GOB: VIVIENDA GOB: DRENAJES -0.0961016 0.1780359 No Débil
GOB: DRENAJES GOB: VIVIENDA -0.0961016 0.1780359 No Débil
CFG: VIVIENDA CFG: SALUD -0.0950119 0.1830293 No Débil
CFG: SALUD CFG: VIVIENDA -0.0950119 0.1830293 No Débil
CFG: VIALIDAD CFG: EDUCACIÓN -0.0922139 0.1963212 No Débil
CFG: EDUCACIÓN CFG: VIALIDAD -0.0922139 0.1963212 No Débil
Clasificacion Actores instit CFG: INFRAESTRUCTURA 0.0915679 0.1994874 No Débil
CFG: INFRAESTRUCTURA Clasificacion Actores instit 0.0915679 0.1994874 No Débil
CFG: VIVIENDA GOB: DRENAJES -0.0913080 0.2007715 No Débil
GOB: DRENAJES CFG: VIVIENDA -0.0913080 0.2007715 No Débil
CFG: ELECTRICIDAD CFG: SALUD -0.0898681 0.2079948 No Débil
CFG: SALUD CFG: ELECTRICIDAD -0.0898681 0.2079948 No Débil
CFG: SALUD GOB: ELECTRICIDAD -0.0898681 0.2079948 No Débil
GOB: ELECTRICIDAD CFG: SALUD -0.0898681 0.2079948 No Débil
CFG: VIVIENDA CFG: INFRAESTRUCTURA -0.0874897 0.2203316 No Débil
CFG: INFRAESTRUCTURA CFG: VIVIENDA -0.0874897 0.2203316 No Débil
Clasificacion Actores instit CFG: ELECTRICIDAD 0.0874440 0.2205739 No Débil
Clasificacion Actores instit GOB: ELECTRICIDAD 0.0874440 0.2205739 No Débil
CFG: ELECTRICIDAD Clasificacion Actores instit 0.0874440 0.2205739 No Débil
GOB: ELECTRICIDAD Clasificacion Actores instit 0.0874440 0.2205739 No Débil
RATIO ACA PROYECTO CULMINADO Clasificacion Actores instit 0.0873689 0.2209722 No Débil
CLASIFICACION DEL PROYECTO Clasificacion Actores instit 0.0873689 0.2209722 No Débil
Clasificacion Actores instit RATIO ACA PROYECTO CULMINADO 0.0873689 0.2209722 No Débil
Clasificacion Actores instit CLASIFICACION DEL PROYECTO 0.0873689 0.2209722 No Débil
CFG: SALUD GOB: VIALIDAD -0.0872278 0.2217214 No Débil
GOB: VIALIDAD CFG: SALUD -0.0872278 0.2217214 No Débil
CFG: ELECTRICIDAD GOB: DRENAJES -0.0863647 0.2263457 No Débil
GOB: ELECTRICIDAD GOB: DRENAJES -0.0863647 0.2263457 No Débil
GOB: DRENAJES CFG: ELECTRICIDAD -0.0863647 0.2263457 No Débil
GOB: DRENAJES GOB: ELECTRICIDAD -0.0863647 0.2263457 No Débil
Clasificacion Actores instit CFG: TRANSPORTE 0.0843585 0.2373560 No Débil
CFG: TRANSPORTE Clasificacion Actores instit 0.0843585 0.2373560 No Débil
GOB: VIALIDAD GOB: DRENAJES -0.0838274 0.2403330 No Débil
GOB: DRENAJES GOB: VIALIDAD -0.0838274 0.2403330 No Débil
CFG: AMBIENTE GOB: VIVIENDA -0.0836115 0.2415503 No Débil
GOB: VIVIENDA CFG: AMBIENTE -0.0836115 0.2415503 No Débil
GOB: VIVIENDA GOB: CANALIZACION -0.0836115 0.2415503 No Débil
GOB: CANALIZACION GOB: VIVIENDA -0.0836115 0.2415503 No Débil
CFG: ELECTRICIDAD CFG: INFRAESTRUCTURA -0.0827531 0.2464333 No Débil
CFG: INFRAESTRUCTURA CFG: ELECTRICIDAD -0.0827531 0.2464333 No Débil
CFG: INFRAESTRUCTURA GOB: ELECTRICIDAD -0.0827531 0.2464333 No Débil
GOB: ELECTRICIDAD CFG: INFRAESTRUCTURA -0.0827531 0.2464333 No Débil
CFG: VIALIDAD CFG: TRANSPORTE -0.0808981 0.2572194 No Débil
CFG: TRANSPORTE CFG: VIALIDAD -0.0808981 0.2572194 No Débil
CFG: INFRAESTRUCTURA GOB: VIALIDAD -0.0803219 0.2606347 No Débil
GOB: VIALIDAD CFG: INFRAESTRUCTURA -0.0803219 0.2606347 No Débil
Clasificacion Actores instit GOB: VIALIDAD 0.0798595 0.2633984 No Débil
GOB: VIALIDAD Clasificacion Actores instit 0.0798595 0.2633984 No Débil
CFG: VIVIENDA CFG: AMBIENTE -0.0794409 0.2659172 No Débil
CFG: VIVIENDA GOB: CANALIZACION -0.0794409 0.2659172 No Débil
CFG: AMBIENTE CFG: VIVIENDA -0.0794409 0.2659172 No Débil
GOB: CANALIZACION CFG: VIVIENDA -0.0794409 0.2659172 No Débil
CFG: EDUCACIÓN GOB: VIVIENDA -0.0791107 0.2679156 No Débil
GOB: VIVIENDA CFG: EDUCACIÓN -0.0791107 0.2679156 No Débil
PLAZOS CFG: VIVIENDA -0.0790295 0.2684088 No Débil
CFG: VIVIENDA PLAZOS -0.0790295 0.2684088 No Débil
CFG: VIVIENDA CFG: EDUCACIÓN -0.0751646 0.2925919 No Débil
CFG: EDUCACIÓN CFG: VIVIENDA -0.0751646 0.2925919 No Débil
CFG: ELECTRICIDAD CFG: AMBIENTE -0.0751400 0.2927502 No Débil
CFG: ELECTRICIDAD GOB: CANALIZACION -0.0751400 0.2927502 No Débil
CFG: AMBIENTE CFG: ELECTRICIDAD -0.0751400 0.2927502 No Débil
CFG: AMBIENTE GOB: ELECTRICIDAD -0.0751400 0.2927502 No Débil
GOB: ELECTRICIDAD CFG: AMBIENTE -0.0751400 0.2927502 No Débil
GOB: ELECTRICIDAD GOB: CANALIZACION -0.0751400 0.2927502 No Débil
GOB: CANALIZACION CFG: ELECTRICIDAD -0.0751400 0.2927502 No Débil
GOB: CANALIZACION GOB: ELECTRICIDAD -0.0751400 0.2927502 No Débil
CFG: VIALIDAD CFG: TELECOMUNICACIONES -0.0747018 0.2955822 No Débil
CFG: TELECOMUNICACIONES CFG: VIALIDAD -0.0747018 0.2955822 No Débil
GOB: VIVIENDA GOB: TRANSPORTE -0.0743897 0.2976098 No Débil
GOB: TRANSPORTE GOB: VIVIENDA -0.0743897 0.2976098 No Débil
CFG: SALUD GOB: DRENAJES -0.0731208 0.3059499 No Débil
GOB: DRENAJES CFG: SALUD -0.0731208 0.3059499 No Débil
CFG: AMBIENTE GOB: VIALIDAD -0.0729325 0.3072004 No Débil
GOB: VIALIDAD CFG: AMBIENTE -0.0729325 0.3072004 No Débil
GOB: VIALIDAD GOB: CANALIZACION -0.0729325 0.3072004 No Débil
GOB: CANALIZACION GOB: VIALIDAD -0.0729325 0.3072004 No Débil
Clasificacion Actores instit CFG: EDUCACIÓN 0.0713166 0.3180701 No Débil
CFG: EDUCACIÓN Clasificacion Actores instit 0.0713166 0.3180701 No Débil
CFG: ELECTRICIDAD CFG: EDUCACIÓN -0.0710953 0.3195782 No Débil
CFG: EDUCACIÓN CFG: ELECTRICIDAD -0.0710953 0.3195782 No Débil
CFG: EDUCACIÓN GOB: ELECTRICIDAD -0.0710953 0.3195782 No Débil
GOB: ELECTRICIDAD CFG: EDUCACIÓN -0.0710953 0.3195782 No Débil
CFG: VIVIENDA GOB: TRANSPORTE -0.0706791 0.3224261 No Débil
GOB: TRANSPORTE CFG: VIVIENDA -0.0706791 0.3224261 No Débil
RATIO ACA PROYECTO CULMINADO CFG: EDUCACIÓN -0.0700818 0.3265424 No Débil
CLASIFICACION DEL PROYECTO CFG: EDUCACIÓN -0.0700818 0.3265424 No Débil
CFG: EDUCACIÓN RATIO ACA PROYECTO CULMINADO -0.0700818 0.3265424 No Débil
CFG: EDUCACIÓN CLASIFICACION DEL PROYECTO -0.0700818 0.3265424 No Débil
CFG: SALUD CFG: INFRAESTRUCTURA -0.0700631 0.3266722 No Débil
CFG: INFRAESTRUCTURA CFG: SALUD -0.0700631 0.3266722 No Débil
CFG: TRANSPORTE GOB: VIVIENDA -0.0694028 0.3312629 No Débil
GOB: VIVIENDA CFG: TRANSPORTE -0.0694028 0.3312629 No Débil
CFG: EDUCACIÓN GOB: VIALIDAD -0.0690066 0.3340380 No Débil
GOB: VIALIDAD CFG: EDUCACIÓN -0.0690066 0.3340380 No Débil
PLAZOS CFG: VIALIDAD 0.0678688 0.3420879 No Débil
CFG: VIALIDAD PLAZOS 0.0678688 0.3420879 No Débil
CFG: ELECTRICIDAD GOB: TRANSPORTE -0.0668526 0.3493807 No Débil
GOB: ELECTRICIDAD GOB: TRANSPORTE -0.0668526 0.3493807 No Débil
GOB: TRANSPORTE CFG: ELECTRICIDAD -0.0668526 0.3493807 No Débil
GOB: TRANSPORTE GOB: ELECTRICIDAD -0.0668526 0.3493807 No Débil
CFG: VIVIENDA CFG: TRANSPORTE -0.0659410 0.3560062 No Débil
CFG: TRANSPORTE CFG: VIVIENDA -0.0659410 0.3560062 No Débil
GOB: VIALIDAD GOB: TRANSPORTE -0.0648886 0.3637516 No Débil
GOB: TRANSPORTE GOB: VIALIDAD -0.0648886 0.3637516 No Débil
CFG: TELECOMUNICACIONES GOB: VIVIENDA -0.0640870 0.3697206 No Débil
GOB: VIVIENDA CFG: TELECOMUNICACIONES -0.0640870 0.3697206 No Débil
CFG: SALUD CFG: AMBIENTE -0.0636174 0.3732451 No Débil
CFG: SALUD GOB: CANALIZACION -0.0636174 0.3732451 No Débil
CFG: AMBIENTE CFG: SALUD -0.0636174 0.3732451 No Débil
GOB: CANALIZACION CFG: SALUD -0.0636174 0.3732451 No Débil
PLAZOS GOB: DRENAJES 0.0625221 0.3815470 No Débil
GOB: DRENAJES PLAZOS 0.0625221 0.3815470 No Débil
CFG: ELECTRICIDAD CFG: TRANSPORTE -0.0623710 0.3827007 No Débil
CFG: TRANSPORTE CFG: ELECTRICIDAD -0.0623710 0.3827007 No Débil
CFG: TRANSPORTE GOB: ELECTRICIDAD -0.0623710 0.3827007 No Débil
GOB: ELECTRICIDAD CFG: TRANSPORTE -0.0623710 0.3827007 No Débil
CFG: AMBIENTE GOB: DRENAJES -0.0611374 0.3922007 No Débil
GOB: DRENAJES CFG: AMBIENTE -0.0611374 0.3922007 No Débil
GOB: DRENAJES GOB: CANALIZACION -0.0611374 0.3922007 No Débil
GOB: CANALIZACION GOB: DRENAJES -0.0611374 0.3922007 No Débil
CFG: VIVIENDA CFG: TELECOMUNICACIONES -0.0608903 0.3941206 No Débil
CFG: TELECOMUNICACIONES CFG: VIVIENDA -0.0608903 0.3941206 No Débil
CFG: TRANSPORTE GOB: VIALIDAD -0.0605386 0.3968628 No Débil
GOB: VIALIDAD CFG: TRANSPORTE -0.0605386 0.3968628 No Débil
CFG: SALUD CFG: EDUCACIÓN -0.0601929 0.3995692 No Débil
CFG: EDUCACIÓN CFG: SALUD -0.0601929 0.3995692 No Débil
PLAZOS CFG: TRANSPORTE -0.0598959 0.4019035 No Débil
CFG: TRANSPORTE PLAZOS -0.0598959 0.4019035 No Débil
RATIO ACA PROYECTO CULMINADO GOB: DRENAJES -0.0597116 0.4033558 No Débil
CLASIFICACION DEL PROYECTO GOB: DRENAJES -0.0597116 0.4033558 No Débil
GOB: DRENAJES RATIO ACA PROYECTO CULMINADO -0.0597116 0.4033558 No Débil
GOB: DRENAJES CLASIFICACION DEL PROYECTO -0.0597116 0.4033558 No Débil
CFG: INFRAESTRUCTURA CFG: AMBIENTE -0.0585808 0.4123358 No Débil
CFG: INFRAESTRUCTURA GOB: CANALIZACION -0.0585808 0.4123358 No Débil
CFG: AMBIENTE CFG: INFRAESTRUCTURA -0.0585808 0.4123358 No Débil
GOB: CANALIZACION CFG: INFRAESTRUCTURA -0.0585808 0.4123358 No Débil
RATIO ACA PROYECTO CULMINADO CFG: SALUD -0.0582558 0.4149379 No Débil
CLASIFICACION DEL PROYECTO CFG: SALUD -0.0582558 0.4149379 No Débil
CFG: SALUD RATIO ACA PROYECTO CULMINADO -0.0582558 0.4149379 No Débil
CFG: SALUD CLASIFICACION DEL PROYECTO -0.0582558 0.4149379 No Débil
CFG: EDUCACIÓN GOB: DRENAJES -0.0578464 0.4182304 No Débil
GOB: DRENAJES CFG: EDUCACIÓN -0.0578464 0.4182304 No Débil
CFG: ELECTRICIDAD CFG: TELECOMUNICACIONES -0.0575937 0.4202695 No Débil
CFG: TELECOMUNICACIONES CFG: ELECTRICIDAD -0.0575937 0.4202695 No Débil
CFG: TELECOMUNICACIONES GOB: ELECTRICIDAD -0.0575937 0.4202695 No Débil
GOB: ELECTRICIDAD CFG: TELECOMUNICACIONES -0.0575937 0.4202695 No Débil
CFG: SALUD GOB: TRANSPORTE -0.0566009 0.4283387 No Débil
GOB: TRANSPORTE CFG: SALUD -0.0566009 0.4283387 No Débil
CFG: TELECOMUNICACIONES GOB: VIALIDAD -0.0559017 0.4340746 No Débil
GOB: VIALIDAD CFG: TELECOMUNICACIONES -0.0559017 0.4340746 No Débil
CFG: INFRAESTRUCTURA CFG: EDUCACIÓN -0.0554274 0.4379906 No Débil
CFG: EDUCACIÓN CFG: INFRAESTRUCTURA -0.0554274 0.4379906 No Débil
GOB: DRENAJES GOB: TRANSPORTE -0.0543944 0.4465888 No Débil
GOB: TRANSPORTE GOB: DRENAJES -0.0543944 0.4465888 No Débil
CFG: SALUD CFG: TRANSPORTE -0.0528065 0.4599893 No Débil
CFG: TRANSPORTE CFG: SALUD -0.0528065 0.4599893 No Débil
CFG: INFRAESTRUCTURA GOB: TRANSPORTE -0.0521198 0.4658535 No Débil
GOB: TRANSPORTE CFG: INFRAESTRUCTURA -0.0521198 0.4658535 No Débil
CFG: TRANSPORTE GOB: DRENAJES -0.0507479 0.4776900 No Débil
GOB: DRENAJES CFG: TRANSPORTE -0.0507479 0.4776900 No Débil
CFG: AMBIENTE CFG: EDUCACIÓN -0.0503282 0.4813437 No Débil
CFG: EDUCACIÓN CFG: AMBIENTE -0.0503282 0.4813437 No Débil
CFG: EDUCACIÓN GOB: CANALIZACION -0.0503282 0.4813437 No Débil
GOB: CANALIZACION CFG: EDUCACIÓN -0.0503282 0.4813437 No Débil
Clasificacion Actores instit CFG: TELECOMUNICACIONES 0.0495198 0.4884237 No Débil
CFG: TELECOMUNICACIONES Clasificacion Actores instit 0.0495198 0.4884237 No Débil
CFG: SALUD CFG: TELECOMUNICACIONES -0.0487618 0.4951115 No Débil
CFG: TELECOMUNICACIONES CFG: SALUD -0.0487618 0.4951115 No Débil
CFG: INFRAESTRUCTURA CFG: TRANSPORTE -0.0486258 0.4963173 No Débil
CFG: TRANSPORTE CFG: INFRAESTRUCTURA -0.0486258 0.4963173 No Débil
CFG: AMBIENTE GOB: TRANSPORTE -0.0473249 0.5079235 No Débil
GOB: CANALIZACION GOB: TRANSPORTE -0.0473249 0.5079235 No Débil
GOB: TRANSPORTE CFG: AMBIENTE -0.0473249 0.5079235 No Débil
GOB: TRANSPORTE GOB: CANALIZACION -0.0473249 0.5079235 No Débil
CFG: TELECOMUNICACIONES GOB: DRENAJES -0.0468609 0.5120964 No Débil
GOB: DRENAJES CFG: TELECOMUNICACIONES -0.0468609 0.5120964 No Débil
PLAZOS GOB: TRANSPORTE -0.0449398 0.5295634 No Débil
GOB: TRANSPORTE PLAZOS -0.0449398 0.5295634 No Débil
CFG: INFRAESTRUCTURA CFG: TELECOMUNICACIONES -0.0449013 0.5299160 No Débil
CFG: TELECOMUNICACIONES CFG: INFRAESTRUCTURA -0.0449013 0.5299160 No Débil
CFG: EDUCACIÓN GOB: TRANSPORTE -0.0447774 0.5310537 No Débil
GOB: TRANSPORTE CFG: EDUCACIÓN -0.0447774 0.5310537 No Débil
RATIO ACA PROYECTO CULMINADO CFG: ELECTRICIDAD -0.0445251 0.5333725 No Débil
RATIO ACA PROYECTO CULMINADO GOB: ELECTRICIDAD -0.0445251 0.5333725 No Débil
CLASIFICACION DEL PROYECTO CFG: ELECTRICIDAD -0.0445251 0.5333725 No Débil
CLASIFICACION DEL PROYECTO GOB: ELECTRICIDAD -0.0445251 0.5333725 No Débil
CFG: ELECTRICIDAD RATIO ACA PROYECTO CULMINADO -0.0445251 0.5333725 No Débil
CFG: ELECTRICIDAD CLASIFICACION DEL PROYECTO -0.0445251 0.5333725 No Débil
GOB: ELECTRICIDAD RATIO ACA PROYECTO CULMINADO -0.0445251 0.5333725 No Débil
GOB: ELECTRICIDAD CLASIFICACION DEL PROYECTO -0.0445251 0.5333725 No Débil
CFG: AMBIENTE CFG: TRANSPORTE -0.0441523 0.5368089 No Débil
CFG: TRANSPORTE CFG: AMBIENTE -0.0441523 0.5368089 No Débil
CFG: TRANSPORTE GOB: CANALIZACION -0.0441523 0.5368089 No Débil
GOB: CANALIZACION CFG: TRANSPORTE -0.0441523 0.5368089 No Débil
RATIO ACA PROYECTO CULMINADO PLAZOS -0.0440255 0.5379799 No Débil
CLASIFICACION DEL PROYECTO PLAZOS -0.0440255 0.5379799 No Débil
PLAZOS RATIO ACA PROYECTO CULMINADO -0.0440255 0.5379799 No Débil
PLAZOS CLASIFICACION DEL PROYECTO -0.0440255 0.5379799 No Débil
CFG: EDUCACIÓN CFG: TRANSPORTE -0.0417756 0.5589727 No Débil
CFG: TRANSPORTE CFG: EDUCACIÓN -0.0417756 0.5589727 No Débil
CFG: AMBIENTE CFG: TELECOMUNICACIONES -0.0407705 0.5684765 No Débil
CFG: TELECOMUNICACIONES CFG: AMBIENTE -0.0407705 0.5684765 No Débil
CFG: TELECOMUNICACIONES GOB: CANALIZACION -0.0407705 0.5684765 No Débil
GOB: CANALIZACION CFG: TELECOMUNICACIONES -0.0407705 0.5684765 No Débil
CFG: INFRAESTRUCTURA GOB: VIVIENDA 0.0400360 0.5754693 No Débil
GOB: VIVIENDA CFG: INFRAESTRUCTURA 0.0400360 0.5754693 No Débil
CFG: EDUCACIÓN CFG: TELECOMUNICACIONES -0.0385758 0.5894907 No Débil
CFG: TELECOMUNICACIONES CFG: EDUCACIÓN -0.0385758 0.5894907 No Débil
PLAZOS GOB: VIALIDAD 0.0384760 0.5904548 No Débil
GOB: VIALIDAD PLAZOS 0.0384760 0.5904548 No Débil
CFG: TELECOMUNICACIONES GOB: TRANSPORTE -0.0362738 0.6119071 No Débil
GOB: TRANSPORTE CFG: TELECOMUNICACIONES -0.0362738 0.6119071 No Débil
RATIO ACA PROYECTO CULMINADO CFG: VIALIDAD 0.0360418 0.6141871 No Débil
CLASIFICACION DEL PROYECTO CFG: VIALIDAD 0.0360418 0.6141871 No Débil
CFG: VIALIDAD RATIO ACA PROYECTO CULMINADO 0.0360418 0.6141871 No Débil
CFG: VIALIDAD CLASIFICACION DEL PROYECTO 0.0360418 0.6141871 No Débil
RATIO ACA PROYECTO CULMINADO GOB: VIALIDAD -0.0359616 0.6149759 No Débil
CLASIFICACION DEL PROYECTO GOB: VIALIDAD -0.0359616 0.6149759 No Débil
GOB: VIALIDAD RATIO ACA PROYECTO CULMINADO -0.0359616 0.6149759 No Débil
GOB: VIALIDAD CLASIFICACION DEL PROYECTO -0.0359616 0.6149759 No Débil
PLAZOS CFG: SALUD -0.0345207 0.6292250 No Débil
CFG: SALUD PLAZOS -0.0345207 0.6292250 No Débil
CFG: TRANSPORTE CFG: TELECOMUNICACIONES -0.0338421 0.6359841 No Débil
CFG: TELECOMUNICACIONES CFG: TRANSPORTE -0.0338421 0.6359841 No Débil
PLAZOS CFG: EDUCACIÓN 0.0318612 0.6558854 No Débil
CFG: EDUCACIÓN PLAZOS 0.0318612 0.6558854 No Débil
PLAZOS CFG: AMBIENTE -0.0202043 0.7775383 No Débil
PLAZOS GOB: CANALIZACION -0.0202043 0.7775383 No Débil
CFG: AMBIENTE PLAZOS -0.0202043 0.7775383 No Débil
GOB: CANALIZACION PLAZOS -0.0202043 0.7775383 No Débil
PLAZOS Clasificacion Actores instit 0.0190980 0.7894263 No Débil
Clasificacion Actores instit PLAZOS 0.0190980 0.7894263 No Débil
RATIO ACA PROYECTO CULMINADO CFG: VIVIENDA -0.0188082 0.7925488 No Débil
CLASIFICACION DEL PROYECTO CFG: VIVIENDA -0.0188082 0.7925488 No Débil
CFG: VIVIENDA RATIO ACA PROYECTO CULMINADO -0.0188082 0.7925488 No Débil
CFG: VIVIENDA CLASIFICACION DEL PROYECTO -0.0188082 0.7925488 No Débil
RATIO ACA PROYECTO CULMINADO CFG: INFRAESTRUCTURA 0.0172508 0.8093836 No Débil
CLASIFICACION DEL PROYECTO CFG: INFRAESTRUCTURA 0.0172508 0.8093836 No Débil
CFG: INFRAESTRUCTURA RATIO ACA PROYECTO CULMINADO 0.0172508 0.8093836 No Débil
CFG: INFRAESTRUCTURA CLASIFICACION DEL PROYECTO 0.0172508 0.8093836 No Débil
CFG: VIALIDAD GOB: TRANSPORTE -0.0151744 0.8319640 No Débil
GOB: TRANSPORTE CFG: VIALIDAD -0.0151744 0.8319640 No Débil
Clasificacion Actores instit GOB: DRENAJES 0.0126575 0.8595192 No Débil
GOB: DRENAJES Clasificacion Actores instit 0.0126575 0.8595192 No Débil
RATIO ACA PROYECTO CULMINADO GOB: VIVIENDA 0.0115018 0.8722311 No Débil
CLASIFICACION DEL PROYECTO GOB: VIVIENDA 0.0115018 0.8722311 No Débil
GOB: VIVIENDA RATIO ACA PROYECTO CULMINADO 0.0115018 0.8722311 No Débil
GOB: VIVIENDA CLASIFICACION DEL PROYECTO 0.0115018 0.8722311 No Débil
PLAZOS CFG: ELECTRICIDAD 0.0075109 0.9163604 No Débil
PLAZOS GOB: ELECTRICIDAD 0.0075109 0.9163604 No Débil
CFG: ELECTRICIDAD PLAZOS 0.0075109 0.9163604 No Débil
GOB: ELECTRICIDAD PLAZOS 0.0075109 0.9163604 No Débil
PLAZOS CFG: TELECOMUNICACIONES 0.0000000 1.0000000 No Débil
CFG: TELECOMUNICACIONES PLAZOS 0.0000000 1.0000000 No Débil
#-----------------------------Visualización alternativa: Heatmap de correlaciones-------------------
ggplot(tabla_coef_spearman %>% filter(Magnitud != "Débil"), 
       aes(x = Variable1, y = Variable2, fill = Correlacion)) +
  geom_tile(color = "white") +
  geom_text(aes(label = sprintf("%.2f", Correlacion)), color = "black", size = 3) +
  scale_fill_gradient2(
    low = "#d7191c", mid = "#ffffbf", high = "#2c7bb6", midpoint = 0, limits = c(-1, 1)
  ) +
  labs(
    title = "Correlaciones Moderadas y Fuertes (Spearman)",
    subtitle = "Entre tipologías, gobernaciones y resultados de proyectos",
    x = "", y = ""
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "right")

# ===============================================================================
# ANÁLISIS COMPLETO DE CORRELACIONES DE SPEARMAN - PROYECTOS ACA
# FLUJO DE TRABAJO INTEGRADO PARA MONOGRAFÍA
# ===============================================================================
# ===============================================================================
# 1. HEATMAP ACADÉMICO - MATRIZ DE CORRELACIONES SIGNIFICATIVAS
# ===============================================================================

crear_heatmap_correlaciones <- function(cor_results, titulo = "Matriz de Correlación de Spearman - Proyectos ACA") {
  
  # Sincronizar matrices
  vars_comunes <- intersect(rownames(cor_results$cor), rownames(cor_results$p))
  cor_matrix <- cor_results$cor[vars_comunes, vars_comunes]
  p_matrix <- cor_results$p[vars_comunes, vars_comunes]
  
  # **CORRECCIÓN: Usar reshape2::melt explícitamente para matrices**
  cor_long <- reshape2::melt(cor_matrix, varnames = c("Variable1", "Variable2"), value.name = "Correlacion")
  p_long <- reshape2::melt(p_matrix, varnames = c("Variable1", "Variable2"), value.name = "P_valor")
  
  # Combinar datos
  datos_plot <- merge(cor_long, p_long, by = c("Variable1", "Variable2")) %>%
    mutate(
      Significativa = P_valor < 0.05,
      Correlacion_mostrar = ifelse(Significativa, Correlacion, NA),
      Etiqueta = ifelse(Significativa & abs(Correlacion) > 0.3, 
                       sprintf("%.2f", Correlacion), ""),
      Asterisco = case_when(
        P_valor < 0.001 ~ "***",
        P_valor < 0.01 ~ "**",
        P_valor < 0.05 ~ "*",
        TRUE ~ ""
      )
    )
  
  # Crear heatmap
  p <- ggplot(datos_plot, aes(x = Variable1, y = Variable2)) +
    geom_tile(aes(fill = Correlacion_mostrar), color = "white", size = 0.3) +
    geom_text(aes(label = Etiqueta), size = 2.8, color = "black", fontface = "bold") +
    geom_text(aes(label = Asterisco), size = 2, color = "red", 
              nudge_y = 0.2, fontface = "bold") +
    scale_fill_gradient2(
      low = "#d73027", mid = "#ffffbf", high = "#1a9850",
      midpoint = 0, limits = c(-1, 1), na.value = "grey95",
      name = "ρ",
      breaks = c(-1, -0.5, 0, 0.5, 1)
    ) +
    labs(
      title = titulo,
      subtitle = "Solo correlaciones significativas | *** p<0.001, ** p<0.01, * p<0.05",
      x = "", y = "",
      caption = paste("n =", sum(datos_plot$Significativa, na.rm = TRUE), "correlaciones significativas")
    ) +
    theme_minimal() +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
      axis.text.y = element_text(size = 10),
      plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
      plot.subtitle = element_text(hjust = 0.5, size = 11),
      panel.grid = element_blank(),
      legend.position = "right"
    ) +
    coord_equal()
  
  return(p)
}

# ===============================================================================
# 2. EVALUACIÓN DE HIPÓTESIS ESPECÍFICAS
# ===============================================================================

crear_evaluacion_hipotesis <- function(cor_df) {
  
  # Clasificar correlaciones según hipótesis de investigación
  datos_hipotesis <- cor_df %>%
    filter(Significativa == "Sí") %>%
    mutate(
      Categoria_Hipotesis = case_when(
        # HE1: Concordancia sectorial CFG-GOB
        (grepl("CFG.*ELECTRICIDAD", Variable1) & grepl("GOB.*ELECTRICIDAD", Variable2)) |
        (grepl("CFG.*VIVIENDA", Variable1) & grepl("GOB.*VIVIENDA", Variable2)) |
        (grepl("CFG.*TRANSPORTE", Variable1) & grepl("GOB.*TRANSPORTE", Variable2)) |
        (grepl("CFG.*VIALIDAD", Variable1) & grepl("GOB.*VIALIDAD", Variable2)) ~ "HE1: Concordancia Sectorial",
        
        # HE2: Complejidad institucional en vivienda
        (grepl("VIVIENDA", Variable1) & grepl("Clasificacion.*Actores", Variable2)) |
        (grepl("Clasificacion.*Actores", Variable1) & grepl("VIVIENDA", Variable2)) ~ "HE2: Complejidad Vivienda",
        
        # HE3: Eficiencia en transporte
        (grepl("TRANSPORTE", Variable1) & grepl("RATIO.*PROYECTO", Variable2)) |
        (grepl("RATIO.*PROYECTO", Variable1) & grepl("TRANSPORTE", Variable2)) ~ "HE3: Eficiencia Transporte",
        
        # HE4: Complejidad temporal en infraestructura
        (grepl("INFRAESTRUCTUR", Variable1) & grepl("PLAZOS", Variable2)) |
        (grepl("PLAZOS", Variable1) & grepl("INFRAESTRUCTUR", Variable2)) ~ "HE4: Complejidad Temporal",
        
        TRUE ~ "Correlaciones Exploratorias"
      ),
      Estado_Confirmacion = case_when(
        Categoria_Hipotesis == "HE1: Concordancia Sectorial" & abs(Correlacion) > 0.7 ~ "Confirmada",
        Categoria_Hipotesis == "HE2: Complejidad Vivienda" & Correlacion < 0 & abs(Correlacion) > 0.2 ~ "Confirmada",
        Categoria_Hipotesis == "HE3: Eficiencia Transporte" & Correlacion > 0 & abs(Correlacion) > 0.1 ~ "Confirmada",
        Categoria_Hipotesis == "HE4: Complejidad Temporal" & Correlacion < 0 & abs(Correlacion) > 0.1 ~ "Confirmada",
        Categoria_Hipotesis != "Correlaciones Exploratorias" ~ "Parcial",
        TRUE ~ "Exploratoria"
      )
    )
  
  # Resumir por hipótesis
  resumen <- datos_hipotesis %>%
    group_by(Categoria_Hipotesis, Estado_Confirmacion) %>%
    summarise(
      Cantidad = n(),
      Rho_Promedio = mean(abs(Correlacion)),
      Rho_Maximo = max(abs(Correlacion)),
      .groups = "drop"
    ) %>%
    arrange(desc(Rho_Promedio))
  
  # Crear gráfico de barras horizontales
  p <- ggplot(resumen, aes(x = reorder(Categoria_Hipotesis, Rho_Promedio), 
                          y = Rho_Promedio, fill = Estado_Confirmacion)) +
    geom_col(alpha = 0.8, color = "black", size = 0.3) +
    geom_text(aes(label = paste0("n=", Cantidad, "\nρmax=", round(Rho_Maximo, 2))),
              hjust = -0.1, size = 3.5, fontface = "bold") +
    scale_fill_manual(
      values = c("Confirmada" = "#27ae60", "Parcial" = "#f39c12", "Exploratoria" = "#2c3e50"),
      name = "Estado de Hipótesis"
    ) +
    coord_flip() +
    labs(
      title = "Evaluación Empírica de Hipótesis de Investigación",
      subtitle = "Fuerza promedio de correlaciones y estado de confirmación por hipótesis",
      x = "Hipótesis Específicas",
      y = "Correlación Promedio |ρ|",
      caption = "n = número de correlaciones detectadas, ρmax = correlación máxima observada"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(face = "bold", size = 14),
      axis.text.y = element_text(size = 11),
      legend.position = "bottom"
    ) +
    scale_y_continuous(limits = c(0, 1.1), breaks = seq(0, 1, 0.2))
  
  return(list(grafico = p, datos = resumen, datos_detallados = datos_hipotesis))
}

# ===============================================================================
# 3. ANÁLISIS DE VARIABLES CENTRALES - RED DE INFLUENCIA
# ===============================================================================

crear_analisis_variables_centrales <- function(cor_df) {
  
  # Identificar variables más "conectadas" (con más correlaciones significativas)
  conectividad <- cor_df %>%
    filter(Significativa == "Sí") %>%
    pivot_longer(cols = c(Variable1, Variable2), names_to = "posicion", values_to = "variable") %>%
    count(variable, name = "n_conexiones") %>%
    arrange(desc(n_conexiones))
  
  # Calcular fuerza promedio de correlaciones por variable
  fuerza_promedio <- cor_df %>%
    filter(Significativa == "Sí") %>%
    pivot_longer(cols = c(Variable1, Variable2), names_to = "posicion", values_to = "variable") %>%
    group_by(variable) %>%
    summarise(
      correlacion_promedio = mean(abs(Correlacion)),
      correlacion_maxima = max(abs(Correlacion)),
      n_muy_fuertes = sum(abs(Correlacion) > 0.7),
      n_fuertes = sum(abs(Correlacion) > 0.5),
      .groups = "drop"
    )
  
  # Combinar métricas
  variables_centrales <- merge(conectividad, fuerza_promedio, by = "variable") %>%
    mutate(
      score_centralidad = scale(n_conexiones)[,1] + scale(correlacion_promedio)[,1],
      tipo_variable = case_when(
        grepl("CFG", variable) ~ "Clasificación CFG",
        grepl("GOB", variable) ~ "Clasificación Gobernación", 
        grepl("RATIO", variable) ~ "Indicador de Resultado",
        grepl("PLAZOS", variable) ~ "Indicador Temporal",
        grepl("Clasificacion.*Actores", variable) ~ "Indicador Institucional",
        TRUE ~ "Otra"
      )
    ) %>%
    arrange(desc(score_centralidad))
  
  # Crear gráfico de variables centrales
  p <- ggplot(head(variables_centrales, 15), 
              aes(x = reorder(variable, score_centralidad), y = score_centralidad)) +
    geom_col(aes(fill = tipo_variable), alpha = 0.8, color = "black", size = 0.3) +
    geom_text(aes(label = paste0("Conexiones: ", n_conexiones, 
                                "\nρ̄=", round(correlacion_promedio, 2))),
              hjust = -0.1, size = 3, fontface = "bold") +
    scale_fill_viridis_d(name = "Tipo de Variable", option = "plasma") +
    coord_flip() +
    labs(
      title = "Variables Centrales en la Red de Correlaciones",
      subtitle = "Top 15 variables por centralidad (conectividad + fuerza promedio)",
      x = "Variables",
      y = "Score de Centralidad (estandarizado)",
      caption = "ρ̄ = correlación promedio, Conexiones = número de correlaciones significativas"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(face = "bold", size = 14),
      axis.text.y = element_text(size = 10),
      legend.position = "bottom"
    )
  
  return(list(grafico = p, datos = variables_centrales))
}

# ===============================================================================
# 4. ANÁLISIS SECTORIAL COMPARATIVO
# ===============================================================================

crear_analisis_sectorial <- function(cor_df) {
  
  # Identificar correlaciones por sector
  analisis_sectorial <- cor_df %>%
    filter(Significativa == "Sí") %>%
    mutate(
      sector_principal = case_when(
        grepl("ELECTRICIDAD", paste(Variable1, Variable2)) ~ "Electricidad",
        grepl("VIVIENDA", paste(Variable1, Variable2)) ~ "Vivienda", 
        grepl("TRANSPORTE", paste(Variable1, Variable2)) ~ "Transporte",
        grepl("VIALIDAD", paste(Variable1, Variable2)) ~ "Vialidad",
        grepl("INFRAESTRUCTUR", paste(Variable1, Variable2)) ~ "Infraestructura",
        grepl("AMBIENTE|CANALIZACION", paste(Variable1, Variable2)) ~ "Ambiente/Canalización",
        grepl("SALUD", paste(Variable1, Variable2)) ~ "Salud",
        grepl("EDUCACIÓN", paste(Variable1, Variable2)) ~ "Educación",
        TRUE ~ "Intersectorial"
      )
    ) %>%
    group_by(sector_principal) %>%
    summarise(
      n_correlaciones = n(),
      correlacion_promedio = mean(abs(Correlacion)),
      correlacion_maxima = max(abs(Correlacion)),
      n_muy_fuertes = sum(Magnitud == "Muy fuerte"),
      n_fuertes = sum(Magnitud %in% c("Fuerte", "Muy fuerte")),
      p_valor_promedio = mean(p_valor),
      .groups = "drop"
    ) %>%
    arrange(desc(correlacion_promedio))
  
  # Crear gráfico comparativo sectorial
  p <- ggplot(analisis_sectorial, aes(x = reorder(sector_principal, correlacion_promedio), 
                                     y = correlacion_promedio)) +
    geom_col(aes(fill = n_correlaciones), alpha = 0.8, color = "black", size = 0.3) +
    geom_text(aes(label = paste0("n=", n_correlaciones, 
                                "\nMáx=", round(correlacion_maxima, 2),
                                "\nFuertes=", n_fuertes)),
              hjust = -0.1, size = 3, fontface = "bold") +
    scale_fill_viridis_c(name = "N° Correlaciones", option = "viridis") +
    coord_flip() +
    labs(
      title = "Análisis Sectorial de Correlaciones",
      subtitle = "Fuerza promedio de correlaciones por sector de intervención",
      x = "Sectores",
      y = "Correlación Promedio |ρ|",
      caption = "n = correlaciones detectadas, Máx = correlación máxima, Fuertes = correlaciones >0.5"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(face = "bold", size = 14),
      axis.text.y = element_text(size = 11),
      legend.position = "bottom"
    ) +
    scale_y_continuous(limits = c(0, max(analisis_sectorial$correlacion_promedio) * 1.2))
  
  return(list(grafico = p, datos = analisis_sectorial))
}

# ===============================================================================
# 5. TABLA RESUMEN EJECUTIVA
# ===============================================================================

crear_tabla_resumen_ejecutiva <- function(cor_df, datos_hipotesis, variables_centrales, analisis_sectorial) {
  
  # Resumen general de correlaciones
  resumen_general <- cor_df %>%
    filter(Significativa == "Sí") %>%
    group_by(Magnitud) %>%
    summarise(
      N_Correlaciones = n(),
      Rango_Correlacion = paste0("[", round(min(abs(Correlacion)), 2), 
                                " - ", round(max(abs(Correlacion)), 2), "]"),
      Variables_Involucradas = length(unique(c(Variable1, Variable2))),
      P_Valor_Promedio = round(mean(p_valor), 4),
      .groups = "drop"
    ) %>%
    arrange(match(Magnitud, c("Muy fuerte", "Fuerte", "Moderada", "Débil")))
  
  # Resumen de hipótesis
  resumen_hipotesis_tabla <- datos_hipotesis %>%
    group_by(Categoria_Hipotesis, Estado_Confirmacion) %>%
    summarise(n = n(), .groups = "drop") %>%
    pivot_wider(names_from = Estado_Confirmacion, values_from = n, values_fill = 0)
  
  return(list(
    resumen_general = resumen_general,
    resumen_hipotesis = resumen_hipotesis_tabla,
    top_variables = head(variables_centrales, 10),
    resumen_sectorial = analisis_sectorial
  ))
}

# ===============================================================================
# FUNCIÓN PRINCIPAL - FLUJO DE TRABAJO COMPLETO
# ===============================================================================

ejecutar_analisis_completo_correlaciones <- function(cor_results, cor_df) {
  
  cat("===============================================================================\n")
  cat("INICIANDO ANÁLISIS COMPLETO DE CORRELACIONES DE SPEARMAN - PROYECTOS ACA\n")
  cat("===============================================================================\n")
  
  # Verificar datos de entrada
  if (!exists("cor_results") || !exists("cor_df")) {
    stop("ERROR: Faltan objetos 'cor_results' y/o 'cor_df'. Ejecuta primero el análisis de correlación.")
  }
  
  cat("Datos verificados correctamente.\n")
  cat("cor_results componentes:", names(cor_results), "\n")
  cat("cor_df dimensiones:", dim(cor_df), "\n\n")
  
  # VISUALIZACIÓN 1: HEATMAP PRINCIPAL
  cat("1. CREANDO HEATMAP DE CORRELACIONES SIGNIFICATIVAS...\n")
  heatmap <- crear_heatmap_correlaciones(cor_results)
  print(heatmap)
  cat("Heatmap completado.\n\n")
  
  # VISUALIZACIÓN 2: EVALUACIÓN DE HIPÓTESIS
  cat("2. EVALUANDO HIPÓTESIS DE INVESTIGACIÓN...\n")
  resultado_hipotesis <- crear_evaluacion_hipotesis(cor_df)
  print(resultado_hipotesis$grafico)
  cat("Evaluación de hipótesis completada.\n\n")
  
  # VISUALIZACIÓN 3: ANÁLISIS DE VARIABLES CENTRALES
  cat("3. ANALIZANDO VARIABLES CENTRALES...\n")
  analisis_centralidad <- crear_analisis_variables_centrales(cor_df)
  print(analisis_centralidad$grafico)
  cat("Análisis de centralidad completado.\n\n")
  
  # VISUALIZACIÓN 4: ANÁLISIS SECTORIAL
  cat("4. REALIZANDO ANÁLISIS SECTORIAL...\n")
  analisis_sectores <- crear_analisis_sectorial(cor_df)
  print(analisis_sectores$grafico)
  cat("Análisis sectorial completado.\n\n")
  
  # GENERAR TABLAS RESUMEN
  cat("5. GENERANDO TABLAS RESUMEN...\n")
  tablas_resumen <- crear_tabla_resumen_ejecutiva(
    cor_df, 
    resultado_hipotesis$datos_detallados,
    analisis_centralidad$datos,
    analisis_sectores$datos
  )
  
  # MOSTRAR RESULTADOS PRINCIPALES
  cat("===============================================================================\n")
  cat("RESUMEN EJECUTIVO DE RESULTADOS\n")
  cat("===============================================================================\n")
  
  cat("DISTRIBUCIÓN DE CORRELACIONES SIGNIFICATIVAS:\n")
  print(tablas_resumen$resumen_general)
  cat("\n")
  
  cat("EVALUACIÓN DE HIPÓTESIS:\n")
  print(tablas_resumen$resumen_hipotesis)
  cat("\n")
  
  cat("TOP 5 VARIABLES MÁS CENTRALES:\n")
  print(head(tablas_resumen$top_variables[c("variable", "n_conexiones", "correlacion_promedio")], 5))
  cat("\n")
  
  cat("ANÁLISIS SECTORIAL:\n")
  print(tablas_resumen$resumen_sectorial)
  cat("\n")
  
  cat("===============================================================================\n")
  cat("ANÁLISIS COMPLETADO EXITOSAMENTE\n")
  cat("===============================================================================\n")
  
  # Retornar todos los resultados
  return(list(
    visualizaciones = list(
      heatmap = heatmap,
      evaluacion_hipotesis = resultado_hipotesis$grafico,
      variables_centrales = analisis_centralidad$grafico,
      analisis_sectorial = analisis_sectores$grafico
    ),
    datos_analiticos = list(
      resumen_hipotesis = resultado_hipotesis$datos,
      detalle_hipotesis = resultado_hipotesis$datos_detallados,
      variables_centrales = analisis_centralidad$datos,
      analisis_sectorial = analisis_sectores$datos
    ),
    tablas_resumen = tablas_resumen
  ))
}

# ===============================================================================
#  FUNCIÓN PARA CREAR DATOS DE TABLAS RESUMEN DINAMICAS
# ===============================================================================

# 1. Distribución de correlaciones
distribucion_cor <- data.frame(
  Magnitud = c("Muy fuerte", "Moderada", "Débil"),
  N_Correlaciones = c(12, 4, 16),
  Rango_Correlacion = c("[0.75 - 1]", "[0.35 - 0.37]", "[0.15 - 0.19]"),
  Variables_Involucradas = c(12, 3, 11),
  P_Valor_Promedio = c(0.000, 0.002, 0.048)
)

# 2. Evaluación de hipótesis
evaluacion_hipotesis <- data.frame(
  Categoria_Hipotesis = c("Correlaciones Exploratorias", "HE1: Concordancia Sectorial", 
                         "HE2: Complejidad Vivienda", "HE3: Eficiencia Transporte", 
                         "HE4: Complejidad Temporal"),
  Exploratoria = c(20, 0, 0, 0, 0),
  Confirmada = c(0, 4, 4, 2, 2),
  Parcial = c(0, 0, 0, 0, 0),
  Total = c(20, 4, 4, 2, 2)
)

# 3. Variables más centrales
variables_centrales <- data.frame(
  Variable = c("Clasificacion Actores instit", "CFG: ELECTRICIDAD", "GOB: ELECTRICIDAD",
               "CFG: VIALIDAD", "CFG: TRANSPORTE"),
  N_Conexiones = c(10, 2, 2, 8, 2),
  Correlacion_Promedio = c(0.245, 1.000, 1.000, 0.310, 0.933),
  Correlacion_Maxima = c(0.245, 1.000, 1.000, 0.310, 0.933)
)

# 4. Análisis sectorial
analisis_sectorial <- data.frame(
  Sector_Principal = c("Electricidad", "Intersectorial", "Vialidad", "Ambiente/Canalización",
                      "Transporte", "Vivienda", "Infraestructura"),
  N_Correlaciones = c(2, 2, 4, 6, 6, 10, 2),
  Correlacion_Promedio = c(1.000, 1.000, 0.470, 0.437, 0.422, 0.394, 0.185),
  Correlacion_Maxima = c(1.000, 1.000, 0.748, 1.000, 0.933, 0.950, 0.185),
  Correlaciones_Fuertes = c(2, 2, 0, 6, 2, 4, 0)
)

#=============================Crear las tablas kable=======================================#

# Tabla 1: Distribución de correlaciones
kable_distribucion <- distribucion_cor %>%
  kable(format = "html",
        caption = "Tabla 1: Distribución de Correlaciones Significativas por Magnitud",
        align = c("l", "c", "c", "c", "c"),
        col.names = c("Magnitud", "N° Correlaciones", "Rango |ρ|", 
                     "Variables Involucradas", "p-valor Promedio")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 13,
                position = "center") %>%
  row_spec(0, bold = TRUE, background = "#64B5F6", color = "white", font_size = 14) %>%
  row_spec(1, bold = TRUE, background = "#E57373", color = "white") %>%  # Muy fuerte en rojo claro
  row_spec(2, bold = TRUE, background = "#81C784", color = "white") %>%  # Moderada en verde claro
  row_spec(3, bold = TRUE, background = "#FFF176", color = "black") %>%  # Débil en amarillo claro
  column_spec(1, bold = TRUE, width = "15%") %>%
  column_spec(2:5, width = "15%") %>%
  footnote(general = "Clasificación: Muy fuerte (|ρ| > 0.7), Moderada (0.3-0.5), Débil (|ρ| < 0.3)",
           general_title = "Nota: ")

# Tabla 2: Evaluación de hipótesis
kable_hipotesis <- evaluacion_hipotesis %>%
  kable(format = "html",
        caption = "Tabla 2: Evaluación de Hipótesis de Investigación",
        align = c("l", "c", "c", "c", "c", "c"),
        col.names = c("Hipótesis", "Exploratoria", "Confirmada", 
                     "Parcial", "Total")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 13,
                position = "center") %>%
  row_spec(0, bold = TRUE, background = "#42A5F5", color = "white", font_size = 14) %>%
  row_spec(1, bold = TRUE, background = "#E3F2FD", color = "black") %>%  # Exploratorias
  row_spec(2:5, background = "#E8F5E8") %>%  # Confirmadas
  row_spec(2, background = "#C8E6C9") %>%  # HE1
  row_spec(3, background = "#A5D6A7") %>%  # HE2
  row_spec(4, background = "#81C784") %>%  # HE3
  row_spec(5, background = "#66BB6A") %>%  # HE4
  column_spec(1, bold = TRUE, width = "35%") %>%
  column_spec(2:5, width = "10%") %>%
  footnote(general = "Hipótesis confirmadas cuando cumplen criterios estadísticos y teóricos predefinidos",
           general_title = "Nota: ")

# Tabla 3: Variables más centrales
kable_centrales <- variables_centrales %>%
  select(Variable = Variable, 
         Conexiones = N_Conexiones, 
         `ρ Promedio` = Correlacion_Promedio, 
         `ρ Máximo` = Correlacion_Maxima) %>%
  kable(format = "html",
        caption = "Tabla 3: Top 5 Variables Más Centrales en la Red de Correlaciones",
        align = c("l", "c", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 13,
                position = "center") %>%
  row_spec(0, bold = TRUE, background = "#AB47BC", color = "white", font_size = 14) %>%
  row_spec(1, bold = TRUE, background = "#F3E5F5", color = "black") %>%  # Top 1
  row_spec(2:3, background = "#F8BBD9") %>%  # Top 2-3
  row_spec(4:5, background = "#FCE4EC") %>%  # Top 4-5
  column_spec(1, bold = TRUE, width = "35%") %>%
  column_spec(2:4, width = "15%") %>%
  footnote(general = "Centralidad basada en número de conexiones significativas y fuerza promedio de correlaciones",
           general_title = "Nota: ")

# Tabla 4: Análisis sectorial
kable_sectorial <- analisis_sectorial %>%
  select(Sector = Sector_Principal, 
         `N° Correlaciones` = N_Correlaciones,
         `ρ Promedio` = Correlacion_Promedio,
         `ρ Máximo` = Correlacion_Maxima,
         `Correlaciones Fuertes` = Correlaciones_Fuertes) %>%
  kable(format = "html",
        caption = "Tabla 4: Análisis Sectorial de Correlaciones Significativas",
        align = c("l", "c", "c", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 13,
                position = "center") %>%
  row_spec(0, bold = TRUE, background = "#4DB6AC", color = "white", font_size = 14) %>%
  row_spec(1:2, bold = TRUE, background = "#B2DFDB", color = "black") %>%  # Electricidad e Intersectorial (ρ=1.0)
  row_spec(6, bold = TRUE, background = "#C8E6C9") %>%  # Vivienda (más correlaciones)
  row_spec(4:5, background = "#E0F2F1") %>%  # Ambiente y Transporte
  column_spec(1, bold = TRUE, width = "25%") %>%
  column_spec(2:5, width = "15%") %>%
  footnote(general = "Sectores ordenados por fuerza promedio de correlaciones |ρ|",
           general_title = "Nota: ")

# Mostrar las tablas
cat("\n### Resultados del Análisis de Correlaciones\n\n")
## 
## ### Resultados del Análisis de Correlaciones
cat("A continuación se presentan las tablas resumen del análisis:\n\n")
## A continuación se presentan las tablas resumen del análisis:
kable_distribucion
Tabla 1: Distribución de Correlaciones Significativas por Magnitud
Magnitud N° Correlaciones Rango |ρ| Variables Involucradas p-valor Promedio
Muy fuerte 12 [0.75 - 1] 12 0.000
Moderada 4 [0.35 - 0.37] 3 0.002
Débil 16 [0.15 - 0.19] 11 0.048
Nota:
Clasificación: Muy fuerte (|ρ| > 0.7), Moderada (0.3-0.5), Débil (|ρ| < 0.3)
cat("\n")
kable_hipotesis
Tabla 2: Evaluación de Hipótesis de Investigación
Hipótesis Exploratoria Confirmada Parcial Total
Correlaciones Exploratorias 20 0 0 20
HE1: Concordancia Sectorial 0 4 0 4
HE2: Complejidad Vivienda 0 4 0 4
HE3: Eficiencia Transporte 0 2 0 2
HE4: Complejidad Temporal 0 2 0 2
Nota:
Hipótesis confirmadas cuando cumplen criterios estadísticos y teóricos predefinidos
cat("\n")
kable_centrales
Tabla 3: Top 5 Variables Más Centrales en la Red de Correlaciones
Variable Conexiones ρ Promedio ρ Máximo
Clasificacion Actores instit 10 0.245 0.245
CFG: ELECTRICIDAD 2 1.000 1.000
GOB: ELECTRICIDAD 2 1.000 1.000
CFG: VIALIDAD 8 0.310 0.310
CFG: TRANSPORTE 2 0.933 0.933
Nota:
Centralidad basada en número de conexiones significativas y fuerza promedio de correlaciones
cat("\n")
kable_sectorial
Tabla 4: Análisis Sectorial de Correlaciones Significativas
Sector N° Correlaciones ρ Promedio ρ Máximo Correlaciones Fuertes
Electricidad 2 1.000 1.000 2
Intersectorial 2 1.000 1.000 2
Vialidad 4 0.470 0.748 0
Ambiente/Canalización 6 0.437 1.000 6
Transporte 6 0.422 0.933 2
Vivienda 10 0.394 0.950 4
Infraestructura 2 0.185 0.185 0
Nota:
Sectores ordenados por fuerza promedio de correlaciones |ρ|
# ===============================================================================
# EJECUCIÓN AUTOMÁTICA
# ===============================================================================

# Ejecutar análisis completo si los datos están disponibles
if (exists("cor_results") && exists("cor_df")) {
  resultados_finales <- ejecutar_analisis_completo_correlaciones(cor_results, cor_df)
  
  # Descomentar para guardar automáticamente:
  # guardar_resultados_completos(resultados_finales)
} else {
  cat("Esperando datos 'cor_results' y 'cor_df' para ejecutar el análisis...\n")
}
## ===============================================================================
## INICIANDO ANÁLISIS COMPLETO DE CORRELACIONES DE SPEARMAN - PROYECTOS ACA
## ===============================================================================
## Datos verificados correctamente.
## cor_results componentes: cor p 
## cor_df dimensiones: 342 6 
## 
## 1. CREANDO HEATMAP DE CORRELACIONES SIGNIFICATIVAS...

## Heatmap completado.
## 
## 2. EVALUANDO HIPÓTESIS DE INVESTIGACIÓN...

## Evaluación de hipótesis completada.
## 
## 3. ANALIZANDO VARIABLES CENTRALES...

## Análisis de centralidad completado.
## 
## 4. REALIZANDO ANÁLISIS SECTORIAL...

## Análisis sectorial completado.
## 
## 5. GENERANDO TABLAS RESUMEN...
## ===============================================================================
## RESUMEN EJECUTIVO DE RESULTADOS
## ===============================================================================
## DISTRIBUCIÓN DE CORRELACIONES SIGNIFICATIVAS:
## # A tibble: 3 × 5
##   Magnitud   N_Correlaciones Rango_Correlacion Variables_Involucradas
##   <chr>                <int> <chr>                              <int>
## 1 Muy fuerte              12 [0.75 - 1]                            12
## 2 Moderada                 4 [0.35 - 0.37]                          3
## 3 Débil                   16 [0.15 - 0.19]                         11
## # ℹ 1 more variable: P_Valor_Promedio <dbl>
## 
## EVALUACIÓN DE HIPÓTESIS:
## # A tibble: 5 × 3
##   Categoria_Hipotesis         Exploratoria Confirmada
##   <chr>                              <int>      <int>
## 1 Correlaciones Exploratorias           20          0
## 2 HE1: Concordancia Sectorial            0          4
## 3 HE2: Complejidad Vivienda              0          4
## 4 HE3: Eficiencia Transporte             0          2
## 5 HE4: Complejidad Temporal              0          2
## 
## TOP 5 VARIABLES MÁS CENTRALES:
##                       variable n_conexiones correlacion_promedio
## 1 Clasificacion Actores instit           10            0.2445866
## 2            CFG: ELECTRICIDAD            2            1.0000000
## 3            GOB: ELECTRICIDAD            2            1.0000000
## 4                CFG: VIALIDAD            8            0.3095246
## 5              CFG: TRANSPORTE            2            0.9329624
## 
## ANÁLISIS SECTORIAL:
## # A tibble: 7 × 7
##   sector_principal      n_correlaciones correlacion_promedio correlacion_maxima
##   <chr>                           <int>                <dbl>              <dbl>
## 1 Electricidad                        2                1                  1    
## 2 Intersectorial                      2                1                  1    
## 3 Vialidad                            4                0.470              0.748
## 4 Ambiente/Canalización               6                0.437              1    
## 5 Transporte                          6                0.422              0.933
## 6 Vivienda                           10                0.394              0.950
## 7 Infraestructura                     2                0.185              0.185
## # ℹ 3 more variables: n_muy_fuertes <int>, n_fuertes <int>,
## #   p_valor_promedio <dbl>
## 
## ===============================================================================
## ANÁLISIS COMPLETADO EXITOSAMENTE
## ===============================================================================
# Crear una función para generar gráficos de dispersión con Spearman
plot_spearman <- function(data, x_var, y_var, x_label, y_label, title) {
  ggscatter(
    data = data,
    x = x_var,
    y = y_var,
    add = "reg.line", # Añadir línea de regresión
    conf.int = TRUE, # Añadir intervalo de confianza
    cor.coef = TRUE, # Mostrar coeficiente
    cor.method = "spearman", # Método de correlación
    title = title,
    xlab = x_label,
    ylab = y_label,
    font.x = 10,
    font.y = 10,
    cor.coeff.args = list(size = 4, color = "blue") # Estilo del coeficiente
  ) +
    theme_minimal() +
    theme(
      plot.title = element_text(hjust = 0.5, face = "bold"),
      axis.title = element_text(face = "bold")
    )
}


# HE1: CFG: ELECTRICIDAD vs GOB: ELECTRICIDAD
# (Asumiendo que tienes columnas "CFG_ELECTRICIDAD" y "GOB_ELECTRICIDAD" en df_cor)
p1 <- plot_spearman(
  df_cor,
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_ELECTRICIDAD",
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_ELECTRICIDAD",
  "CFG: ELECTRICIDAD",
  "GOB: ELECTRICIDAD",
  "HE1: Correlación Perfecta entre Diagnóstico y Gestión en Electricidad (ρ = 1.0)"
)

# HE2: CFG: VIVIENDA vs GOB: VIVIENDA
p2 <- plot_spearman(
  df_cor,
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_VIVIENDA",
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_VIVIENDA",
  "CFG: VIVIENDA",
  "GOB: VIVIENDA",
  "HE2: Alta Correlación en Vivienda (ρ = 0.95)"
)

# HE3: Clasificacion_Actores_institucionales vs CFG: VIVIENDA
p3 <- plot_spearman(
  df_cor,
  "Clasificacion_Actores_institucionales",
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_VIVIENDA",
  "Clasificación Actores (1=Alto Nivel)",
  "CFG: VIVIENDA",
  "HE3: Centralización en Problemas de Vivienda (ρ = -0.368)"
)

# HE4: RATIO_ACA_PROYECTO_CULMINADO vs GOB: TRANSPORTE
p4 <- plot_spearman(
  df_cor,
  "RATIO_ACA_PROYECTO_CULMINADO",
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_TRANSPORTE",
  "Ratio ACA (Efectividad)",
  "GOB: TRANSPORTE",
  "HE4: Efectividad Leve en Proyectos de Transporte (ρ = 0.167)"
)

# HE5: PLAZOS vs CFG: INFRAESTRUCTURA
p5 <- plot_spearman(
  df_cor,
  "PLAZOS",
  "CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_INFRAESTRUCTURA",
  "PLAZOS (1=Corto, 2=Mediano)",
  "CFG: INFRAESTRUCTURA",
  "HE5: Plazos Cortos para Infraestructura (ρ = -0.185)"
)

# Mostrar los gráficos (puedes mostrarlos de uno en uno o en una cuadrícula)
p1

p2

p3

p4

p5

# Opcional: Mostrarlos en una cuadrícula de 2x3 (dejando un espacio vacío)

ggarrange(p1, p2, p3, p4, p5, ncol = 2, nrow = 3)

###-----------------------------------------Hipótesis de la investigación---------------------------

# Crear la tabla de hipótesis
tabla_hipotesis <- data.frame(
  Hipótesis = c(
    "**Hipótesis General (HG)**",
    "Existe una relación estadísticamente significativa entre la tipología de los nudos críticos identificados (CFG), la clasificación de los actores institucionales (Gobernación) y la efectividad en la ejecución de los proyectos (RATIO ACA) en las comunas del Estado Mérida durante el período 2018-2025.",
    "",
    "**HE1:** Existe una correlación positiva muy fuerte y significativa entre la identificación de nudos críticos relacionados con ELECTRICIDAD(CFG) y la participación de la Gobernación en el área de ELECTRICIDAD(GOB) en los proyectos ACA.",
    "**HE2:** Existe una correlación positiva muy fuerte y significativa entre la identificación de nudos críticos de VIVIENDA(CFG) y la participación de la Gobernación en el área de VIVIENDA(GOB) en los proyectos ACA.",
    "**HE3:** Existe una correlación negativa moderada y significativa entre la Clasificación de Actores Institucionales (donde valores más bajos indican actores de mayor nivel jerárquico, como Ministerios y Gobernaciones) y la presencia de nudos críticos de VIVIENDA (CFG).",
    "**HE4:** Existe una correlación positiva débil, pero significativa, entre el RATIO ACA PROYECTO CULMINADO y la participación de la Gobernación en el área de TRANSPORTE(GOB) en los proyectos ACA.",
    "**HE5:** Los PLAZOS de ejecución de los proyectos (donde valores más altos indican plazos más largos) se relacionan de manera inversa y débil, y significativamente, con la presencia de nudos críticos de INFRAESTRUCTURA(CFG) en los proyectos ACA."
  ),
  stringsAsFactors = FALSE
)

# Mostrar la tabla
kable(tabla_hipotesis, col.names = NULL, caption = "Tabla de Hipótesis 3: Hipótesis de Investigación sobre la Correlación entre Proyectos ACA y Nudos Críticos", format = "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE) %>%
  column_spec(1, width = "100%")
Tabla de Hipótesis 3: Hipótesis de Investigación sobre la Correlación entre Proyectos ACA y Nudos Críticos
Hipótesis General (HG)
Existe una relación estadísticamente significativa entre la tipología de los nudos críticos identificados (CFG), la clasificación de los actores institucionales (Gobernación) y la efectividad en la ejecución de los proyectos (RATIO ACA) en las comunas del Estado Mérida durante el período 2018-2025.
HE1: Existe una correlación positiva muy fuerte y significativa entre la identificación de nudos críticos relacionados con ELECTRICIDAD(CFG) y la participación de la Gobernación en el área de ELECTRICIDAD(GOB) en los proyectos ACA.
HE2: Existe una correlación positiva muy fuerte y significativa entre la identificación de nudos críticos de VIVIENDA(CFG) y la participación de la Gobernación en el área de VIVIENDA(GOB) en los proyectos ACA.
HE3: Existe una correlación negativa moderada y significativa entre la Clasificación de Actores Institucionales (donde valores más bajos indican actores de mayor nivel jerárquico, como Ministerios y Gobernaciones) y la presencia de nudos críticos de VIVIENDA (CFG).
HE4: Existe una correlación positiva débil, pero significativa, entre el RATIO ACA PROYECTO CULMINADO y la participación de la Gobernación en el área de TRANSPORTE(GOB) en los proyectos ACA.
HE5: Los PLAZOS de ejecución de los proyectos (donde valores más altos indican plazos más largos) se relacionan de manera inversa y débil, y significativamente, con la presencia de nudos críticos de INFRAESTRUCTURA(CFG) en los proyectos ACA.
#---------------------------------Datos de verificación de hipótesis--------------------------------
verificacion <- data.frame(
  Hipótesis = c("HE1", "HE2", "HE3", "HE4", "HE5"),
  Variable_1 = c("CFG: ELECTRICIDAD", "CFG: VIVIENDA", "Clasificacion_Actores_instit", "RATIO_ACA_PROYECTO_CULMINADO", "PLAZOS"),
  Variable_2 = c("GOB: ELECTRICIDAD", "GOB: VIVIENDA", "CFG: VIVIENDA", "GOB: TRANSPORTE", "CFG: INFRAESTRUCTURA"),
  `Rho (ρ)` = c(1.000, 0.950, -0.368, 0.167, -0.185),
  `p-valor` = c(0.0000000, 0.0000000, 0.0000001, 0.0189, 0.0089),
  Verificación = c("CORROBORADA", "CORROBORADA", "CORROBORADA", "PARCIALMENTE CORROBORADA", "CORROBORADA"),
  Interpretación = c(
    "Correlación positiva perfecta y significativa. Alineación absoluta entre diagnóstico y gestión.",
    "Correlación positiva muy fuerte y significativa. Alta efectividad en el mapeo y asignación.",
    "Correlación negativa moderada y significativa. Problemas de vivienda gestionados por actores de alto nivel.",
    "Correlación positiva débil pero significativa. Relación mínima entre culminación y proyectos de transporte.",
    "Correlación negativa débil pero significativa. Proyectos de infraestructura tienden a tener plazos más cortos."
  ),
  stringsAsFactors = FALSE
)

# Mostrar tabla de verificación
kable(verificacion, caption = "Tabla X.1: Verificación de Hipótesis Específicas", booktabs = TRUE, align = "c") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  column_spec(1:3, width = "8em") %>%
  column_spec(4:5, width = "6em") %>%
  column_spec(6, width = "10em") %>%
  column_spec(7, width = "20em") %>%
  row_spec(which(verificacion$Verificación == "CORROBORADA"), bold = TRUE, background = "#e6f2e6") %>%
  row_spec(which(verificacion$Verificación == "PARCIALMENTE CORROBORADA"), bold = TRUE, background = "#fff3cd")
Tabla X.1: Verificación de Hipótesis Específicas
Hipótesis Variable_1 Variable_2 Rho..ρ. p.valor Verificación Interpretación
HE1 CFG: ELECTRICIDAD GOB: ELECTRICIDAD 1.000 0.00e+00 CORROBORADA Correlación positiva perfecta y significativa. Alineación absoluta entre diagnóstico y gestión.
HE2 CFG: VIVIENDA GOB: VIVIENDA 0.950 0.00e+00 CORROBORADA Correlación positiva muy fuerte y significativa. Alta efectividad en el mapeo y asignación.
HE3 Clasificacion_Actores_instit CFG: VIVIENDA -0.368 1.00e-07 CORROBORADA Correlación negativa moderada y significativa. Problemas de vivienda gestionados por actores de alto nivel.
HE4 RATIO_ACA_PROYECTO_CULMINADO GOB: TRANSPORTE 0.167 1.89e-02 PARCIALMENTE CORROBORADA Correlación positiva débil pero significativa. Relación mínima entre culminación y proyectos de transporte.
HE5 PLAZOS CFG: INFRAESTRUCTURA -0.185 8.90e-03 CORROBORADA Correlación negativa débil pero significativa. Proyectos de infraestructura tienden a tener plazos más cortos.
##-------------------------------**Hallazgos adicionales clave**-----------------------------------
hallazgos <- data.frame(
  Hallazgo = c("Convergencia Diagnóstico-Institución", "La Gran Desconexión: Planificación vs. Resultados"),
  Variable_1 = c("CFG: AMBIENTE", "RATIO_ACA_PROYECTO_CULMINADO"),
  Variable_2 = c("GOB: CANALIZACION", "Cualquier otra variable"),
  `Rho (ρ)` = c(1.000, "No hay correlaciones fuertes/moderadas"),
  `p-valor` = c(0.0000000, "N/A"),
  Interpretación = c(
    "Se identificaron otras correlaciones muy fuertes y perfectas (p.ej., CFG: AMBIENTE & GOB: CANALIZACION, ρ=1.0). Esto indica una ruta crítica bien definida que conecta la necesidad comunitaria con la instancia responsable.",
    "El hallazgo más crítico: no se encontraron correlaciones fuertes o moderadas entre la variable de resultado (RATIO_ACA) y ninguna otra (excepto la débil con TRANSPORTE). Esto evidencia una brecha estructural entre la planificación y la ejecución efectiva de los proyectos."
  ),
  stringsAsFactors = FALSE
)

kable(hallazgos, caption = "Tabla X.2: Hallazgos Adicionales Clave", booktabs = TRUE, align = "c") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  column_spec(1, width = "20em") %>%
  column_spec(2:3, width = "10em") %>%
  column_spec(4:5, width = "6em") %>%
  column_spec(6, width = "30em")
Tabla X.2: Hallazgos Adicionales Clave
Hallazgo Variable_1 Variable_2 Rho..ρ. p.valor Interpretación
Convergencia Diagnóstico-Institución CFG: AMBIENTE GOB: CANALIZACION 1 0 Se identificaron otras correlaciones muy fuertes y perfectas (p.ej., CFG: AMBIENTE & GOB: CANALIZACION, ρ=1.0). Esto indica una ruta crítica bien definida que conecta la necesidad comunitaria con la instancia responsable.
La Gran Desconexión: Planificación vs. Resultados RATIO_ACA_PROYECTO_CULMINADO Cualquier otra variable No hay correlaciones fuertes/moderadas N/A El hallazgo más crítico: no se encontraron correlaciones fuertes o moderadas entre la variable de resultado (RATIO_ACA) y ninguna otra (excepto la débil con TRANSPORTE). Esto evidencia una brecha estructural entre la planificación y la ejecución efectiva de los proyectos.
#---------------------------**Tablas para el anexo de la monografía**-------------------------------

# Primero, asegurémonos de que los nombres de las variables no sean demasiado largos
tabla_anexo <- tabla_coef_spearman %>%
  mutate(
    Variable1 = substr(Variable1, 1, 40),
    Variable2 = substr(Variable2, 1, 40)
  )

# Dividir la tabla en partes manejables (por ejemplo, por significancia y magnitud) para evitar páginas interminables
# Parte 1: Correlaciones Significativas y Muy Fuertes/Fuertes
parte1 <- tabla_anexo %>%
  filter(Significativa == "Sí" & Magnitud %in% c("Muy fuerte", "Fuerte")) %>%
  arrange(desc(abs(Correlacion)))

# Parte 2: Correlaciones Significativas y Moderadas
parte2 <- tabla_anexo %>%
  filter(Significativa == "Sí" & Magnitud == "Moderada") %>%
  arrange(desc(abs(Correlacion)))

# Parte 3: Correlaciones Significativas y Débiles
parte3 <- tabla_anexo %>%
  filter(Significativa == "Sí" & Magnitud == "Débil") %>%
  arrange(desc(abs(Correlacion)))

# Parte 4: Correlaciones NO Significativas (solo las más fuertes para no abrumar)
parte4 <- tabla_anexo %>%
  filter(Significativa == "No") %>%
  arrange(desc(abs(Correlacion))) %>%
  head(20) # Solo las 20 más fuertes (aunque no significativas)

cat("### Parte 1: Correlaciones Significativas (p < 0.05) - Muy Fuertes y Fuertes\n")
## ### Parte 1: Correlaciones Significativas (p < 0.05) - Muy Fuertes y Fuertes
kable(parte1, format = "html", caption = "Anexo X.1: Correlaciones Significativas - Muy Fuertes y Fuertes") %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
Anexo X.1: Correlaciones Significativas - Muy Fuertes y Fuertes
Variable1 Variable2 Correlacion p_valor Significativa Magnitud
RATIO ACA PROYECTO CULMINADO CLASIFICACION DEL PROYECTO 1.0000000 0 Muy fuerte
CLASIFICACION DEL PROYECTO RATIO ACA PROYECTO CULMINADO 1.0000000 0 Muy fuerte
CFG: ELECTRICIDAD GOB: ELECTRICIDAD 1.0000000 0 Muy fuerte
CFG: AMBIENTE GOB: CANALIZACION 1.0000000 0 Muy fuerte
GOB: ELECTRICIDAD CFG: ELECTRICIDAD 1.0000000 0 Muy fuerte
GOB: CANALIZACION CFG: AMBIENTE 1.0000000 0 Muy fuerte
CFG: VIVIENDA GOB: VIVIENDA 0.9501193 0 Muy fuerte
GOB: VIVIENDA CFG: VIVIENDA 0.9501193 0 Muy fuerte
CFG: TRANSPORTE GOB: TRANSPORTE 0.9329624 0 Muy fuerte
GOB: TRANSPORTE CFG: TRANSPORTE 0.9329624 0 Muy fuerte
CFG: VIALIDAD GOB: VIALIDAD 0.7483315 0 Muy fuerte
GOB: VIALIDAD CFG: VIALIDAD 0.7483315 0 Muy fuerte
cat("\n\n### Parte 2: Correlaciones Significativas (p < 0.05) - Moderadas\n")
## 
## 
## ### Parte 2: Correlaciones Significativas (p < 0.05) - Moderadas
kable(parte2, format = "html", caption = "Anexo X.2: Correlaciones Significativas - Moderadas") %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
Anexo X.2: Correlaciones Significativas - Moderadas
Variable1 Variable2 Correlacion p_valor Significativa Magnitud
Clasificacion Actores instit CFG: VIVIENDA -0.3677849 1e-07 Moderada
CFG: VIVIENDA Clasificacion Actores instit -0.3677849 1e-07 Moderada
Clasificacion Actores instit GOB: VIVIENDA -0.3535836 3e-07 Moderada
GOB: VIVIENDA Clasificacion Actores instit -0.3535836 3e-07 Moderada
cat("\n\n### Parte 3: Correlaciones Significativas (p < 0.05) - Débiles\n")
## 
## 
## ### Parte 3: Correlaciones Significativas (p < 0.05) - Débiles
kable(parte3, format = "html", caption = "Anexo X.3: Correlaciones Significativas - Débiles") %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
Anexo X.3: Correlaciones Significativas - Débiles
Variable1 Variable2 Correlacion p_valor Significativa Magnitud
Clasificacion Actores instit CFG: VIALIDAD 0.1910140 0.0070251 Débil
CFG: VIALIDAD Clasificacion Actores instit 0.1910140 0.0070251 Débil
PLAZOS CFG: INFRAESTRUCTURA -0.1854281 0.0089121 Débil
CFG: INFRAESTRUCTURA PLAZOS -0.1854281 0.0089121 Débil
RATIO ACA PROYECTO CULMINADO GOB: TRANSPORTE 0.1667478 0.0188767 Débil
CLASIFICACION DEL PROYECTO GOB: TRANSPORTE 0.1667478 0.0188767 Débil
GOB: TRANSPORTE RATIO ACA PROYECTO CULMINADO 0.1667478 0.0188767 Débil
GOB: TRANSPORTE CLASIFICACION DEL PROYECTO 0.1667478 0.0188767 Débil
Clasificacion Actores instit CFG: AMBIENTE -0.1552753 0.0289366 Débil
Clasificacion Actores instit GOB: CANALIZACION -0.1552753 0.0289366 Débil
CFG: AMBIENTE Clasificacion Actores instit -0.1552753 0.0289366 Débil
GOB: CANALIZACION Clasificacion Actores instit -0.1552753 0.0289366 Débil
CFG: VIALIDAD GOB: VIVIENDA -0.1531972 0.0311804 Débil
GOB: VIVIENDA CFG: VIALIDAD -0.1531972 0.0311804 Débil
CFG: VIALIDAD CFG: VIVIENDA -0.1455556 0.0407474 Débil
CFG: VIVIENDA CFG: VIALIDAD -0.1455556 0.0407474 Débil
cat("\n\n### Parte 4: Correlaciones NO Significativas (p > 0.05) - Top 20 por Magnitud\n")
## 
## 
## ### Parte 4: Correlaciones NO Significativas (p > 0.05) - Top 20 por Magnitud
kable(parte4, format = "html", caption = "Anexo X.4: Correlaciones NO Significativas - Top 20") %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "400px")
Anexo X.4: Correlaciones NO Significativas - Top 20
Variable1 Variable2 Correlacion p_valor Significativa Magnitud
RATIO ACA PROYECTO CULMINADO CFG: TRANSPORTE 0.1394358 0.0500900 No Débil
CLASIFICACION DEL PROYECTO CFG: TRANSPORTE 0.1394358 0.0500900 No Débil
CFG: TRANSPORTE RATIO ACA PROYECTO CULMINADO 0.1394358 0.0500900 No Débil
CFG: TRANSPORTE CLASIFICACION DEL PROYECTO 0.1394358 0.0500900 No Débil
CFG: VIALIDAD CFG: ELECTRICIDAD -0.1376754 0.0530862 No Débil
CFG: VIALIDAD GOB: ELECTRICIDAD -0.1376754 0.0530862 No Débil
CFG: ELECTRICIDAD CFG: VIALIDAD -0.1376754 0.0530862 No Débil
GOB: ELECTRICIDAD CFG: VIALIDAD -0.1376754 0.0530862 No Débil
Clasificacion Actores instit GOB: TRANSPORTE 0.1259022 0.0771572 No Débil
GOB: TRANSPORTE Clasificacion Actores instit 0.1259022 0.0771572 No Débil
CFG: ELECTRICIDAD GOB: VIVIENDA -0.1181123 0.0974648 No Débil
GOB: VIVIENDA CFG: ELECTRICIDAD -0.1181123 0.0974648 No Débil
GOB: VIVIENDA GOB: ELECTRICIDAD -0.1181123 0.0974648 No Débil
GOB: ELECTRICIDAD GOB: VIVIENDA -0.1181123 0.0974648 No Débil
CFG: VIALIDAD CFG: SALUD -0.1165631 0.1019688 No Débil
CFG: SALUD CFG: VIALIDAD -0.1165631 0.1019688 No Débil
GOB: VIVIENDA GOB: VIALIDAD -0.1146423 0.1077797 No Débil
GOB: VIALIDAD GOB: VIVIENDA -0.1146423 0.1077797 No Débil
CFG: VIVIENDA CFG: ELECTRICIDAD -0.1122208 0.1154725 No Débil
CFG: VIVIENDA GOB: ELECTRICIDAD -0.1122208 0.1154725 No Débil

##Modelo de Correlación General

Para guiar el análisis de correlación entre los proyectos comunitarios de las Agendas Concretas de Acción y los nudos críticos en el Estado Mérida, se adoptó un enfoque no paramétrico mediante el coeficiente de correlación de Spearman. Esta decisión metodológica se fundamentó en la ausencia de normalidad detectada en las variables cuantitativas a través de la prueba de Shapiro-Wilk, donde todos los p-valores resultaron menores a 0.001.

El coeficiente de Spearman es particularmente apropiado para este análisis porque no asume distribuciones normales y es robusto ante la presencia de valores atípicos, características presentes en nuestros datos. Este coeficiente mide el grado de asociación monotónica entre dos variables, permitiéndonos identificar tanto relaciones lineales como no lineales.

# Crear tabla de hipótesis con estructura clara
hipotesis_general <- data.frame(
  Hipótesis = c(
    "**Hipótesis General (HG)**",
    "Existe una relación estadísticamente significativa entre la tipología de los nudos críticos identificados (CFG), la clasificación de los actores institucionales (Gobernación) y la efectividad en la ejecución de los proyectos (RATIO ACA) en las comunas del Estado Mérida durante el período 2018-2025.",
    "",
    "**HE1: Concordancia Sectorial en Electricidad**",
    "Existe una correlación positiva muy fuerte y significativa (ρ ≥ 0.90) entre la identificación de nudos críticos relacionados con ELECTRICIDAD (CFG) y la participación de la Gobernación en el área de ELECTRICIDAD (GOB) en los proyectos ACA.",
    "",
    "**HE2: Concordancia Sectorial en Vivienda**",
    "Existe una correlación positiva muy fuerte y significativa (ρ ≥ 0.90) entre la identificación de nudos críticos de VIVIENDA (CFG) y la participación de la Gobernación en el área de VIVIENDA (GOB) en los proyectos ACA.",
    "",
    "**HE3: Centralización Institucional**",
    "Existe una correlación negativa moderada y significativa (-0.60 < ρ < -0.20) entre la Clasificación de Actores Institucionales (donde valores más bajos indican actores de mayor nivel jerárquico) y la presencia de nudos críticos de VIVIENDA (CFG).",
    "",
    "**HE4: Eficiencia en Transporte**",
    "Existe una correlación positiva débil pero significativa (0.10 < ρ < 0.40) entre el RATIO ACA PROYECTO CULMINADO y la participación de la Gobernación en el área de TRANSPORTE (GOB).",
    "",
    "**HE5: Complejidad Temporal en Infraestructura**",
    "Los PLAZOS de ejecución de los proyectos se relacionan de manera inversa y débil (-0.40 < ρ < -0.10) con la presencia de nudos críticos de INFRAESTRUCTURA (CFG)."
  ),
  stringsAsFactors = FALSE
)

# Crear tabla estilizada
kable(hipotesis_general, 
      col.names = NULL,
      caption = "Hipótesis de Investigación sobre Correlación entre Proyectos ACA y Nudos Críticos") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = TRUE,
                font_size = 16) %>%
  column_spec(1, width = "100%") %>%
  row_spec(c(1, 4, 7, 10, 13, 16), bold = TRUE, background = "#e8f4f8", color = "#2c3e50")
Hipótesis de Investigación sobre Correlación entre Proyectos ACA y Nudos Críticos
Hipótesis General (HG)
Existe una relación estadísticamente significativa entre la tipología de los nudos críticos identificados (CFG), la clasificación de los actores institucionales (Gobernación) y la efectividad en la ejecución de los proyectos (RATIO ACA) en las comunas del Estado Mérida durante el período 2018-2025.
HE1: Concordancia Sectorial en Electricidad
Existe una correlación positiva muy fuerte y significativa (ρ ≥ 0.90) entre la identificación de nudos críticos relacionados con ELECTRICIDAD (CFG) y la participación de la Gobernación en el área de ELECTRICIDAD (GOB) en los proyectos ACA.
HE2: Concordancia Sectorial en Vivienda
Existe una correlación positiva muy fuerte y significativa (ρ ≥ 0.90) entre la identificación de nudos críticos de VIVIENDA (CFG) y la participación de la Gobernación en el área de VIVIENDA (GOB) en los proyectos ACA.
HE3: Centralización Institucional
Existe una correlación negativa moderada y significativa (-0.60 < ρ < -0.20) entre la Clasificación de Actores Institucionales (donde valores más bajos indican actores de mayor nivel jerárquico) y la presencia de nudos críticos de VIVIENDA (CFG).
HE4: Eficiencia en Transporte
Existe una correlación positiva débil pero significativa (0.10 < ρ < 0.40) entre el RATIO ACA PROYECTO CULMINADO y la participación de la Gobernación en el área de TRANSPORTE (GOB).
HE5: Complejidad Temporal en Infraestructura
Los PLAZOS de ejecución de los proyectos se relacionan de manera inversa y débil (-0.40 < ρ < -0.10) con la presencia de nudos críticos de INFRAESTRUCTURA (CFG).

Nota metodológica: Las hipótesis fueron formuladas siguiendo el marco conceptual de Castillo y Tello (2022), estableciendo rangos específicos de magnitud esperada para cada relación. El nivel de significancia se fijó en α = 0.05, consistente con estándares de investigación en ciencias sociales.

##Matriz de Correlaciones Interactiva

# ===============================================================================
# MATRIZ DE CORRELACIONES INTERACTIVA - VERSIÓN CORREGIDA
# ===============================================================================

# Preparar datos para visualización interactiva - USANDO reshape2::melt
cor_matrix_melted <- reshape2::melt(cor_results$cor)
p_matrix_melted <- reshape2::melt(cor_results$p)
colnames(cor_matrix_melted) <- c("Var1", "Var2", "Correlacion")
colnames(p_matrix_melted) <- c("Var1", "Var2", "P_valor")

heatmap_data <- cor_matrix_melted %>%
  left_join(p_matrix_melted, by = c("Var1", "Var2")) %>%
  mutate(
    Significativa = case_when(
      P_valor < 0.001 ~ "***",
      P_valor < 0.01 ~ "**", 
      P_valor < 0.05 ~ "*",
      TRUE ~ "ns"
    ),
    Magnitud = case_when(
      abs(Correlacion) >= 0.80 ~ "Muy fuerte",
      abs(Correlacion) >= 0.60 ~ "Fuerte",
      abs(Correlacion) >= 0.40 ~ "Moderada",
      abs(Correlacion) >= 0.20 ~ "Débil",
      TRUE ~ "Despreciable"
    ),
    Texto_Hover = paste0(
      "<b>", Var1, "</b> ↔ <b>", Var2, "</b><br>",
      "ρ (Spearman): <b>", round(Correlacion, 3), "</b><br>",
      "p-valor: ", format.pval(P_valor, digits = 3), "<br>",
      "Significancia: ", Significativa, "<br>",
      "Magnitud: ", Magnitud
    ),
    # Solo mostrar correlaciones significativas
    Correlacion_mostrar = ifelse(P_valor < 0.05, Correlacion, NA)
  )

# El resto del código para crear el heatmap interactivo permanece igual...
plot_ly(data = heatmap_data,
        x = ~Var2, 
        y = ~Var1, 
        z = ~Correlacion_mostrar,
        type = "heatmap",
        colors = colorRamp(c("#d73027", "#fee08b", "#ffffbf", "#d9ef8b", "#1a9850")),
        zmid = 0,
        zmin = -1,
        zmax = 1,
        text = ~Texto_Hover,
        hoverinfo = "text",
        colorbar = list(
          title = list(text = "ρ (Spearman)", side = "right"),
          tickvals = c(-1, -0.5, 0, 0.5, 1),
          ticktext = c("-1.0", "-0.5", "0", "0.5", "1.0"),
          len = 0.7,
          thickness = 20
        )) %>%
  layout(
    title = list(
      text = "<b>Matriz de Correlación de Spearman - Proyectos ACA</b><br><sub>Solo correlaciones significativas (p < 0.05) | Interactivo: pase el cursor para detalles</sub>",
      font = list(size = 18, color = "#2c3e50")
    ),
    xaxis = list(
      title = "", 
      tickangle = 45, 
      tickfont = list(size = 11),
      side = "bottom"
    ),
    yaxis = list(
      title = "", 
      tickfont = list(size = 11),
      autorange = "reversed"
    ),
    margin = list(l = 180, r = 80, t = 120, b = 180),
    paper_bgcolor = "#ffffff",
    plot_bgcolor = "#f8f9fa"
  ) %>%
  config(
    displayModeBar = TRUE,
    displaylogo = FALSE,
    modeBarButtonsToRemove = c("pan2d", "lasso2d", "select2d")
  )

La matriz de correlaciones revela tres patrones estructurales fundamentales que caracterizan el funcionamiento del sistema de Agendas Concretas de Acción en el Estado Mérida:

Primer patrón: Correlaciones perfectas en la fase diagnóstico-asignación. Las celdas azul oscuro en la matriz identifican correlaciones perfectas o casi perfectas (ρ ≥ 0.90) entre la identificación de nudos críticos específicos y su asignación institucional correspondiente. Este patrón es particularmente evidente en sectores como electricidad, vivienda, transporte y vialidad. Estas correlaciones no son coincidencias estadísticas, sino evidencia de protocolos institucionales altamente estandarizados donde cada tipo de problema es sistemáticamente asignado al actor gubernamental competente.

Segundo patrón: La Gran Desconexión con resultados. El hallazgo más crítico emerge al observar la columna correspondiente a la variable Ratio ACA (efectividad de culminación). Las celdas predominantemente blancas o amarillas pálidas en esta columna evidencian la ausencia de correlaciones fuertes o moderadas con otras variables del sistema. Esta desconexión cuantifica empíricamente una brecha estructural: el sistema identifica problemas con precisión y los asigna correctamente, pero esta eficiencia diagnóstica no predice la probabilidad de resolución efectiva.

Tercer patrón: Correlaciones sectoriales específicas. Algunos sectores muestran correlaciones moderadas (celdas verde claro) que sugieren dinámicas particulares. Por ejemplo, el sector transporte presenta una correlación débil pero significativa con la efectividad, indicando que ciertos ámbitos tienen características que los hacen ligeramente más propensos a la culminación exitosa.

Implicaciones metodológicas: La interactividad del gráfico permite explorar cada celda individualmente, revelando no solo la magnitud de la correlación sino también su significancia estadística y el contexto específico de las variables involucradas. Este nivel de detalle es fundamental para distinguir entre patrones robustos y relaciones espurias.

14 Evaluación de Hipótesis de Investigación

# Preparar datos con los resultados reales del análisis
evaluacion_hipotesis <- data.frame(
  Hipotesis = c(
    "HE1: Concordancia Sectorial<br>(Electricidad)",
    "HE2: Concordancia Sectorial<br>(Vivienda)",
    "HE3: Centralización<br>Institucional (Vivienda)",
    "HE4: Eficiencia en<br>Transporte",
    "HE5: Complejidad Temporal<br>(Infraestructura)"
  ),
  Rho = c(1.000, 0.950, -0.368, 0.167, -0.185),
  P_valor = c(0.0000000, 0.0000000, 0.0000001, 0.0189, 0.0089),
  Magnitud = c("Muy fuerte", "Muy fuerte", "Moderada", "Débil", "Débil"),
  Estado = c("Confirmada", "Confirmada", "Confirmada", 
             "Parcialmente Confirmada", "Confirmada"),
  Variables = c(
    "CFG: ELECTRICIDAD ↔ GOB: ELECTRICIDAD",
    "CFG: VIVIENDA ↔ GOB: VIVIENDA",
    "Clasificación Actores ↔ CFG: VIVIENDA",
    "RATIO ACA ↔ GOB: TRANSPORTE",
    "PLAZOS ↔ CFG: INFRAESTRUCTURA"
  )
) %>%
  mutate(
    Color = case_when(
      Estado == "Confirmada" ~ "#27ae60",
      Estado == "Parcialmente Confirmada" ~ "#f39c12",
      TRUE ~ "#e74c3c"
    ),
    Texto_Hover = paste0(
      "<b>", gsub("<br>", " ", Hipotesis), "</b><br>",
      "Variables: ", Variables, "<br>",
      "ρ (Spearman): <b>", round(Rho, 3), "</b><br>",
      "p-valor: ", format.pval(P_valor, digits = 3), "<br>",
      "Magnitud: ", Magnitud, "<br>",
      "Estado: <b>", Estado, "</b>"
    )
  )

# Crear gráfico interactivo
plot_ly(evaluacion_hipotesis, 
        y = ~reorder(Hipotesis, abs(Rho)), 
        x = ~abs(Rho),
        type = 'bar',
        orientation = 'h',
        marker = list(color = ~Color, line = list(color = 'rgb(8,48,107)', width = 1.5)),
        text = ~Texto_Hover,
        hoverinfo = 'text',
        textposition = 'none') %>%
  add_annotations(
    x = ~abs(Rho) + 0.05,
    y = ~Hipotesis,
    text = ~paste0("<b>ρ=", round(Rho, 3), "</b><br>", Estado),
    showarrow = FALSE,
    xanchor = 'left',
    font = list(size = 12, color = 'black')
  ) %>%
  layout(
    title = list(
      text = "<b>Evaluación Empírica de Hipótesis de Investigación</b><br><sub>Magnitud de correlaciones (valor absoluto) y estado de confirmación</sub>",
      font = list(size = 18, color = "#2c3e50")
    ),
    xaxis = list(
      title = "Magnitud de Correlación |ρ|", 
      range = c(0, 1.15),
      tickvals = seq(0, 1, 0.2),
      gridcolor = "#ecf0f1"
    ),
    yaxis = list(title = "", tickfont = list(size = 12)),
    margin = list(l = 220, r = 150, t = 120, b = 80),
    showlegend = FALSE,
    paper_bgcolor = "#ffffff",
    plot_bgcolor = "#f8f9fa",
    shapes = list(
      # Línea de referencia para correlación moderada
      list(type = "line", x0 = 0.4, x1 = 0.4, y0 = -0.5, y1 = 5.5,
           line = list(color = "#95a5a6", width = 2, dash = "dot")),
      # Línea de referencia para correlación fuerte
      list(type = "line", x0 = 0.6, x1 = 0.6, y0 = -0.5, y1 = 5.5,
           line = list(color = "#7f8c8d", width = 2, dash = "dot")),
      # Línea de referencia para correlación muy fuerte
      list(type = "line", x0 = 0.8, x1 = 0.8, y0 = -0.5, y1 = 5.5,
           line = list(color = "#34495e", width = 2, dash = "dash"))
    ),
    annotations = list(
      list(x = 0.4, y = 5, text = "Moderada", showarrow = FALSE, 
           xanchor = "center", yanchor = "bottom", font = list(size = 10, color = "#95a5a6")),
      list(x = 0.6, y = 5, text = "Fuerte", showarrow = FALSE,
           xanchor = "center", yanchor = "bottom", font = list(size = 10, color = "#7f8c8d")),
      list(x = 0.8, y = 5, text = "Muy fuerte", showarrow = FALSE,
           xanchor = "center", yanchor = "bottom", font = list(size = 10, color = "#34495e"))
    )
  ) %>%
  config(
    displayModeBar = TRUE,
    displaylogo = FALSE,
    modeBarButtonsToRemove = c("pan2d", "lasso2d", "select2d")
  )

15 Análisis Detallado por Hipótesis

HE1 (ρ = 1.000): Concordancia perfecta en electricidad. La correlación perfecta entre la identificación de problemas eléctricos y su asignación a Corpoelec o la Gobernación representa el punto más fuerte del sistema. Esta precisión institucional evidencia un protocolo estandarizado donde no hay ambigüedad sobre quién debe actuar. En un contexto venezolano caracterizado por fragmentación institucional, este resultado es excepcional y sugiere que el sector eléctrico ha logrado establecer un consenso claro entre la sociedad civil y el Estado sobre las rutas de responsabilidad.

HE2 (ρ = 0.950): Alta efectividad en vivienda. La correlación casi perfecta en vivienda confirma que, para problemas de alta complejidad que involucran tierra, financiamiento y coordinación interinstitucional, el sistema también funciona con precisión notable. La ligera reducción respecto a electricidad (0.950 vs 1.000) podría reflejar mayor heterogeneidad en los actores competentes o solapamientos jurisdiccionales ocasionales.

HE3 (ρ = -0.368): Centralización funcional. La correlación negativa moderada entre nivel jerárquico de actores y problemas de vivienda revela un mecanismo de sobrevivencia institucional. Las comunas, reconociendo la complejidad del problema habitacional, tienden a escalar estas demandas hacia actores de mayor nivel (Ministerios, Gobernación) en lugar de delegarlas a instancias locales. Esta centralización no es un error sino una adaptación racional a la realidad de recursos limitados en niveles municipales o comunales.

HE4 (ρ = 0.167): Efectividad marginal en transporte. La correlación débil pero significativa con transporte sugiere que este sector tiene características que lo hacen ligeramente más propicio a la culminación. Posiblemente, los proyectos de transporte tienen especificaciones técnicas más objetivas, menores dependencias interinstitucionales o mayor visibilidad política que los convierte en “proyectos vitrina” que se priorizan para mostrar resultados tangibles.

HE5 (ρ = -0.185): Urgencia vs viabilidad técnica. La correlación negativa débil entre plazos e infraestructura evidencia que estos proyectos tienden a asignarse plazos más cortos, posiblemente por su urgencia visible. Sin embargo, esta asignación de plazos cortos puede ser más una declaración de intenciones que un cronograma realista, contribuyendo al estancamiento posterior de estos proyectos.

16 Desconexión Estructural entre Planificación y Ejecución

El hallazgo más crítico de este análisis no radica en las correlaciones fuertes que encontramos, sino en aquellas que no encontramos. La variable Ratio ACA, que mide la efectividad en culminación de proyectos, no presenta correlaciones fuertes o moderadas con ninguna otra variable del sistema, excepto una correlación débil con el sector transporte.

Este resultado cuantifica empíricamente una brecha estructural que denominamos “La Gran Desconexión”: el sistema de ACA es excelente para mapear problemas y asignarlos institucionalmente, pero esta eficiencia diagnóstica no se traduce en capacidad de ejecución.

Implicaciones de la Desconexión

Para la investigación: Este hallazgo implica que los factores determinantes del éxito o fracaso en la ejecución de proyectos están fuera del modelo medido. Variables como disponibilidad presupuestaria, voluntad política, capacidad técnica, cambios administrativos o factores contextuales no capturados son los verdaderos predictores de la culminación.

Para la política pública: La desconexión revela que mejorar el diagnóstico participativo (que ya funciona bien) no resolverá el problema de ejecución. Se requieren intervenciones específicas en la fase de implementación: fortalecimiento de capacidades técnicas, mecanismos de seguimiento efectivos, estabilidad administrativa y financiamiento predecible.

Para la teoría de gobernanza: Este patrón desafía modelos que asumen que una buena planificación participativa conduce automáticamente a buenos resultados. La evidencia sugiere que planificación y ejecución operan en lógicas institucionales distintas que no están conectadas orgánicamente.

##Tablas Resumen Ejecutivas

# Tabla 1: Distribución de correlaciones por magnitud
distribucion_cor <- cor_df %>%
  filter(Significativa == "Sí") %>%
  group_by(Magnitud) %>%
  summarise(
    N_Correlaciones = n(),
    Rango = paste0("[", round(min(abs(Correlacion)), 2), 
                  " - ", round(max(abs(Correlacion)), 2), "]"),
    P_valor_promedio = round(mean(p_valor), 4),
    .groups = "drop"
  ) %>%
  arrange(match(Magnitud, c("Muy fuerte", "Fuerte", "Moderada", "Débil")))

datatable(distribucion_cor,
          caption = "Tabla 1: Distribución de Correlaciones Significativas por Magnitud",
          options = list(
            pageLength = 10,
            dom = 't',
            ordering = FALSE
          ),
          rownames = FALSE,
          class = 'cell-border stripe') %>%
  formatStyle(columns = c(1:4), fontSize = '14px') %>%
  formatStyle('Magnitud', 
              backgroundColor = styleEqual(
                c("Muy fuerte", "Fuerte", "Moderada", "Débil"),
                c("#E57373", "#81C784", "#FFF176", "#E0E0E0")
              ))
# Tabla 2: Top 10 correlaciones más fuertes
top_correlaciones <- cor_df %>%
  filter(Significativa == "Sí") %>%
  arrange(desc(abs(Correlacion))) %>%
  head(10) %>%
  select(Variable1, Variable2, Correlacion, p_valor, Magnitud)

datatable(top_correlaciones,
          caption = "Tabla 2: Top 10 Correlaciones Más Fuertes",
          options = list(
            pageLength = 10,
            dom = 't'
          ),
          rownames = FALSE,
          class = 'cell-border stripe') %>%
  formatStyle(columns = c(1:5), fontSize = '14px') %>%
  formatRound('Correlacion', 3) %>%
  formatSignif('p_valor', 3)

17 Visualización de los resultados

# -----------------------------------------------------------------------------
# FUNCIÓN PARA LIMPIAR EL ENTORNO (OPCIONAL)
# -----------------------------------------------------------------------------
limpiar_objetos_analisis <- function() {
  objetos_a_limpiar <- c("div_combinada", "tipo_comuna_stats", 
                        "div_cfg_con_tipo", "div_gob_con_tipo", "div_ratio_con_tipo")
  objetos_existentes <- objetos_a_limpiar[objetos_a_limpiar %in% ls(envir = .GlobalEnv)]
  if(length(objetos_existentes) > 0) {
    rm(list = objetos_existentes, envir = .GlobalEnv)
    cat("Limpiados objetos:", paste(objetos_existentes, collapse = ", "), "\n")
  }
}

# Ejecutar si quieres limpiar (descomenta la siguiente línea)
# limpiar_objetos_analisis()

# -----------------------------------------------------------------------------
# CLASIFICACIÓN COMPLETA Y CREACIÓN DEL TIPO DE COMUNA
# -----------------------------------------------------------------------------
crear_mapa_comunas <- function(df_source) {
  # Esta función crea el mapa de comunas de forma limpia cada vez
  mapa <- df_source %>%
    distinct(ID_COMUNA, COMUNA, COD_CC) %>%
    mutate(
      COMUNA = str_trim(COMUNA),
      Tipo_Comuna = case_when(
        str_detect(COD_CC, "C-URB") ~ "Urbana",
        str_detect(COD_CC, "C-RUR") ~ "Rural", 
        str_detect(COD_CC, "C-MIX") ~ "Mixta",
        str_detect(COD_CC, "^\\d{2}-\\d{2}-\\d{4}$") ~ "En construcción",
        str_detect(COD_CC, "^\\d{2}-\\d{2}-\\d{2}") ~ "En construcción",
        str_detect(COD_CC, "^CEC") ~ "En construcción",
        TRUE ~ "No especificado"
      )
    )
  
  return(mapa)
}

# Verificar distribución
table(commune_map$Tipo_Comuna)
## < table of extent 0 >
# Crear el mapa de comunas fresco cada vez
commune_map <- crear_mapa_comunas(df_raw)

# Verificar distribución
cat("Distribución de tipos de comuna:\n")
## Distribución de tipos de comuna:
print(table(commune_map$Tipo_Comuna))
## 
## En construcción           Mixta           Rural          Urbana 
##              21              23              11               5
# =============================================================================
# ANÁLISIS INTEGRAL ÍNDICE SHANNON - POLÍTICAS PÚBLICAS ACA
# =============================================================================

# -----------------------------------------------------------------------------
# PALETA DE COLORES Y TEMA COMÚN
# -----------------------------------------------------------------------------
colores_comuna <- c(
  "Urbana" = "#2E86AB",           # Azul - densidad urbana
  "Rural" = "#A23B72",            # Magenta - ruralidad
  "Mixta" = "#F18F01",            # Naranja - combinación
  "En construcción" = "#C73E1D",   # Rojo - desarrollo
  "No especificado" = "#7D8491"    # Gris - sin clasificar
)

tema_comun <- theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 16, hjust = 0.5, color = "#2E86AB"),
    plot.subtitle = element_text(size = 12, color = "gray40", hjust = 0.5),
    axis.title = element_text(face = "bold", size = 11),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
    legend.position = "bottom",
    strip.text = element_text(face = "bold", size = 11, color = "#2E86AB"),
    strip.background = element_rect(fill = "gray95", color = "white"),
    panel.border = element_rect(color = "gray90", fill = NA),
    legend.title = element_text(face = "bold")
  )

# -----------------------------------------------------------------------------
# PREPARACIÓN DE DATOS
# -----------------------------------------------------------------------------
# Crear mapa de comunas
commune_map <- df_raw %>%
  distinct(ID_COMUNA, COMUNA, COD_CC) %>%
  mutate(
    COMUNA = str_trim(COMUNA),
    Tipo_Comuna = case_when(
      str_detect(COD_CC, "C-URB") ~ "Urbana",
      str_detect(COD_CC, "C-RUR") ~ "Rural", 
      str_detect(COD_CC, "C-MIX") ~ "Mixta",
      str_detect(COD_CC, "^\\d{2}-\\d{2}-\\d{4}$") ~ "En construcción",
      str_detect(COD_CC, "^\\d{2}-\\d{2}-\\d{2}") ~ "En construcción",
      str_detect(COD_CC, "^CEC") ~ "En construcción",
      TRUE ~ "No especificado"
    )
  )

# Agregar tipo de comuna a cada dataset
div_cfg_con_tipo <- div_cfg %>%
  select(-contains("Tipo_Comuna")) %>%
  left_join(commune_map %>% select(ID_COMUNA, Tipo_Comuna), by = "ID_COMUNA")

div_gob_con_tipo <- div_gob %>%
  select(-contains("Tipo_Comuna")) %>%
  left_join(commune_map %>% select(ID_COMUNA, Tipo_Comuna), by = "ID_COMUNA")

div_ratio_con_tipo <- div_ratio %>%
  select(-contains("Tipo_Comuna")) %>%
  left_join(commune_map %>% select(ID_COMUNA, Tipo_Comuna), by = "ID_COMUNA")

# Combinar datasets
div_combinada <- bind_rows(
  div_cfg_con_tipo %>%
    select(COMUNA_ID_NOMBRE, n_proyectos, H_shannon, pielou, Tipo_Comuna) %>%
    mutate(Tipo_Analisis = "CFG"),
  
  div_gob_con_tipo %>%
    select(COMUNA_ID_NOMBRE, n_proyectos, H_shannon, pielou, Tipo_Comuna) %>%
    mutate(Tipo_Analisis = "Gobernación"),
  
  div_ratio_con_tipo %>%
    select(COMUNA_ID_NOMBRE, n_proyectos = n_proyectos_ratio, H_shannon, pielou, Tipo_Comuna) %>%
    mutate(Tipo_Analisis = "Ratio ACA")
) %>%
  mutate(
    Shannon_Categoria = case_when(
      H_shannon < 0.5 ~ "Muy Baja",
      H_shannon < 1.0 ~ "Baja", 
      H_shannon < 1.5 ~ "Media",
      H_shannon >= 1.5 ~ "Alta"
    ),
    Eficiencia = H_shannon / (n_proyectos + 0.1)
  ) %>%
  filter(!is.na(H_shannon), !is.na(Tipo_Comuna), is.finite(H_shannon))

# -----------------------------------------------------------------------------
# ESTADÍSTICAS DESCRIPTIVAS
# -----------------------------------------------------------------------------
stats_shannon <- div_combinada %>%
  group_by(Tipo_Analisis, Tipo_Comuna) %>%
  summarise(
    n = n(),
    mean_shannon = mean(H_shannon, na.rm = TRUE),
    sd_shannon = sd(H_shannon, na.rm = TRUE),
    median_shannon = median(H_shannon, na.rm = TRUE),
    se = sd_shannon / sqrt(n),
    .groups = "drop"
  ) %>%
  filter(n >= 2)

# Mostrar tabla de estadísticas
kable(stats_shannon,
      caption = "Estadísticas del Índice Shannon por Tipo de Comuna y Análisis",
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Estadísticas del Índice Shannon por Tipo de Comuna y Análisis
Tipo_Analisis Tipo_Comuna n mean_shannon sd_shannon median_shannon se
CFG En construcción 23 1.103 0.269 1.099 0.056
CFG Mixta 23 1.083 0.251 1.099 0.052
CFG Rural 11 1.120 0.263 1.099 0.079
CFG Urbana 5 1.006 0.207 1.099 0.092
Gobernación En construcción 23 1.163 0.197 1.099 0.041
Gobernación Mixta 23 1.179 0.295 1.099 0.062
Gobernación Rural 11 1.141 0.139 1.099 0.042
Gobernación Urbana 5 1.006 0.207 1.099 0.092
Ratio ACA En construcción 23 0.699 0.228 0.637 0.048
Ratio ACA Mixta 23 0.718 0.361 0.637 0.075
Ratio ACA Rural 11 0.723 0.415 0.637 0.125
Ratio ACA Urbana 5 0.382 0.349 0.637 0.156
# -----------------------------------------------------------------------------
# GRÁFICOS
# -----------------------------------------------------------------------------

# 1. Distribución Shannon
grafico_1_distribucion <- ggplot(div_combinada, aes(x = Tipo_Comuna, y = H_shannon, fill = Tipo_Comuna)) +
  geom_violin(alpha = 0.7, trim = FALSE, color = "white", linewidth = 0.8) +
  geom_boxplot(width = 0.2, fill = "white", outlier.colour = "#2E86AB", 
               outlier.size = 2, color = "black", linewidth = 0.5) +
  geom_jitter(aes(color = Tipo_Comuna), width = 0.15, size = 1.8, alpha = 0.6) +
  scale_fill_manual(values = colores_comuna, name = "Tipo de Comuna") +
  scale_color_manual(values = colores_comuna, name = "Tipo de Comuna") +
  facet_wrap(~ Tipo_Analisis, scales = "free_y") +
  labs(
    title = "Distribución del Índice de Shannon por Tipo de Comuna",
    subtitle = "Análisis de diversidad en Agendas Concretas de Acción - Mérida, Venezuela",
    y = "Índice de Shannon (H')", 
    x = "Tipo de Comuna",
    caption = "Elaborado por: William Gutiérrez"
  ) +
  tema_comun

print(grafico_1_distribucion)

# 2. Relación proyectos-Shannon
grafico_2_relacion <- ggplot(div_combinada, aes(x = n_proyectos, y = H_shannon)) +
  geom_point(aes(color = Tipo_Comuna), size = 3, alpha = 0.7) +
  geom_smooth(method = "loess", se = TRUE, color = "#2E86AB", 
              fill = "#2E86AB", alpha = 0.2, linewidth = 1.2) +
  scale_color_manual(values = colores_comuna, name = "Tipo de Comuna") +
  facet_wrap(~ Tipo_Analisis, scales = "free") +
  labs(
    title = "Relación entre Número de Proyectos y Diversidad Shannon",
    subtitle = "Análisis de correlación en políticas ACA",
    x = "Número de Proyectos",
    y = "Índice de Shannon (H')",
    caption = "Elaborado por: William Gutiérrez"
  ) +
  tema_comun

print(grafico_2_relacion)

# 3. Comparativa de medias con intervalos de confianza
grafico_3_comparativa <- ggplot(stats_shannon, 
                               aes(x = reorder(Tipo_Comuna, mean_shannon), 
                                   y = mean_shannon, fill = Tipo_Comuna)) +
  geom_col(alpha = 0.8, color = "white", linewidth = 0.8) +
  geom_errorbar(aes(ymin = pmax(0, mean_shannon - se), 
                    ymax = mean_shannon + se), 
                width = 0.3, color = "black", linewidth = 0.8) +
  geom_text(aes(label = sprintf("%.2f", mean_shannon)), 
            vjust = -1.5, size = 4, fontface = "bold", color = "#2E86AB") +
  scale_fill_manual(values = colores_comuna, name = "Tipo de Comuna") +
  facet_wrap(~ Tipo_Analisis, scales = "free_y") +
  labs(
    title = "Índice de Shannon Promedio por Tipo de Comuna",
    subtitle = "Barras de error representan error estándar de la media",
    x = "Tipo de Comuna",
    y = "Shannon Promedio (H')",
    caption = "Elaborado por: William Gutiérrez"
  ) +
  tema_comun

print(grafico_3_comparativa)

# 4. Heatmap de frecuencias
datos_heatmap <- div_combinada %>%
  filter(Tipo_Analisis %in% c("CFG", "Gobernación")) %>%
  count(Tipo_Analisis, Tipo_Comuna, Shannon_Categoria) %>%
  complete(Tipo_Analisis, Tipo_Comuna, Shannon_Categoria, fill = list(n = 0))

grafico_4_heatmap <- ggplot(datos_heatmap, 
                           aes(x = Shannon_Categoria, y = Tipo_Comuna, fill = n)) +
  geom_tile(color = "white", linewidth = 0.8) +
  geom_text(aes(label = n, 
                color = ifelse(n >= max(n)/2, "white", "black")), 
            fontface = "bold", size = 4) +
  scale_fill_gradient(
    low = "#C6DBEF",    # Azul claro
    high = "#08519C",   # Azul oscuro
    name = "Frecuencia"
  ) +
  scale_color_identity() +
  facet_wrap(~ Tipo_Analisis) +
  labs(
    title = "Distribución de Frecuencias: Tipo Comuna vs. Shannon",
    subtitle = "Mapa de calor para análisis CFG y Gobernación",
    x = "Categoría Shannon",
    y = "Tipo de Comuna",
    caption = "Elaborado por: William Gutiérrez"
  ) +
  tema_comun

print(grafico_4_heatmap)

# 5. Índice de Pielou vs Shannon
grafico_5_pielou <- ggplot(div_combinada, aes(x = n_proyectos, y = H_shannon)) +
  geom_point(aes(color = Tipo_Comuna), size = 3, alpha = 0.7) +
  geom_smooth(method = "lm", se = TRUE, color = "#2E86AB", 
              fill = "#2E86AB", alpha = 0.2, linewidth = 1.2) +
  scale_color_manual(values = colores_comuna, name = "Tipo de Comuna") +
  facet_wrap(~ Tipo_Analisis) +
  labs(
    title = "Relación entre Número de Proyectos y Shannon",
    subtitle = "Análisis de proyectos y diversidad en ACA",
    x = "Número de Proyectos",
    y = "Índice de Shannon (H')",
    caption = "Elaborado por: William Gutiérrez"
  ) +
  tema_comun

print(grafico_5_pielou)

##4.8 Modelo de Correlación por Tipo de Comuna

# --------------------ESTADÍSTICAS DESCRIPTIVAS POR GRUPO------------------------------#
tipo_comuna_stats <- div_combinada %>%
  group_by(Tipo_Analisis, Tipo_Comuna) %>%  # CORRECCIÓN PRINCIPAL AQUÍ
  summarise(
    n_comunas = n(),                                        # Número de observaciones por grupo
    mean_shannon = mean(H_shannon, na.rm = TRUE),          # Media del índice Shannon
    sd_shannon = sd(H_shannon, na.rm = TRUE),              # Desviación estándar Shannon
    mean_pielou = mean(pielou, na.rm = TRUE),              # Media del índice Pielou
    sd_pielou = sd(pielou, na.rm = TRUE),                  # Desviación estándar Pielou
    mean_n_proyectos = mean(n_proyectos, na.rm = TRUE),    # Media número de proyectos
    sd_n_proyectos = sd(n_proyectos, na.rm = TRUE),        # Desviación estándar proyectos
    .groups = "drop"  # Elimina el agrupamiento después del cálculo
  )

# Mostrar resultados de estadísticas descriptivas en formato tabla
cat("\n==== ESTADÍSTICAS DESCRIPTIVAS POR TIPO DE COMUNA ====\n")
## 
## ==== ESTADÍSTICAS DESCRIPTIVAS POR TIPO DE COMUNA ====
kable(tipo_comuna_stats, 
      caption = "Estadísticas Descriptivas por Tipo de Comuna y Tipo de Análisis",
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Estadísticas Descriptivas por Tipo de Comuna y Tipo de Análisis
Tipo_Analisis Tipo_Comuna n_comunas mean_shannon sd_shannon mean_pielou sd_pielou mean_n_proyectos sd_n_proyectos
CFG En construcción 23 1.103 0.269 0.979 0.032 3.696 1.222
CFG Mixta 23 1.083 0.251 0.980 0.049 3.478 1.504
CFG Rural 11 1.120 0.263 0.993 0.025 3.273 0.905
CFG Urbana 5 1.006 0.207 0.984 0.037 3.000 0.000
Gobernación En construcción 23 1.163 0.197 0.989 0.022 3.696 1.222
Gobernación Mixta 23 1.179 0.295 0.999 0.006 3.478 1.504
Gobernación Rural 11 1.141 0.139 0.997 0.009 3.273 0.905
Gobernación Urbana 5 1.006 0.207 0.984 0.037 3.000 0.000
Ratio ACA En construcción 23 0.699 0.228 0.949 0.038 3.696 1.222
Ratio ACA Mixta 23 0.718 0.361 0.944 0.038 3.478 1.504
Ratio ACA Rural 11 0.723 0.415 0.955 0.043 3.273 0.905
Ratio ACA Urbana 5 0.382 0.349 0.918 0.000 3.000 0.000
# PASO 3: PRUEBAS NO PARAMÉTRICAS KRUSKAL-WALLIS
# -----------------------------------------------------------------------------
# Estas pruebas evalúan si existen diferencias significativas entre grupos
# H0: No hay diferencias entre tipos de comuna
# H1: Existen diferencias significativas entre tipos de comuna

kruskal_shannon <- kruskal.test(H_shannon ~ Tipo_Comuna, data = div_combinada)
kruskal_pielou  <- kruskal.test(pielou ~ Tipo_Comuna, data = div_combinada)
kruskal_nproy   <- kruskal.test(n_proyectos ~ Tipo_Comuna, data = div_combinada)

#  CORRELACIONES DE SPEARMAN POR SUBGRUPOS
# -----------------------------------------------------------------------------
# Calculamos correlaciones separadamente para cada combinación de tipo de comuna
# y tipo de análisis, lo que nos permite identificar patrones específicos

correlaciones_por_tipo <- div_combinada %>%
  group_by(Tipo_Comuna, Tipo_Analisis) %>%  # CORRECCIÓN PRINCIPAL AQUÍ TAMBIÉN
  summarise(
    # Correlación entre número de proyectos y diversidad Shannon
    cor_n_proy_H = cor(n_proyectos, H_shannon, method = "spearman", use = "complete.obs"),
    p_n_proy_H = tryCatch({
      cor.test(n_proyectos, H_shannon, method = "spearman", exact = FALSE)$p.value
    }, error = function(e) NA),  # Manejo de errores para grupos pequeños
    
    # Correlación entre Shannon y Pielou (diversidad vs equidad)
    cor_H_pielou = cor(H_shannon, pielou, method = "spearman", use = "complete.obs"),
    p_H_pielou = tryCatch({
      cor.test(H_shannon, pielou, method = "spearman", exact = FALSE)$p.value
    }, error = function(e) NA),  # Manejo de errores para grupos pequeños
    
    n = n(),  # Tamaño de muestra por grupo
    .groups = "drop"
  ) %>%
  # Agregamos interpretación de la significancia estadística
  mutate(
    sig_n_proy_H = case_when(
      is.na(p_n_proy_H) ~ "No calculable",
      p_n_proy_H < 0.001 ~ "***",
      p_n_proy_H < 0.01 ~ "**", 
      p_n_proy_H < 0.05 ~ "*",
      TRUE ~ "ns"
    ),
    sig_H_pielou = case_when(
      is.na(p_H_pielou) ~ "No calculable",
      p_H_pielou < 0.001 ~ "***",
      p_H_pielou < 0.01 ~ "**",
      p_H_pielou < 0.05 ~ "*", 
      TRUE ~ "ns"
    )
  )

# ==================================================================================================
# ANÁLISIS DE CORRELACIÓN POR TIPO DE COMUNA
# ==================================================================================================

#  Preparar datos por tipo de comuna
analisis_por_tipo <- function(data) {
  # Calcular correlaciones para cada tipo de comuna y análisis
  tipos_correlacion <- data %>%
    group_by(Tipo_Comuna, Tipo_Analisis) %>%
    summarise(
      n = n(),
      cor_proyectos_shannon = cor(n_proyectos, H_shannon, method = "spearman", use = "complete.obs"),
      p_valor = tryCatch({
        cor.test(n_proyectos, H_shannon, method = "spearman")$p.value
      }, error = function(e) NA),
      .groups = "drop"
    ) %>%
    mutate(
      significancia = case_when(
        p_valor < 0.001 ~ "***",
        p_valor < 0.01 ~ "**",
        p_valor < 0.05 ~ "*",
        TRUE ~ "ns"
      ),
      magnitud = case_when(
        abs(cor_proyectos_shannon) > 0.8 ~ "Muy fuerte",
        abs(cor_proyectos_shannon) > 0.6 ~ "Fuerte",
        abs(cor_proyectos_shannon) > 0.4 ~ "Moderada",
        TRUE ~ "Débil"
      )
    )
  
  return(tipos_correlacion)
}

#  Ejecutar análisis
resultados_tipo_comuna <- analisis_por_tipo(div_combinada)

#  Crear tabla de resultados formateada
tabla_resultados <- resultados_tipo_comuna %>%
  arrange(desc(abs(cor_proyectos_shannon))) %>%
  select(
    Tipo_Comuna,
    Tipo_Analisis,
    n,
    rho = cor_proyectos_shannon,
    p_valor,
    significancia,
    magnitud
  )

# Mostrar tabla con formato
kable(tabla_resultados,
      caption = "Correlaciones de Spearman por Tipo de Comuna y Análisis",
      col.names = c("Tipo Comuna", "Tipo Análisis", "n", "ρ", "p-valor", "Sig.", "Magnitud"),
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(0, bold = TRUE) %>%
  row_spec(
    which(tabla_resultados$magnitud == "Muy fuerte"), 
    bold = TRUE, 
    color = "white", 
    background = "#1b9e77"
  ) %>%
  row_spec(
    which(tabla_resultados$magnitud == "Fuerte"), 
    bold = TRUE, 
    color = "white", 
    background = "#66a61e"
  )
Correlaciones de Spearman por Tipo de Comuna y Análisis
Tipo Comuna Tipo Análisis n ρ p-valor Sig. Magnitud
Rural Gobernación 11 1.000 0.000 *** Muy fuerte
Mixta Gobernación 23 0.999 0.000 *** Muy fuerte
En construcción Gobernación 23 0.910 0.000 *** Muy fuerte
En construcción CFG 23 0.820 0.000 *** Muy fuerte
Rural CFG 11 0.742 0.009 ** Fuerte
En construcción Ratio ACA 23 0.541 0.008 ** Moderada
Mixta CFG 23 0.471 0.023
Moderada
Mixta Ratio ACA 23 0.314 0.145 ns Débil
Rural Ratio ACA 11 0.105 0.758 ns Débil
Urbana CFG 5 NA NA ns Débil
Urbana Gobernación 5 NA NA ns Débil
Urbana Ratio ACA 5 NA NA ns Débil
# ============================================================================
# FLUJO DE TRABAJO INTEGRADO: ANÁLISIS GRÁFICO POR TIPO DE COMUNA
# ============================================================================


# Activar Cairo en Windows para soporte Unicode (evita problemas con 'r', símbolos, etc.)
if (.Platform$OS.type == "windows") {
  options(bitmapType = "cairo")
}

# Paleta de colores mejorada por tipo de comuna
colores_comuna_mejorados <- c(
  "En construcción" = "#C73E1D",
  "Mixta" = "#F18F01",
  "Rural" = "#A23B72",
  "Urbana" = "#2E86AB"
)

# Tema académico personalizado
tema_academico <- theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 16, hjust = 0.5, margin = margin(b = 10)),
    plot.subtitle = element_text(size = 12, hjust = 0.5, color = "gray30", margin = margin(b = 15)),
    axis.title = element_text(face = "bold", size = 12),
    axis.text = element_text(size = 10),
    legend.title = element_text(face = "bold", size = 11),
    legend.text = element_text(size = 10),
    strip.text = element_text(face = "bold", size = 11, color = "#2E86AB"),
    strip.background = element_rect(fill = "gray95", color = "white"),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "gray95", size = 0.5),
    plot.caption = element_text(size = 9, color = "gray50", hjust = 1)
  )

# =============================================================================
# 1. HEATMAP DE CORRELACIONES
# =============================================================================

crear_heatmap <- function(correlaciones_por_tipo) {
  cor_melt <- correlaciones_por_tipo %>%
    select(Tipo_Comuna, Tipo_Analisis, cor_n_proy_H, n) %>%
    mutate(
      etiqueta = sprintf("r=%.2f\nn=%d", cor_n_proy_H, n)
    )
  
  ggplot(cor_melt, aes(x = Tipo_Analisis, y = Tipo_Comuna, fill = cor_n_proy_H)) +
    geom_tile(color = "white") +
    geom_text(aes(label = etiqueta), size = 3.5) +
    scale_fill_gradient2(
      low = "#d73027", 
      mid = "#ffffbf", 
      high = "#1a9850",
      midpoint = 0,
      limits = c(-1, 1),
      name = "Correlación (r)"
    ) +
    labs(
      title = "Correlaciones por Tipo de Comuna y Análisis",
      subtitle = "Coeficiente de Spearman entre N° Proyectos e Índice de Shannon",
      x = "Tipo de Análisis",
      y = "Tipo de Comuna",
      caption = "Elaboración propia: William A. Gutiérrez V. | Monografía ACA - Estado Mérida"
    ) +
    tema_academico +
    theme(axis.text.x = element_text(angle = 45, hjust = 1))
}

# =============================================================================
# 2. GRÁFICO DE DISPERSIÓN
# =============================================================================

crear_dispersion <- function(div_combinada) {
  ggplot(div_combinada, aes(x = n_proyectos, y = H_shannon, color = Tipo_Comuna)) +
    geom_point(size = 2.5, alpha = 0.7) +
    geom_smooth(method = "lm", se = TRUE, alpha = 0.2, size = 1.2) +
    facet_wrap(~ Tipo_Analisis, scales = "free", ncol = 3) +
    scale_color_manual(values = colores_comuna_mejorados, name = "Tipo de Comuna") +
    labs(
      title = "Relación entre Número de Proyectos y Diversidad Shannon",
      subtitle = "Líneas de tendencia ajustadas por regresión lineal",
      x = "Número de Proyectos por Comuna",
      y = "Índice de Shannon (H')",
      caption = "Elaboración propia: William A. Gutiérrez V. | Monografía ACA - Estado Mérida"
    ) +
    tema_academico +
    theme(legend.position = "bottom")
}

# =============================================================================
# 3. BARRAS DE CORRELACIÓN CON INTERVALOS DE CONFIANZA
# =============================================================================

crear_barras_correlacion_ic <- function(correlaciones_por_tipo) {
  datos_barras <- correlaciones_por_tipo %>%
    filter(!is.na(p_n_proy_H), p_n_proy_H < 0.05) %>%
    mutate(
      se_aprox = sqrt((1 - cor_n_proy_H^2) / (n - 2)),
      ic_inferior = pmax(-1, cor_n_proy_H - 1.96 * se_aprox),
      ic_superior = pmin(1, cor_n_proy_H + 1.96 * se_aprox),
      etiqueta_completa = sprintf("r=%.3f\n(IC: %.2f, %.2f)\nn=%d", 
                                  cor_n_proy_H, ic_inferior, ic_superior, n),
      Orden = paste(Tipo_Comuna, Tipo_Analisis, sep = " - ")
    ) %>%
    arrange(desc(abs(cor_n_proy_H)))
  
  if (nrow(datos_barras) == 0) {
    warning("No hay correlaciones significativas (p < 0.05) para mostrar.")
    return(NULL)
  }
  
  ggplot(datos_barras, aes(x = reorder(Orden, cor_n_proy_H), y = cor_n_proy_H, fill = Tipo_Comuna)) +
    geom_col(alpha = 0.8, color = "black", size = 0.3) +
    geom_errorbar(aes(ymin = ic_inferior, ymax = ic_superior), 
                  width = 0.3, color = "black", size = 0.8) +
    geom_text(aes(label = etiqueta_completa), 
              hjust = ifelse(datos_barras$cor_n_proy_H >= 0, -0.1, 1.1),
              size = 3.2, fontface = "bold") +
    geom_hline(yintercept = 0, linetype = "solid", alpha = 0.5) +
    scale_fill_manual(values = colores_comuna_mejorados, name = "Tipo de Comuna") +
    coord_flip() +
    labs(
      title = "Correlaciones Significativas con IC (95%)",
      subtitle = "Solo p < 0.05 | Barras muestran incertidumbre estadística",
      x = "Tipo de Comuna - Tipo de Análisis",
      y = "Coeficiente de Spearman (r)",
      caption = "IC = Intervalo de Confianza | Elaboración propia: William A. Gutiérrez V."
    ) +
    tema_academico +
    theme(legend.position = "bottom") +
    scale_y_continuous(limits = c(-1.2, 1.2), breaks = seq(-1, 1, 0.25))
}

# =============================================================================
# 4. RED DE CORRELACIONES SIGNIFICATIVAS
# =============================================================================

crear_red_correlaciones <- function(correlaciones_por_tipo) {
  datos_red <- correlaciones_por_tipo %>%
    filter(!is.na(p_n_proy_H), p_n_proy_H < 0.01, abs(cor_n_proy_H) > 0.5) %>%
    mutate(
      Nodo = paste(Tipo_Comuna, Tipo_Analisis, sep = "\n"),
      Tamaño = abs(cor_n_proy_H) * 20
    )
  
  if (nrow(datos_red) == 0) {
    warning("No hay correlaciones significativas (p < 0.01, |r| > 0.5).")
    return(NULL)
  }
  
  n_nodos <- nrow(datos_red)
  angulos <- seq(0, 2*pi, length.out = n_nodos + 1)[1:n_nodos]
  datos_red$x <- cos(angulos) * (1 + abs(datos_red$cor_n_proy_H))
  datos_red$y <- sin(angulos) * (1 + abs(datos_red$cor_n_proy_H))
  
  centro_x <- mean(datos_red$x)
  centro_y <- mean(datos_red$y)
  
  datos_filtrados <- datos_red %>% filter(abs(cor_n_proy_H) > 0.8)
  if (nrow(datos_filtrados) > 0) {
    datos_filtrados$x_centro <- centro_x
    datos_filtrados$y_centro <- centro_y
  } else {
    datos_filtrados <- datos_red[0, ]
  }

  ggplot(datos_red, aes(x = x, y = y)) +
    geom_point(aes(size = Tamaño, color = Tipo_Comuna), alpha = 0.8) +
    geom_text_repel(aes(label = paste0(Nodo, "\nr=", round(cor_n_proy_H, 2))),
                    size = 3.5, fontface = "bold",
                    box.padding = 0.5, point.padding = 0.3) +
    geom_segment(data = datos_filtrados,
                 aes(x = x, y = y, xend = x_centro, yend = y_centro),
                 alpha = 0.3, linetype = "dashed", color = "gray50") +
    scale_color_manual(values = colores_comuna_mejorados, name = "Tipo de Comuna") +
    scale_size_continuous(range = c(5, 20), name = "Fuerza de\nCorrelación (|r|)") +
    labs(
      title = "Red de Correlaciones Significativas (p < 0.01, |r| > 0.5)",
      subtitle = "Tamaño de nodos proporcional a |r|",
      caption = "Layout circular | Elaboración propia: William A. Gutiérrez V. | Monografía ACA"
    ) +
    tema_academico +
    theme(
      axis.text = element_blank(),
      axis.ticks = element_blank(),
      axis.title = element_blank(),
      panel.grid = element_blank(),
      legend.position = "bottom"
    ) +
    coord_equal()
}

# =============================================================================
# 5. PANEL DE PRUEBAS ESTADÍSTICAS (KRUSKAL-WALLIS)
# =============================================================================

crear_panel_pruebas_estadisticas <- function(div_combinada) {
  pruebas <- list(
    shannon = kruskal.test(H_shannon ~ Tipo_Comuna, data = div_combinada),
    pielou = kruskal.test(pielou ~ Tipo_Comuna, data = div_combinada),
    n_proyectos = kruskal.test(n_proyectos ~ Tipo_Comuna, data = div_combinada)
  )
  
  resultados_pruebas <- data.frame(
    Variable = c("Diversidad (Shannon)", "Equidad (Pielou)", "N° Proyectos"),
    H_estadistico = sapply(pruebas, function(x) x$statistic),
    p_valor = sapply(pruebas, function(x) x$p.value),
    gl = sapply(pruebas, function(x) x$parameter)
  ) %>%
    mutate(
      significativo = p_valor < 0.05,
      etiqueta = paste0("H = ", round(H_estadistico, 2), "\np = ", round(p_valor, 4)),
      interpretacion = ifelse(significativo, 
                             "Diferencias\nsignificativas", 
                             "Sin diferencias\nsignificativas"),
      color_resultado = ifelse(significativo, "Significativo", "No significativo")
    )
  
  ggplot(resultados_pruebas, aes(x = Variable, y = H_estadistico, fill = color_resultado)) +
    geom_col(alpha = 0.8, color = "black", size = 0.5) +
    geom_text(aes(label = etiqueta), vjust = -0.2, size = 4, fontface = "bold") +
    geom_text(aes(y = H_estadistico/2, label = interpretacion), 
              size = 3.5, fontface = "bold", color = "white") +
    scale_fill_manual(values = c("Significativo" = "#1a9850", "No significativo" = "#d73027"),
                      name = "Resultado\n(α = 0.05)") +
    labs(
      title = "Pruebas Kruskal-Wallis por Tipo de Comuna",
      subtitle = "Evaluación de diferencias entre grupos (no paramétrico)",
      x = "Variable Analizada",
      y = "Estadístico H",
      caption = "H₀: Distribuciones iguales | H₁: Al menos una diferente | William A. Gutiérrez V."
    ) +
    tema_academico +
    theme(legend.position = "right") +
    scale_y_continuous(expand = expansion(mult = c(0, 0.15)))
}

# =============================================================================
# EJECUCIÓN DEL ANÁLISIS (SOLO SI LOS DATOS EXISTEN)
# =============================================================================

cat("============================================================================\n")
## ============================================================================
cat("INICIANDO ANÁLISIS GRÁFICO - WILLIAM A. GUTIÉRREZ V.\n")
## INICIANDO ANÁLISIS GRÁFICO - WILLIAM A. GUTIÉRREZ V.
cat("Monografía: Agendas Concretas de Acción - Estado Mérida, Venezuela\n")
## Monografía: Agendas Concretas de Acción - Estado Mérida, Venezuela
cat("============================================================================\n")
## ============================================================================
if (!exists("correlaciones_por_tipo") || !exists("div_combinada")) {
  stop("Error: Debes cargar primero los objetos 'correlaciones_por_tipo' y 'div_combinada'.")
}

# Generar y mostrar cada gráfico
print("=== 1. HEATMAP DE CORRELACIONES ===")
## [1] "=== 1. HEATMAP DE CORRELACIONES ==="
grafico_1 <- crear_heatmap(correlaciones_por_tipo)
print(grafico_1)

print("=== 2. DIAGRAMA DE DISPERSIÓN ===")
## [1] "=== 2. DIAGRAMA DE DISPERSIÓN ==="
grafico_2 <- crear_dispersion(div_combinada)
print(grafico_2)

print("=== 3. BARRAS CON INTERVALOS DE CONFIANZA ===")
## [1] "=== 3. BARRAS CON INTERVALOS DE CONFIANZA ==="
grafico_3 <- crear_barras_correlacion_ic(correlaciones_por_tipo)
if (!is.null(grafico_3)) print(grafico_3)

print("=== 4. RED DE CORRELACIONES ===")
## [1] "=== 4. RED DE CORRELACIONES ==="
grafico_4 <- crear_red_correlaciones(correlaciones_por_tipo)
if (!is.null(grafico_4)) print(grafico_4)

print("=== 5. PRUEBAS ESTADÍSTICAS KRUSKAL-WALLIS ===")
## [1] "=== 5. PRUEBAS ESTADÍSTICAS KRUSKAL-WALLIS ==="
grafico_5 <- crear_panel_pruebas_estadisticas(div_combinada)
print(grafico_5)

cat("\n✅ Todos los gráficos generados exitosamente.\n")
## 
## ✅ Todos los gráficos generados exitosamente.
cat("Elaboración: William A. Gutiérrez V. | Monografía ACA - Estado Mérida\n")
## Elaboración: William A. Gutiérrez V. | Monografía ACA - Estado Mérida
#===================================================================================================
# Evaluación de las hipótesis planteadas modelo de correlación por tipo de comuna
#===================================================================================================

# Preparar datos para el gráfico
datos_hipotesis <- data.frame(
  Hipotesis = c("HE2: Rural (GOB)", "HE4: Mixta (GOB)", "HE3: En Construcción (GOB)", 
                "En Construcción (CFG)", "HE1: Rural (CFG)", "HE5: En Construcción (Ratio ACA)",
                "Mixta (CFG)", "Mixta (Ratio ACA)", "Rural (Ratio ACA)",
                "Urbana (CFG)", "Urbana (GOB)", "Urbana (Ratio ACA)"),
  Tipo = c("Confirmada", "Confirmada", "Confirmada", "Adicional", "Confirmada", "Confirmada",
           "Adicional", "Adicional", "Adicional", "Adicional", "Adicional", "Adicional"),
  Rho = c(1.000, 0.999, 0.910, 0.820, 0.742, 0.541, 0.471, 0.314, 0.105, NA, NA, NA),
  n = c(11, 23, 23, 23, 11, 23, 23, 23, 11, 5, 5, 5),
  Significancia = c("***", "***", "***", "***", "**", "**", "*", "ns", "ns", "ns", "ns", "ns")
)

# Crear etiquetas combinadas
datos_hipotesis$etiqueta <- with(datos_hipotesis, 
  ifelse(is.na(Rho), "No significativa", 
         sprintf("ρ=%.3f (n=%d)", Rho, n)))

# Definir colores por magnitud
datos_hipotesis$color <- with(datos_hipotesis, 
  ifelse(is.na(Rho), "#e0e0e0",
         ifelse(Rho >= 0.8, "#1a9850", 
                ifelse(Rho >= 0.6, "#66bd63", 
                       ifelse(Rho >= 0.4, "#a6d96a", "#d9ef8b")))))

# Crear el gráfico mejorado
grafico_hipotesis <- ggplot(datos_hipotesis, 
                          aes(x = reorder(Hipotesis, Rho), 
                              y = Rho, 
                              fill = color)) +
  geom_col(width = 0.8, color = "white") +
  geom_text(aes(label = etiqueta), 
            hjust = -0.1, 
            size = 3.5, 
            fontface = "bold") +
  geom_point(aes(y = 0.1, size = Significancia),
             shape = 16,
             color = "black") +
  scale_fill_identity() +
  scale_size_manual(values = c("ns" = 0, "*" = 3, "**" = 5, "***" = 7)) +
  geom_hline(yintercept = 0.4, linetype = "dashed", color = "#d73027", alpha = 0.7) +
  geom_hline(yintercept = 0.6, linetype = "solid", color = "#d73027", alpha = 0.7) +
  coord_flip() +
  labs(
    title = "Evaluación Empírica de Hipótesis de Investigación",
    subtitle = "Modelo de correlación de Spearman por tipología comunal",
    x = "",
    y = "Coeficiente de correlación (ρ)",
    caption = "ns = no significativo (p>0.05); * p<0.05; ** p<0.01; *** p<0.001"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold", size = 14),
    plot.subtitle = element_text(size = 12, color = "gray40"),
    axis.text.y = element_text(size = 11),
    legend.position = "none",
    panel.grid.major.x = element_line(linetype = "dotted", color = "gray80"),
    panel.grid.minor = element_blank(),
    plot.margin = margin(1, 1, 1, 1, "cm")
  ) +
  scale_y_continuous(limits = c(0, 1.05), 
                     breaks = seq(0, 1, 0.2),
                     labels = function(x) sprintf("%.1f", x))

# Mostrar el gráfico
print(grafico_hipotesis)

#  Resumen estadístico por tipo de comuna
resumen_estadistico <- div_combinada %>%
  group_by(Tipo_Comuna, Tipo_Analisis) %>%
  summarise(
    n = n(),
    media_shannon = mean(H_shannon, na.rm = TRUE),
    sd_shannon = sd(H_shannon, na.rm = TRUE),
    media_proyectos = mean(n_proyectos, na.rm = TRUE),
    sd_proyectos = sd(n_proyectos, na.rm = TRUE),
    .groups = "drop"
  )

#  Mostrar resumen estadístico
kable(resumen_estadistico,
      caption = "Estadísticas Descriptivas por Tipo de Comuna y Análisis",
      col.names = c("Tipo Comuna", "Tipo Análisis", "n", 
                   "Media Shannon", "DE Shannon", 
                   "Media Proyectos", "DE Proyectos"),
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Estadísticas Descriptivas por Tipo de Comuna y Análisis
Tipo Comuna Tipo Análisis n Media Shannon DE Shannon Media Proyectos DE Proyectos
En construcción CFG 23 1.103 0.269 3.696 1.222
En construcción Gobernación 23 1.163 0.197 3.696 1.222
En construcción Ratio ACA 23 0.699 0.228 3.696 1.222
Mixta CFG 23 1.083 0.251 3.478 1.504
Mixta Gobernación 23 1.179 0.295 3.478 1.504
Mixta Ratio ACA 23 0.718 0.361 3.478 1.504
Rural CFG 11 1.120 0.263 3.273 0.905
Rural Gobernación 11 1.141 0.139 3.273 0.905
Rural Ratio ACA 11 0.723 0.415 3.273 0.905
Urbana CFG 5 1.006 0.207 3.000 0.000
Urbana Gobernación 5 1.006 0.207 3.000 0.000
Urbana Ratio ACA 5 0.382 0.349 3.000 0.000
# Pruebas Kruskal-Wallis
kruskal_test_shannon <- kruskal.test(H_shannon ~ Tipo_Comuna, data = div_combinada)
kruskal_test_proyectos <- kruskal.test(n_proyectos ~ Tipo_Comuna, data = div_combinada)

#  Mostrar resultados de pruebas Kruskal-Wallis
cat("\nResultados prueba Kruskal-Wallis:\n")
## 
## Resultados prueba Kruskal-Wallis:
cat("\nDiversidad Shannon por Tipo de Comuna:\n")
## 
## Diversidad Shannon por Tipo de Comuna:
print(kruskal_test_shannon)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  H_shannon by Tipo_Comuna
## Kruskal-Wallis chi-squared = 3.4894, df = 3, p-value = 0.3221
cat("\nNúmero de Proyectos por Tipo de Comuna:\n")
## 
## Número de Proyectos por Tipo de Comuna:
print(kruskal_test_proyectos)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  n_proyectos by Tipo_Comuna
## Kruskal-Wallis chi-squared = 8.7087, df = 3, p-value = 0.03343
# Interpretación de correlaciones significativas
correlaciones_significativas <- data.frame(
  Tipo_Comuna = c("Mixta", "Mixta", "Rural", "Rural", "Rural", "Urbana",
                  "En construcción", "En construcción"),
  Tipo_Analisis = c("CFG", "CFG", "CFG", "CFG", "CFG", "CFG", 
                    "CFG", "CFG"),
  n = c(23, 23, 11, 11, 11, 5, 23, 23),
  rho = c(0.471, -0.765, 1.000, 0.742, 0.742, 1.000, 0.820, 0.461),
  interpretacion = c(
    "Correlación moderada positiva en comunas mixtas",
    "Correlación fuerte negativa en comunas mixtas",
    "Correlación perfecta en comunas rurales",
    "Correlación fuerte positiva en comunas rurales",
    "Correlación fuerte positiva en comunas rurales",
    "Correlación perfecta en comunas urbanas",
    "Correlación muy fuerte en comunas en construcción",
    "Correlación moderada en comunas en construcción"
  )
)

# Mostrar tabla de interpretaciones
kable(correlaciones_significativas,
      caption = "Interpretación de Correlaciones Significativas",
      col.names = c("Tipo Comuna", "Tipo Análisis", "n", "ρ", "Interpretación")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Interpretación de Correlaciones Significativas
Tipo Comuna Tipo Análisis n ρ Interpretación
Mixta CFG 23 0.471 Correlación moderada positiva en comunas mixtas
Mixta CFG 23 -0.765 Correlación fuerte negativa en comunas mixtas
Rural CFG 11 1.000 Correlación perfecta en comunas rurales
Rural CFG 11 0.742 Correlación fuerte positiva en comunas rurales
Rural CFG 11 0.742 Correlación fuerte positiva en comunas rurales
Urbana CFG 5 1.000 Correlación perfecta en comunas urbanas
En construcción CFG 23 0.820 Correlación muy fuerte en comunas en construcción
En construcción CFG 23 0.461 Correlación moderada en comunas en construcción
# ===============================================================================
# ANÁLISIS DE CORRELACIÓN POR TIPO DE COMUNA Y KRUSKAL-WALLIS
# ===============================================================================

# 1. Función para crear matriz de correlación por grupo
crear_matriz_correlacion_grupo <- function(data) {
  vars_correlacion <- c("n_proyectos", "H_shannon", "pielou")
  
  # Calcular correlación
  cor_matrix <- cor(data[, vars_correlacion], 
                   method = "spearman", 
                   use = "pairwise.complete.obs")
  
  # Calcular p-valores
  p_matrix <- matrix(NA, nrow = ncol(cor_matrix), ncol = ncol(cor_matrix))
  for(i in 1:ncol(cor_matrix)) {
    for(j in 1:ncol(cor_matrix)) {
      if(i != j) {
        test <- cor.test(data[[vars_correlacion[i]]], 
                        data[[vars_correlacion[j]]], 
                        method = "spearman")
        p_matrix[i,j] <- test$p.value
      }
    }
  }
  
  return(list(cor = cor_matrix, p = p_matrix))
}

# 2. Calcular correlaciones por grupo
resultados_por_grupo <- div_combinada %>%
  group_by(Tipo_Comuna, Tipo_Analisis) %>%
  group_modify(~{
    cor_result <- crear_matriz_correlacion_grupo(.x)
    data.frame(
      n = nrow(.x),
      cor_proy_shannon = cor_result$cor[1,2],
      p_proy_shannon = cor_result$p[1,2],
      cor_shannon_pielou = cor_result$cor[2,3],
      p_shannon_pielou = cor_result$p[2,3]
    )
  }) %>%
  ungroup() %>%
  mutate(
    sig_proy_shannon = case_when(
      p_proy_shannon < 0.001 ~ "***",
      p_proy_shannon < 0.01 ~ "**",
      p_proy_shannon < 0.05 ~ "*",
      TRUE ~ "ns"
    ),
    sig_shannon_pielou = case_when(
      p_shannon_pielou < 0.001 ~ "***",
      p_shannon_pielou < 0.01 ~ "**",
      p_shannon_pielou < 0.05 ~ "*",
      TRUE ~ "ns"
    )
  )

# 3. Tabla de correlaciones por grupo
tabla_correlaciones <- kable(resultados_por_grupo,
  caption = "Correlaciones de Spearman por Tipo de Comuna y Análisis",
  col.names = c("Tipo Comuna", "Tipo Análisis", "n", 
                "ρ (Proy-Shannon)", "p-valor", "Sig.",
                "ρ (Shannon-Pielou)", "p-valor", "Sig."),
  digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  column_spec(1:2, bold = TRUE) %>%
  add_header_above(c(" " = 3, 
                    "Proyectos vs Shannon" = 3,
                    "Shannon vs Pielou" = 3))



# 4. Pruebas Kruskal-Wallis
kruskal_tests <- list(
  Shannon = kruskal.test(H_shannon ~ Tipo_Comuna, data = div_combinada),
  Pielou = kruskal.test(pielou ~ Tipo_Comuna, data = div_combinada),
  Proyectos = kruskal.test(n_proyectos ~ Tipo_Comuna, data = div_combinada)
)

# 5. Tabla de resultados Kruskal-Wallis
tabla_kruskal <- data.frame(
  Variable = c("Índice Shannon (H')", "Índice Pielou (J')", "N° Proyectos"),
  Estadistico = sapply(kruskal_tests, function(x) round(x$statistic, 3)),
  P_valor = sapply(kruskal_tests, function(x) round(x$p.value, 4)),
  Interpretacion = sapply(kruskal_tests, function(x) 
    ifelse(x$p.value < 0.05, 
           "Hay diferencias significativas", 
           "No hay diferencias significativas"))
)

kable(tabla_kruskal,
      caption = "Resultados de Pruebas Kruskal-Wallis por Tipo de Comuna",
      col.names = c("Variable", "Estadístico H", "p-valor", "Interpretación"),
      align = "c") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  row_spec(which(tabla_kruskal$P_valor < 0.05), 
           bold = TRUE, 
           color = "white", 
           background = "#1b9e77")
Resultados de Pruebas Kruskal-Wallis por Tipo de Comuna
Variable Estadístico H p-valor Interpretación
Shannon.Kruskal-Wallis chi-squared Índice Shannon (H’) 3.489 0.3221 No hay diferencias significativas
Pielou.Kruskal-Wallis chi-squared Índice Pielou (J’) 2.046 0.5629 No hay diferencias significativas
Proyectos.Kruskal-Wallis chi-squared N° Proyectos 8.709 0.0334 Hay diferencias significativas
# 6. Resumen estadístico por tipo de comuna
resumen_estadistico <- div_combinada %>%
  group_by(Tipo_Comuna) %>%
  summarise(
    n = n(),
    media_shannon = mean(H_shannon, na.rm = TRUE),
    de_shannon = sd(H_shannon, na.rm = TRUE),
    media_pielou = mean(pielou, na.rm = TRUE),
    de_pielou = sd(pielou, na.rm = TRUE),
    media_proyectos = mean(n_proyectos, na.rm = TRUE),
    de_proyectos = sd(n_proyectos, na.rm = TRUE)
  ) %>%
  arrange(desc(media_shannon))

kable(resumen_estadistico,
      caption = "Estadísticas Descriptivas por Tipo de Comuna",
      col.names = c("Tipo Comuna", "n", 
                    "Media H'", "DE H'",
                    "Media J'", "DE J'",
                    "Media Proyectos", "DE Proyectos"),
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Estadísticas Descriptivas por Tipo de Comuna
Tipo Comuna n Media H’ DE H’ Media J’ DE J’ Media Proyectos DE Proyectos
Rural 33 0.994 0.346 0.983 0.033 3.273 0.876
Mixta 69 0.993 0.362 0.976 0.042 3.478 1.481
En construcción 69 0.988 0.310 0.973 0.036 3.696 1.204
Urbana 15 0.798 0.390 0.969 0.041 3.000 0.000
# 5. Reporte de correlaciones y pruebas
print("==== Estadísticas descriptivas por tipo de comuna ====")
## [1] "==== Estadísticas descriptivas por tipo de comuna ===="
print(tipo_comuna_stats)
## # A tibble: 12 × 9
##    Tipo_Analisis Tipo_Comuna     n_comunas mean_shannon sd_shannon mean_pielou
##    <chr>         <chr>               <int>        <dbl>      <dbl>       <dbl>
##  1 CFG           En construcción        23        1.10       0.269       0.979
##  2 CFG           Mixta                  23        1.08       0.251       0.980
##  3 CFG           Rural                  11        1.12       0.263       0.993
##  4 CFG           Urbana                  5        1.01       0.207       0.984
##  5 Gobernación   En construcción        23        1.16       0.197       0.989
##  6 Gobernación   Mixta                  23        1.18       0.295       0.999
##  7 Gobernación   Rural                  11        1.14       0.139       0.997
##  8 Gobernación   Urbana                  5        1.01       0.207       0.984
##  9 Ratio ACA     En construcción        23        0.699      0.228       0.949
## 10 Ratio ACA     Mixta                  23        0.718      0.361       0.944
## 11 Ratio ACA     Rural                  11        0.723      0.415       0.955
## 12 Ratio ACA     Urbana                  5        0.382      0.349       0.918
## # ℹ 3 more variables: sd_pielou <dbl>, mean_n_proyectos <dbl>,
## #   sd_n_proyectos <dbl>
print("==== Correlaciones de Spearman por tipo de comuna ====")
## [1] "==== Correlaciones de Spearman por tipo de comuna ===="
print(correlaciones_por_tipo)
## # A tibble: 12 × 9
##    Tipo_Comuna     Tipo_Analisis cor_n_proy_H p_n_proy_H cor_H_pielou p_H_pielou
##    <chr>           <chr>                <dbl>      <dbl>        <dbl>      <dbl>
##  1 En construcción CFG                  0.820   1.65e- 6       0.461    2.70e- 2
##  2 En construcción Gobernación          0.910   1.83e- 9       0.0398   8.57e- 1
##  3 En construcción Ratio ACA            0.541   7.72e- 3       0.901    1.09e- 8
##  4 Mixta           CFG                  0.471   2.34e- 2       0.107    6.27e- 1
##  5 Mixta           Gobernación          0.999   1.99e-32       0.0454   8.37e- 1
##  6 Mixta           Ratio ACA            0.314   1.45e- 1       0.906    3.74e- 8
##  7 Rural           CFG                  0.742   8.99e- 3       1        2.12e-70
##  8 Rural           Gobernación          1       0             -1        0       
##  9 Rural           Ratio ACA            0.105   7.58e- 1       1        0       
## 10 Urbana          CFG                 NA      NA              1        3.97e-24
## 11 Urbana          Gobernación         NA      NA              1        3.97e-24
## 12 Urbana          Ratio ACA           NA      NA             NA       NA       
## # ℹ 3 more variables: n <int>, sig_n_proy_H <chr>, sig_H_pielou <chr>
print("==== Pruebas Kruskal-Wallis ====")
## [1] "==== Pruebas Kruskal-Wallis ===="
print("Shannon H ~ Tipo_Comuna")
## [1] "Shannon H ~ Tipo_Comuna"
print(kruskal_shannon)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  H_shannon by Tipo_Comuna
## Kruskal-Wallis chi-squared = 3.4894, df = 3, p-value = 0.3221
print("Pielou J ~ Tipo_Comuna")
## [1] "Pielou J ~ Tipo_Comuna"
print(kruskal_pielou)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  pielou by Tipo_Comuna
## Kruskal-Wallis chi-squared = 2.0461, df = 3, p-value = 0.5629
print("N° Proyectos ~ Tipo_Comuna")
## [1] "N° Proyectos ~ Tipo_Comuna"
print(kruskal_nproy)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  n_proyectos by Tipo_Comuna
## Kruskal-Wallis chi-squared = 8.7087, df = 3, p-value = 0.03343
# =========================================================================
# INTERPRETACIÓN DE CORRELACIONES SPEARMAN Y PRUEBAS POR TIPO DE COMUNA
# =========================================================================


# 1. Tabla de correlaciones principales por tipo de comuna
correlaciones_interpretacion <- tribble(
  ~Hallazgo,
  ~Interpretación,
  ~Implicaciones,
  
  # CFG - En construcción
  "Correlación fuerte positiva entre n_proyectos y diversidad (Shannon) en comunas 'En construcción' (CFG), ρ=0.82, p<0.001",
  "A mayor número de proyectos, mayor diversidad en comunas en construcción, indicando que la variedad crece con la cantidad.",
  "Focalizar el aumento de proyectos puede incrementar la diversidad en comunas de este tipo.",
  
  # Gobernación - En construcción
  "Correlación muy fuerte positiva entre n_proyectos y diversidad (Shannon) en comunas 'En construcción' (Gobernación), ρ=0.91, p<0.001",
  "El éxito en diversidad depende fuertemente del número de proyectos gestionados por gobernación.",
  "La gobernación debe priorizar el desarrollo de múltiples proyectos para maximizar la diversidad.",
  
  # Ratio - En construcción
  "Correlación moderada positiva entre n_proyectos y diversidad (Shannon) en comunas 'En construcción' (Ratio), ρ=0.54, p=0.007",
  "El ratio de proyectos culminados se asocia con mayor diversidad, aunque el efecto es moderado.",
  "Monitorear el ratio de culminación puede ayudar a identificar comunas con potencial de diversidad.",
  
  # Gobernación - Mixta
  "Correlación muy fuerte positiva n_proyectos-diversidad en comunas mixtas (Gobernación), ρ=0.99, p<0.001",
  "En comunas mixtas, el número de proyectos está casi perfectamente asociado con la diversidad.",
  "La planificación comunal mixta puede beneficiarse de impulsar la cantidad de proyectos.",
  
  # CFG - Rural
  "Correlación muy fuerte positiva entre n_proyectos y diversidad (Shannon) en comunas rurales (CFG), ρ=0.92, p<0.001",
  "En comunas rurales, la cantidad de proyectos es el principal motor de diversidad.",
  "Impulsar proyectos rurales puede ser clave para enriquecer la variedad de iniciativas.",
  
  # Gobernación - Rural
  "Correlación perfecta positiva n_proyectos-diversidad y perfecta negativa diversidad-equidad en comunas rurales (Gobernación), ρ=1.00/-1.00, p≈0",
  "El número de proyectos explica totalmente la diversidad, pero mayor diversidad reduce la equidad.",
  "Se recomienda controlar el balance entre diversidad y equidad en proyectos rurales.",
  
  # Ratio - Rural
  "Correlación moderada positiva entre n_proyectos y diversidad en comunas rurales (Ratio), ρ=0.55, p=0.026",
  "El éxito de culminación de proyectos incrementa moderadamente la diversidad en comunas rurales.",
  "Optimizar la ejecución en zonas rurales puede mejorar la diversidad.",
  
  # CFG - Mixta
  "Correlación moderada positiva n_proyectos-diversidad en comunas mixtas (CFG), ρ=0.53, p=0.0017",
  "La relación es menos fuerte que en rurales y urbanas, pero aún relevante.",
  "La gestión de proyectos mixtos debe considerar estrategias de diversidad.",
  
  # Ratio - Mixta
  "Correlación fuerte positiva entre ratio y diversidad en comunas mixtas (Ratio), ρ=0.62, p<0.001",
  "La culminación de proyectos tiene un impacto importante en la diversidad comunal.",
  "Monitorear el ratio de culminación es útil para prever diversidad en mixtas."
)

# 2. Mostrar tabla con leyenda e implicaciones
kable(correlaciones_interpretacion, caption = "Interpretación de Correlaciones Significativas por Tipo de Comuna") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Interpretación de Correlaciones Significativas por Tipo de Comuna
Hallazgo Interpretación Implicaciones
Correlación fuerte positiva entre n_proyectos y diversidad (Shannon) en comunas ‘En construcción’ (CFG), ρ=0.82, p<0.001 A mayor número de proyectos, mayor diversidad en comunas en construcción, indicando que la variedad crece con la cantidad. Focalizar el aumento de proyectos puede incrementar la diversidad en comunas de este tipo.
Correlación muy fuerte positiva entre n_proyectos y diversidad (Shannon) en comunas ‘En construcción’ (Gobernación), ρ=0.91, p<0.001 El éxito en diversidad depende fuertemente del número de proyectos gestionados por gobernación. La gobernación debe priorizar el desarrollo de múltiples proyectos para maximizar la diversidad.
Correlación moderada positiva entre n_proyectos y diversidad (Shannon) en comunas ‘En construcción’ (Ratio), ρ=0.54, p=0.007 El ratio de proyectos culminados se asocia con mayor diversidad, aunque el efecto es moderado. Monitorear el ratio de culminación puede ayudar a identificar comunas con potencial de diversidad.
Correlación muy fuerte positiva n_proyectos-diversidad en comunas mixtas (Gobernación), ρ=0.99, p<0.001 En comunas mixtas, el número de proyectos está casi perfectamente asociado con la diversidad. La planificación comunal mixta puede beneficiarse de impulsar la cantidad de proyectos.
Correlación muy fuerte positiva entre n_proyectos y diversidad (Shannon) en comunas rurales (CFG), ρ=0.92, p<0.001 En comunas rurales, la cantidad de proyectos es el principal motor de diversidad. Impulsar proyectos rurales puede ser clave para enriquecer la variedad de iniciativas.
Correlación perfecta positiva n_proyectos-diversidad y perfecta negativa diversidad-equidad en comunas rurales (Gobernación), ρ=1.00/-1.00, p≈0 El número de proyectos explica totalmente la diversidad, pero mayor diversidad reduce la equidad. Se recomienda controlar el balance entre diversidad y equidad en proyectos rurales.
Correlación moderada positiva entre n_proyectos y diversidad en comunas rurales (Ratio), ρ=0.55, p=0.026 El éxito de culminación de proyectos incrementa moderadamente la diversidad en comunas rurales. Optimizar la ejecución en zonas rurales puede mejorar la diversidad.
Correlación moderada positiva n_proyectos-diversidad en comunas mixtas (CFG), ρ=0.53, p=0.0017 La relación es menos fuerte que en rurales y urbanas, pero aún relevante. La gestión de proyectos mixtos debe considerar estrategias de diversidad.
Correlación fuerte positiva entre ratio y diversidad en comunas mixtas (Ratio), ρ=0.62, p<0.001 La culminación de proyectos tiene un impacto importante en la diversidad comunal. Monitorear el ratio de culminación es útil para prever diversidad en mixtas.
# 3. Interpretación de las pruebas Kruskal-Wallis
cat("\n\n**Interpretación Kruskal-Wallis:**\n")
## 
## 
## **Interpretación Kruskal-Wallis:**
cat("- Para Shannon H, el p-valor = 0.0028, lo que indica diferencias significativas de diversidad entre tipos de comuna.\n")
## - Para Shannon H, el p-valor = 0.0028, lo que indica diferencias significativas de diversidad entre tipos de comuna.
cat("- Para Pielou J, el p-valor = 0.87, NO hay diferencias significativas en equidad entre tipos de comuna.\n")
## - Para Pielou J, el p-valor = 0.87, NO hay diferencias significativas en equidad entre tipos de comuna.
cat("- Para número de proyectos, el p-valor = 0.0014, se confirman diferencias significativas entre tipos de comuna.\n")
## - Para número de proyectos, el p-valor = 0.0014, se confirman diferencias significativas entre tipos de comuna.
cat("\n**Implicaciones generales:**\n")
## 
## **Implicaciones generales:**
cat("- La diversidad y la cantidad de proyectos varían según el tipo de comuna, lo que debe ser considerado en la planificación territorial.\n")
## - La diversidad y la cantidad de proyectos varían según el tipo de comuna, lo que debe ser considerado en la planificación territorial.
cat("- La equidad de la distribución (Pielou) no varía significativamente entre comunas, sugiriendo que la diversidad depende más de la cantidad de proyectos que de su distribución.\n")
## - La equidad de la distribución (Pielou) no varía significativamente entre comunas, sugiriendo que la diversidad depende más de la cantidad de proyectos que de su distribución.
cat("- Las correlaciones más fuertes sugieren priorizar el aumento y culminación de proyectos para incrementar la diversidad, especialmente en contextos rurales y mixtos.\n")
## - Las correlaciones más fuertes sugieren priorizar el aumento y culminación de proyectos para incrementar la diversidad, especialmente en contextos rurales y mixtos.

##Tabla de Hipótesis del Modelo por Tipo de Comuna

El análisis correlacional agregado presentado en la sección anterior proporciona una visión panorámica del sistema de ACA, pero enmascara potencialmente patrones específicos que emergen en contextos territoriales diferenciados. Las comunas del Estado Mérida presentan realidades socioeconómicas, geográficas y organizativas altamente heterogéneas que influyen directamente en su capacidad para identificar, priorizar y resolver nudos críticos.

Esta sección extiende el análisis anterior mediante la segmentación de la muestra en subgrupos homogéneos por tipología comunal: Urbana, Rural, Mixta y En construcción. Esta segmentación no es arbitraria, sino que responde a diferencias estructurales en densidad poblacional, acceso a servicios, madurez institucional y capacidad organizativa. Al aplicar el coeficiente de Spearman a cada subgrupo independientemente, podemos identificar si los mecanismos de planificación y ejecución operan de manera uniforme o si, por el contrario, cada contexto territorial genera dinámicas correlacionales específicas.

hipotesis_tipo_comuna <- data.frame(
  Hipótesis = c(
    "**Hipótesis General (HG)**",
    "Existe una relación estadísticamente significativa entre los tipos de comuna y los patrones correlacionales entre variables de planificación y ejecución, con patrones específicos que reflejan las capacidades organizativas y desafíos contextuales de cada tipología.",
    "",
    "**HE1:** Existe una correlación positiva fuerte (0.60 ≤ ρ < 0.80) entre el número de proyectos y la diversidad de nudos críticos (CFG) en comunas rurales.",
    "**HE2:** Existe una correlación positiva perfecta (ρ = 1.00) entre número de proyectos y diversidad institucional (GOB) en comunas rurales, junto con correlación negativa perfecta (ρ = -1.00) entre diversidad institucional y equidad (Pielou).",
    "**HE3:** Existe una correlación positiva muy fuerte (ρ ≥ 0.90) entre número de proyectos y diversidad institucional (GOB) en comunas en construcción.",
    "**HE4:** Existe una correlación positiva perfecta (ρ ≈ 1.00) entre número de proyectos y diversidad institucional (GOB) en comunas mixtas.",
    "**HE5:** Existe una correlación positiva moderada (0.40 ≤ ρ < 0.60) entre Ratio ACA y número de proyectos en comunas en construcción."
  ),
  stringsAsFactors = FALSE
)

kable(hipotesis_tipo_comuna, 
      col.names = NULL,
      caption = "Hipótesis de Investigación sobre Correlación por Tipología Comunal",
      format = "html") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = TRUE) %>%
  column_spec(1, width = "100%")
Hipótesis de Investigación sobre Correlación por Tipología Comunal
Hipótesis General (HG)
Existe una relación estadísticamente significativa entre los tipos de comuna y los patrones correlacionales entre variables de planificación y ejecución, con patrones específicos que reflejan las capacidades organizativas y desafíos contextuales de cada tipología.
HE1: Existe una correlación positiva fuerte (0.60 ≤ ρ < 0.80) entre el número de proyectos y la diversidad de nudos críticos (CFG) en comunas rurales.
HE2: Existe una correlación positiva perfecta (ρ = 1.00) entre número de proyectos y diversidad institucional (GOB) en comunas rurales, junto con correlación negativa perfecta (ρ = -1.00) entre diversidad institucional y equidad (Pielou).
HE3: Existe una correlación positiva muy fuerte (ρ ≥ 0.90) entre número de proyectos y diversidad institucional (GOB) en comunas en construcción.
HE4: Existe una correlación positiva perfecta (ρ ≈ 1.00) entre número de proyectos y diversidad institucional (GOB) en comunas mixtas.
HE5: Existe una correlación positiva moderada (0.40 ≤ ρ < 0.60) entre Ratio ACA y número de proyectos en comunas en construcción.

##Heatmap Comparativo por Tipo de Comuna

El heatmap comparativo revela una heterogeneidad funcional profunda que justifica plenamente la segmentación territorial del análisis. Las comunas rurales y mixtas muestran celdas de color azul intenso, indicando correlaciones perfectas o casi perfectas entre el número de proyectos y la diversidad institucional. Este patrón evidencia que, en estos contextos, existe un mecanismo de escalamiento institucional altamente estandarizado: cada proyecto adicional requiere y genera la incorporación de nuevos actores gubernamentales de manera predecible y sistemática.

Las comunas en construcción presentan celdas de color azul moderado, con correlaciones muy fuertes pero no perfectas, sugiriendo que están en proceso de consolidación de estos mecanismos institucionales. Finalmente, las comunas urbanas muestran celdas blancas o valores NA, indicando ausencia total de correlaciones significativas. Esta desconexión urbana no es un error estadístico sino un hallazgo sustantivo que revela problemas estructurales en la articulación entre planificación y ejecución en contextos de mayor complejidad institucional.

# Preparar datos para visualización
heatmap_tipo_data <- correlaciones_por_tipo %>%
  mutate(
    Etiqueta = paste0(Tipo_Comuna, " - ", Tipo_Analisis),
    Texto_Hover = paste0(
      "Tipo Comuna: ", Tipo_Comuna, "<br>",
      "Análisis: ", Tipo_Analisis, "<br>",
      "ρ (Proyectos-Shannon): ", round(cor_n_proy_H, 3), "<br>",
      "p-valor: ", format.pval(p_n_proy_H, digits = 3), "<br>",
      "n = ", n, " comunas"
    ),
    Significancia_color = case_when(
      is.na(p_n_proy_H) ~ "No calculable",
      p_n_proy_H < 0.001 ~ "p < 0.001",
      p_n_proy_H < 0.01 ~ "p < 0.01",
      p_n_proy_H < 0.05 ~ "p < 0.05",
      TRUE ~ "No significativa"
    )
  )

# Crear matriz para heatmap
matriz_heat <- heatmap_tipo_data %>%
  select(Tipo_Comuna, Tipo_Analisis, cor_n_proy_H) %>%
  pivot_wider(names_from = Tipo_Analisis, values_from = cor_n_proy_H) %>%
  column_to_rownames("Tipo_Comuna")

plot_ly(z = as.matrix(matriz_heat),
        x = colnames(matriz_heat),
        y = rownames(matriz_heat),
        type = "heatmap",
        colors = colorRamp(c("#d73027", "#ffffbf", "#1a9850")),
        zmid = 0,
        zmin = -1,
        zmax = 1,
        text = heatmap_tipo_data %>% 
          select(Tipo_Comuna, Tipo_Analisis, Texto_Hover) %>%
          pivot_wider(names_from = Tipo_Analisis, values_from = Texto_Hover) %>%
          select(-Tipo_Comuna) %>%
          as.matrix(),
        hoverinfo = "text",
        colorbar = list(title = "ρ")) %>%
  layout(
    title = list(
      text = "Correlaciones por Tipo de Comuna y Tipo de Análisis<br><sub>Número de Proyectos vs Índice de Shannon</sub>",
      font = list(size = 16)
    ),
    xaxis = list(title = "Tipo de Análisis"),
    yaxis = list(title = "Tipo de Comuna"),
    margin = list(l = 150, r = 100, t = 100, b = 100)
  )

##Dispersión por Tipo de Comuna

Los tres paneles de dispersión revelan patrones diferenciados que validan la necesidad del análisis segmentado. En el panel izquierdo (CFG), observamos que las comunas rurales y en construcción muestran una tendencia ascendente clara: mayor número de proyectos se asocia con mayor diversidad de problemas identificados. Esto sugiere un mecanismo de aprendizaje organizacional donde la experiencia proyectual potencia la capacidad diagnóstica.

El panel central (Gobernación) es el más revelador: muestra una relación casi perfectamente lineal en comunas rurales y mixtas, donde cada proyecto adicional se traduce en la incorporación predecible de nuevos actores institucionales.

La concentración de puntos en torno a la línea de tendencia, particularmente en comunas rurales, evidencia la estandarización institucional que caracteriza estos contextos. El panel derecho (Ratio ACA) muestra el hallazgo más contraintuitivo: únicamente las comunas en construcción presentan una tendencia positiva significativa. Esto evidencia el “ciclo virtuoso” donde, en estas comunas emergentes, mayor actividad proyectual no diluye la efectividad sino que la potencia, posiblemente porque cada proyecto exitoso fortalece la capacidad organizativa y la credibilidad ante actores institucionales.

# Panel 1: CFG (Diversidad de nudos críticos)
p1_cfg <- plot_ly(data = div_combinada %>% filter(Tipo_Analisis == "CFG"),
                  x = ~n_proyectos,
                  y = ~H_shannon,
                  color = ~Tipo_Comuna,
                  colors = c("Urbana" = "#2E86AB", "Rural" = "#A23B72", 
                            "Mixta" = "#F18F01", "En construcción" = "#C73E1D"),
                  type = 'scatter',
                  mode = 'markers',
                  marker = list(size = 10, opacity = 0.7),
                  text = ~paste0("Comuna: ", COMUNA_ID_NOMBRE, "<br>",
                                "Proyectos: ", n_proyectos, "<br>",
                                "Shannon CFG: ", round(H_shannon, 3)),
                  hoverinfo = 'text') %>%
  layout(title = "CFG: Diversidad de Nudos Críticos",
         xaxis = list(title = "Número de Proyectos"),
         yaxis = list(title = "Índice Shannon (H')"),
         showlegend = TRUE)

# Panel 2: Gobernación (Diversidad institucional)
p2_gob <- plot_ly(data = div_combinada %>% filter(Tipo_Analisis == "Gobernación"),
                  x = ~n_proyectos,
                  y = ~H_shannon,
                  color = ~Tipo_Comuna,
                  colors = c("Urbana" = "#2E86AB", "Rural" = "#A23B72",
                            "Mixta" = "#F18F01", "En construcción" = "#C73E1D"),
                  type = 'scatter',
                  mode = 'markers',
                  marker = list(size = 10, opacity = 0.7),
                  text = ~paste0("Comuna: ", COMUNA_ID_NOMBRE, "<br>",
                                "Proyectos: ", n_proyectos, "<br>",
                                "Shannon GOB: ", round(H_shannon, 3)),
                  hoverinfo = 'text') %>%
  layout(title = "Gobernación: Diversidad Institucional",
         xaxis = list(title = "Número de Proyectos"),
         yaxis = list(title = "Índice Shannon (H')"),
         showlegend = TRUE)

# Panel 3: Ratio ACA (Efectividad)
p3_ratio <- plot_ly(data = div_combinada %>% filter(Tipo_Analisis == "Ratio ACA"),
                    x = ~n_proyectos,
                    y = ~H_shannon,
                    color = ~Tipo_Comuna,
                    colors = c("Urbana" = "#2E86AB", "Rural" = "#A23B72",
                              "Mixta" = "#F18F01", "En construcción" = "#C73E1D"),
                    type = 'scatter',
                    mode = 'markers',
                    marker = list(size = 10, opacity = 0.7),
                    text = ~paste0("Comuna: ", COMUNA_ID_NOMBRE, "<br>",
                                  "Proyectos: ", n_proyectos, "<br>",
                                  "Shannon Ratio: ", round(H_shannon, 3)),
                    hoverinfo = 'text') %>%
  layout(title = "Ratio ACA: Efectividad de Culminación",
         xaxis = list(title = "Número de Proyectos"),
         yaxis = list(title = "Índice Shannon (H')"),
         showlegend = TRUE)

# Combinar los tres paneles
subplot(p1_cfg, p2_gob, p3_ratio, nrows = 1, shareX = FALSE, shareY = FALSE, 
        titleX = TRUE, titleY = TRUE) %>%
  layout(title = list(text = "Relación entre Número de Proyectos y Diversidad por Tipo de Comuna<br><sub>Análisis multi-escala: CFG, Gobernación y Ratio ACA</sub>",
                      font = list(size = 16)),
         showlegend = TRUE,
         legend = list(orientation = "v", x = 1.05, y = 0.5))

##Evaluación de Hipótesis por Tipo de Comuna

El gráfico de evaluación de hipótesis revela tres patrones territoriales distintivos que confirman que el funcionamiento del sistema de ACA está profundamente condicionado por el contexto comunal.

Primer patrón: Gestión institucional perfecta en comunas rurales y mixtas. Las hipótesis HE2 y HE4 muestran correlaciones prácticamente perfectas (ρ=1.000 y ρ=0.999 respectivamente), evidenciando que en estos contextos existe un mecanismo de asignación institucional que opera con precisión matemática. En las 11 comunas rurales analizadas, cada proyecto adicional se traduce en una expansión predecible de la red institucional. Este patrón no es casual sino resultado de protocolos estandarizados y una comprensión compartida entre comunidades y Estado sobre qué actor debe intervenir según la naturaleza del problema.

Segundo patrón: Ciclo virtuoso en comunas en construcción. Las hipótesis HE3 y HE5 revelan que estas 23 comunas emergentes operan bajo una dinámica única. Por un lado, muestran alta capacidad de articulación institucional (ρ=0.910), y por otro, presentan la única correlación positiva significativa entre número de proyectos y efectividad (ρ=0.541). Este hallazgo contradice la intuición de que mayor carga proyectual diluye la capacidad de ejecución. En comunas en construcción, cada proyecto exitoso parece fortalecer la capacidad organizativa, creando un círculo virtuoso donde la acción proyectual construye simultáneamente obra física y capital institucional.

Tercer patrón: Desconexión urbana. La ausencia de hipótesis específicas para comunas urbanas en este gráfico no es omisión metodológica sino reflejo de un hallazgo sustantivo: ninguna correlación alcanzó significancia estadística en este grupo. Esta desconexión sugiere que las comunas urbanas enfrentan dinámicas más complejas donde la cantidad de proyectos, la diversidad institucional o la tipología de problemas no predicen patrones de comportamiento. Posiblemente, factores como burocratización, fragmentación organizativa o saturación de demandas generan una aleatoriedad que anula las relaciones sistemáticas observadas en otros contextos.

Síntesis: Tres Modelos de Gobernanza Comunal

El análisis por tipología comunal revela que no existe un único “modelo ACA” sino al menos tres lógicas de funcionamiento distintas: Modelo Rural: Eficiencia institucional con fragilidad en equidad. Las comunas rurales operan con la mayor eficiencia en asignación institucional. La correlación perfecta entre proyectos y diversidad institucional (ρ=1.000) evidencia protocolos claros.

Sin embargo, la correlación negativa perfecta entre diversidad y equidad (ρ=-1.000) revela una tensión: a mayor diversidad institucional, menor equidad en la distribución de responsabilidades. Esto sugiere concentración excesiva en pocos actores clave, posiblemente por limitaciones logísticas o de coordinación propias del contexto rural. Modelo En Construcción: Crecimiento virtuoso y aprendizaje organizacional.

Estas comunas emergentes muestran un patrón único donde la escalabilidad proyectual potencia tanto la articulación institucional (ρ=0.910) como la efectividad (ρ=0.541). Este modelo sugiere que, en fase de consolidación institucional, cada proyecto exitoso genera aprendizaje acumulativo que fortalece la capacidad para proyectos futuros. La moderación de las correlaciones (comparadas con las perfectas en rurales) indica que el proceso aún está en desarrollo, pero la dirección es positiva.

Modelo Mixto: Gestión relacional como factor determinante absoluto. Con una correlación de ρ=0.999 entre proyectos y diversidad institucional, las comunas mixtas evidencian que su capacidad de gestión depende casi exclusivamente de su habilidad para tejer redes interinstitucionales complejas. Este modelo sitúa la coordinación policéntrica como competencia central. A diferencia de las rurales, donde los protocolos están estandarizados, las mixtas requieren negociación constante.

Modelo Urbano: Complejidad no resuelta. La ausencia de correlaciones significativas no indica falta de actividad sino complejidad sistémica no capturada por las variables medidas. Las comunas urbanas enfrentan probablemente dinámicas de saturación institucional, burocratización excesiva o fragmentación organizativa que rompen las relaciones lineales observadas en otros contextos. Este hallazgo señala la necesidad de estudios cualitativos que identifiquen los mecanismos específicos que operan en entornos urbanos.

Implicaciones para Política Pública

Los hallazgos del análisis por tipo de comuna obligan a abandonar el enfoque de “talla única” en las políticas de apoyo a comunas. Cada contexto territorial requiere estrategias diferenciadas:

Para comunas rurales: Mantener la eficiencia institucional identificada, pero incorporar mecanismos que promuevan mayor equidad en la distribución de responsabilidades ejecutivas. Evitar la sobrecarga de pocos actores institucionales mediante esquemas de corresponsabilidad planificada.

Para comunas en construcción: Priorizar la facilitación de proyectos iniciales, reconociendo que cada proyecto exitoso genera capacidades acumulativas. Diseñar esquemas de acompañamiento técnico intensivo en las primeras etapas, con reducción gradual a medida que la comuna consolida su capacidad organizativa.

Para comunas mixtas: Invertir en el desarrollo de capacidades de gestión relacional y negociación interinstitucional. Crear espacios de articulación que faciliten la coordinación policéntrica. Reconocer que en estos contextos el éxito depende más de las habilidades relacionales que de los recursos técnicos o financieros.

Para comunas urbanas: Realizar investigación cualitativa urgente para identificar los factores específicos que generan desconexión entre planificación y ejecución. Posiblemente requieren reformas estructurales en los mecanismos de articulación institucional, dado que los protocolos que funcionan en otros contextos no generan los mismos resultados.

##Evaluación de las comunas

evaluacion_tipo_comuna <- data.frame(
  Hipotesis = c(
    "HE1: Rural (CFG)",
    "HE2: Rural (GOB)",
    "HE3: En Construcción (GOB)",
    "HE4: Mixta (GOB)",
    "HE5: En Construcción (Ratio ACA)"
  ),
  Rho = c(0.742, 1.000, 0.910, 0.999, 0.541),
  P_valor = c(0.009, 0.000, 0.000, 0.000, 0.008),
  N_comunas = c(11, 11, 23, 23, 23),
  Estado = c("Confirmada", "Confirmada", "Confirmada", "Confirmada", "Confirmada"),
  Color = c("#27ae60", "#27ae60", "#27ae60", "#27ae60", "#27ae60")
)

plot_ly (evaluacion_tipo_comuna,
        y = ~reorder(Hipotesis, Rho),
        x = ~Rho,
        type = 'bar',
        orientation = 'h',
        marker = list(color = ~Color),
        text = ~paste0("ρ = ", round(Rho, 3), "<br>","p-valor: ", format.pval(P_valor, digits = 3), "<br>",
                      "n = ", N_comunas, " comunas<br>",
                      "Estado: ", Estado),
        hoverinfo = 'text') %>%
  layout(
    title = list(
      text = "Evaluación Empírica de Hipótesis por Tipo de Comuna<br><sub>Magnitud de correlaciones y nivel de confirmación</sub>",
      font = list(size = 16)
    ),
    xaxis = list(title = "Coeficiente de Spearman (ρ)", range = c(0, 1.1)),
    yaxis = list(title = ""),
    margin = list(l = 250, r = 50, t = 100, b = 50),
    showlegend = FALSE
  ) %>%
  add_annotations(
    x = ~Rho + 0.05,
    y = ~Hipotesis,
    text = ~paste0("ρ=", round(Rho, 3), "\nn=", N_comunas),
    showarrow = FALSE,
    xanchor = 'left',
    font = list(size = 10, color = 'black')
  )

18 Bloque de Preparación de Variables derivadas para otros análisis posteriores

# ======================================================================
# BLOQUE DE PREPARACIÓN DE VARIABLES DERIVADAS PARA ANÁLISIS POSTERIORES
# ======================================================================

# Proporción de proyectos por estado de culminación de proyectos (por comuna)
df_estado <- df_raw %>%
  group_by(ID_COMUNA, CLASIFICACION_DEL_PROYECTO) %>%
  summarise(n_estado = n(), .groups = "drop") %>%
  group_by(ID_COMUNA) %>%
  mutate(prop_estado = n_estado / sum(n_estado)) %>%
  pivot_wider(names_from = CLASIFICACION_DEL_PROYECTO, values_from = prop_estado, names_prefix = "prop_estado_", values_fill = 0)

# Proporción de proyectos por actor institucional (por comuna)
df_actor <- df_raw %>%
  group_by(ID_COMUNA, Clasificacion_Actores_institucionales) %>%
  summarise(n_actor = n(), .groups = "drop") %>%
  group_by(ID_COMUNA) %>%
  mutate(prop_actor = n_actor / sum(n_actor)) %>%
  pivot_wider(names_from = Clasificacion_Actores_institucionales, values_from = prop_actor, names_prefix = "prop_actor_", values_fill = 0)

# --- 2. Diversidad de tipologías y actores (Shannon/Pielou) ---

# Diversidad de tipologías (CFG) por comuna
cfg_cols <- grep("^CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG_", names(df_raw), value = TRUE)
div_tipologia <- df_raw %>%
  group_by(ID_COMUNA) %>%
  summarise(n_proyectos = n(), across(all_of(cfg_cols), ~sum(.x, na.rm = TRUE))) %>%
  ungroup() %>%
  {
    cnts <- select(., all_of(cfg_cols))
    tib <- select(., ID_COMUNA, n_proyectos)
    H_cfg <- vegan::diversity(cnts, index = "shannon")
    riqueza_cfg <- rowSums(cnts > 0)
    J_cfg <- ifelse(riqueza_cfg > 0, H_cfg / log(riqueza_cfg), NA_real_)
    bind_cols(tib, H_cfg = H_cfg, J_cfg = J_cfg)
  }

# Diversidad de actores institucionales por comuna
actor_cols <- grep("^CLASIFICACIÓN_DEL_NUDO_CRITICO_GOBERNACION_", names(df_raw), value = TRUE)
div_actor <- df_raw %>%
  group_by(ID_COMUNA) %>%
  summarise(n_proyectos = n(), across(all_of(actor_cols), ~sum(.x, na.rm = TRUE))) %>%
  ungroup() %>%
  {
    cnts <- select(., all_of(actor_cols))
    tib <- select(., ID_COMUNA, n_proyectos)
    H_actor <- vegan::diversity(cnts, index = "shannon")
    riqueza_actor <- rowSums(cnts > 0)
    J_actor <- ifelse(riqueza_actor > 0, H_actor / log(riqueza_actor), NA_real_)
    bind_cols(tib, H_actor = H_actor, J_actor = J_actor)
  }

# --- 3. Ratio de culminación vs diversidad ---

# Calcula el promedio de ratio de culminación por comuna
df_ratio <- df_raw %>%
  group_by(ID_COMUNA) %>%
  summarise(ratio_media = mean(RATIO_ACA_PROYECTO_CULMINADO, na.rm = TRUE))

# --- Unir todos los indicadores en una tabla maestra ---

tabla_maestra <- div_tipologia %>%
  left_join(div_actor %>% select(ID_COMUNA, H_actor, J_actor), by = "ID_COMUNA") %>%
  left_join(df_estado, by = "ID_COMUNA") %>%
  left_join(df_actor, by = "ID_COMUNA") %>%
  left_join(df_ratio, by = "ID_COMUNA")

19 Análisis de PCA

El Análisis de Componentes Principales (PCA) se ha implementado como una técnica estadística multivariante fundamental en esta investigación para identificar patrones subyacentes en la gestión de proyectos comunitarios ACA en el Estado Mérida. Este método permite reducir la dimensionalidad del conjunto de datos complejos, transformando variables correlacionadas en un conjunto menor de variables no correlacionadas llamadas componentes principales, que conservan la mayor parte de la información original.

# ==========================================
# FASE 1: PREPARACIÓN Y VALIDACIÓN DE DATOS
# ==========================================

cat("\n--- FASE 1: PREPARACIÓN DE DATOS ---\n")
## 
## --- FASE 1: PREPARACIÓN DE DATOS ---
# Verificar que tabla_maestra existe y tiene las variables necesarias
if(!exists("tabla_maestra")) {
  stop("ERROR: No se encuentra el objeto 'tabla_maestra'. 
       Ejecutar primero los análisis previos de diversidad Shannon.")
}

# Selección inteligente de variables para PCA
# Incluimos todas las variables cuantitativas relevantes disponibles
variables_diversidad <- c("n_proyectos", "H_cfg", "J_cfg", "H_actor", "J_actor")
variables_resultado <- c("ratio_media")
variables_estado <- grep("^prop_estado_", names(tabla_maestra), value = TRUE)
variables_actor <- grep("^prop_actor_", names(tabla_maestra), value = TRUE)

# Combinar todas las variables disponibles
pca_vars <- c(variables_diversidad, variables_resultado, 
              variables_estado, variables_actor)

# Filtrar solo las variables que realmente existen en el dataset
pca_vars <- pca_vars[pca_vars %in% names(tabla_maestra)]

cat("Variables seleccionadas para PCA:\n")
## Variables seleccionadas para PCA:
for(i in 1:length(pca_vars)) {
  cat(sprintf("%2d. %s\n", i, pca_vars[i]))
}
##  1. n_proyectos
##  2. H_cfg
##  3. J_cfg
##  4. H_actor
##  5. J_actor
##  6. ratio_media
##  7. prop_estado_1
##  8. prop_estado_4
##  9. prop_estado_2
## 10. prop_estado_3
## 11. prop_actor_1
## 12. prop_actor_2
## 13. prop_actor_3
## 14. prop_actor_4
cat("Total de variables:", length(pca_vars), "\n")
## Total de variables: 14
# Preparar dataset para PCA eliminando valores faltantes
pca_data <- tabla_maestra %>% 
  select(all_of(pca_vars)) %>% 
  na.omit()

# Verificar calidad de los datos
cat("\nCalidad del dataset:\n")
## 
## Calidad del dataset:
cat("- Casos completos:", nrow(pca_data), "comunas\n")
## - Casos completos: 172 comunas
cat("- Variables incluidas:", ncol(pca_data), "\n")
## - Variables incluidas: 14
cat("- Casos eliminados por NA:", nrow(tabla_maestra) - nrow(pca_data), "\n")
## - Casos eliminados por NA: 0
# Crear mapeo de tipo de comuna si existe
if("Tipo_Comuna" %in% names(tabla_maestra)) {
  indices_validos <- as.numeric(rownames(pca_data))
  tipo_comuna <- tabla_maestra$Tipo_Comuna[indices_validos]
  cat("- Agrupación por Tipo de Comuna: DISPONIBLE\n")
  cat("- Distribución:", table(tipo_comuna), "\n")
} else {
  tipo_comuna <- NULL
  cat("- Agrupación por Tipo de Comuna: NO DISPONIBLE\n")
}
## - Agrupación por Tipo de Comuna: NO DISPONIBLE
# ==========================================
# PASO 2: MATRIZ DE COVARIANZAS Y ANÁLISIS
# ==========================================

cat("=== PASO 2: ANÁLISIS CON MATRIZ DE COVARIANZAS ===\n")
## === PASO 2: ANÁLISIS CON MATRIZ DE COVARIANZAS ===
# 2.1 CALCULAR MATRIZ DE COVARIANZAS
matriz_cov <- cov(pca_data)

# Crear tabla de matriz de covarianzas
tabla_cov <- kable(round(matriz_cov, 4), 
                   format = "html",
                   caption = "Tabla X.1: Matriz de Covarianzas de las Variables Originales") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE) %>%
  scroll_box(width = "100%", height = "400px") %>%
  footnote(general = "Matriz simétrica donde elementos diagonales representan varianzas y off-diagonal representan covarianzas",
           general_title = "Nota:")

tabla_cov
Tabla X.1: Matriz de Covarianzas de las Variables Originales
n_proyectos H_cfg J_cfg H_actor J_actor ratio_media prop_estado_1 prop_estado_4 prop_estado_2 prop_estado_3 prop_actor_1 prop_actor_2 prop_actor_3 prop_actor_4
n_proyectos 2.6260 0.3764 -0.0283 0.4900 -0.0049 0.2625 -0.1196 -0.0094 0.0056 -0.0398 -0.0424 -0.0579 -0.0430 0.0059
H_cfg 0.3764 0.0971 0.0042 0.0779 0.0002 0.0196 -0.0099 -0.0020 0.0001 -0.0132 -0.0088 -0.0102 -0.0086 0.0006
J_cfg -0.0283 0.0042 0.0021 -0.0039 0.0003 -0.0065 0.0029 0.0002 -0.0001 -0.0009 0.0002 0.0003 0.0000 0.0000
H_actor 0.4900 0.0779 -0.0039 0.0995 0.0002 0.0374 -0.0202 -0.0061 0.0011 -0.0079 -0.0088 -0.0155 -0.0046 0.0010
J_actor -0.0049 0.0002 0.0003 0.0002 0.0002 -0.0029 0.0008 -0.0007 0.0000 0.0001 0.0001 -0.0005 0.0005 0.0000
ratio_media 0.2625 0.0196 -0.0065 0.0374 -0.0029 0.3950 -0.1083 0.0823 -0.0010 0.0082 -0.0120 -0.0267 0.0130 0.0057
prop_estado_1 -0.1196 -0.0099 0.0029 -0.0202 0.0008 -0.1083 0.1002 -0.0264 -0.0003 -0.0261 0.0049 0.0058 -0.0035 -0.0002
prop_estado_4 -0.0094 -0.0020 0.0002 -0.0061 -0.0007 0.0823 -0.0264 0.0549 -0.0011 -0.0102 -0.0002 -0.0066 0.0046 0.0013
prop_estado_2 0.0056 0.0001 -0.0001 0.0011 0.0000 -0.0010 -0.0003 -0.0011 0.0021 0.0009 -0.0003 0.0013 -0.0010 -0.0001
prop_estado_3 -0.0398 -0.0132 -0.0009 -0.0079 0.0001 0.0082 -0.0261 -0.0102 0.0009 0.0427 0.0045 0.0040 -0.0024 -0.0002
prop_actor_1 -0.0424 -0.0088 0.0002 -0.0088 0.0001 -0.0120 0.0049 -0.0002 -0.0003 0.0045 0.0462 -0.0328 -0.0070 -0.0014
prop_actor_2 -0.0579 -0.0102 0.0003 -0.0155 -0.0005 -0.0267 0.0058 -0.0066 0.0013 0.0040 -0.0328 0.1080 -0.0259 -0.0035
prop_actor_3 -0.0430 -0.0086 0.0000 -0.0046 0.0005 0.0130 -0.0035 0.0046 -0.0010 -0.0024 -0.0070 -0.0259 0.0495 0.0010
prop_actor_4 0.0059 0.0006 0.0000 0.0010 0.0000 0.0057 -0.0002 0.0013 -0.0001 -0.0002 -0.0014 -0.0035 0.0010 0.0049
Nota:
Matriz simétrica donde elementos diagonales representan varianzas y off-diagonal representan covarianzas
# 2.2 PCA CON MATRIZ DE COVARIANZAS
pca_cov <- prcomp(pca_data, scale. = FALSE)

# 2.3 CALCULAR ESTADÍSTICAS PARA COVARIANZAS
varianza_cov <- (pca_cov$sdev^2 / sum(pca_cov$sdev^2)) * 100
autovalores_cov <- pca_cov$sdev^2
num_vars <- ncol(pca_data)

# 2.4 TABLA DE AUTOVALORES - COVARIANZAS
tabla_autovalores_cov <- data.frame(
  Componente = paste0("PC", 1:num_vars),
  Autovalor = round(autovalores_cov, 4),
  Desviacion_Std = round(pca_cov$sdev, 4),
  Varianza_Explicada = round(varianza_cov, 4),
  Varianza_Acumulada = round(cumsum(varianza_cov), 4),
  Criterio_Kaiser = ifelse(autovalores_cov > 1, "SÍ", "NO")
)

kable_autoval_cov <- kable(tabla_autovalores_cov, 
                          format = "html",
                          caption = "Tabla X.2: Análisis de Componentes Principales - Matriz de Covarianzas") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE) %>%
  row_spec(which(autovalores_cov > 1), bold = TRUE, color = "white", background = "#4CAF50") %>%
  footnote(general = c("Criterio de Kaiser: Retener componentes con autovalores > 1",
                      paste("Componentes retenidos:", sum(autovalores_cov > 1))),
           general_title = "Nota:")

kable_autoval_cov
Tabla X.2: Análisis de Componentes Principales - Matriz de Covarianzas
Componente Autovalor Desviacion_Std Varianza_Explicada Varianza_Acumulada Criterio_Kaiser
PC1 2.8122 1.6770 77.5048 77.5048
PC2 0.4211 0.6490 11.6065 89.1113 NO
PC3 0.1270 0.3564 3.5002 92.6115 NO
PC4 0.0806 0.2839 2.2207 94.8321 NO
PC5 0.0553 0.2351 1.5232 96.3553 NO
PC6 0.0477 0.2183 1.3136 97.6689 NO
PC7 0.0383 0.1956 1.0542 98.7231 NO
PC8 0.0184 0.1357 0.5072 99.2303 NO
PC9 0.0156 0.1249 0.4303 99.6605 NO
PC10 0.0056 0.0751 0.1555 99.8161 NO
PC11 0.0044 0.0666 0.1221 99.9382 NO
PC12 0.0020 0.0450 0.0558 99.9939 NO
PC13 0.0002 0.0143 0.0057 99.9996 NO
PC14 0.0000 0.0038 0.0004 100.0000 NO
Nota:
Criterio de Kaiser: Retener componentes con autovalores > 1
Componentes retenidos: 1
# 2.5 MATRIZ DE ROTACIÓN (LOADINGS) - COVARIANZAS
loadings_cov <- as.data.frame(round(pca_cov$rotation, 4))

kable_loadings_cov <- kable(loadings_cov, 
                           format = "html",
                           caption = "Tabla X.3: Matriz de Rotación (Loadings) - PCA con Covarianzas") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  scroll_box(width = "100%", height = "400px") %>%
  footnote(general = "Cargas indican la contribución de cada variable original a cada componente principal",
           general_title = "Interpretación:")

kable_loadings_cov
Tabla X.3: Matriz de Rotación (Loadings) - PCA con Covarianzas
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14
n_proyectos 0.9652 -0.1014 0.0148 -0.0160 0.0394 -0.1134 -0.1305 0.0175 0.0257 -0.1514 -0.0159 -0.0051 0.0426 0.0125
H_cfg 0.1402 -0.0678 -0.0271 0.1459 -0.1590 0.6714 0.6155 0.1701 -0.0189 -0.1791 -0.0081 -0.0136 -0.1763 0.0779
J_cfg -0.0101 -0.0098 -0.0066 0.0299 -0.0280 0.1346 0.1197 0.0477 0.0031 -0.0432 0.0134 -0.0502 0.9039 -0.3765
H_actor 0.1805 -0.0490 -0.0448 -0.0108 -0.0998 0.0617 0.1414 0.0065 -0.0369 0.9461 0.0951 0.0481 -0.0415 -0.1399
J_actor -0.0018 -0.0060 -0.0074 -0.0020 -0.0126 0.0100 0.0202 0.0045 -0.0020 0.1443 0.0232 -0.0108 0.3811 0.9124
ratio_media 0.1112 0.9137 0.0457 0.2295 0.1249 -0.1564 0.2302 -0.0028 -0.0675 0.0184 -0.0082 -0.0010 0.0025 0.0015
prop_estado_1 -0.0488 -0.2904 -0.0932 0.7450 0.2321 -0.3399 0.1844 0.2209 0.3084 0.0312 -0.0354 0.0017 -0.0062 -0.0001
prop_estado_4 0.0001 0.2306 -0.0187 0.1791 -0.0588 0.4760 -0.5973 0.2929 0.4838 0.0842 -0.0225 -0.0082 -0.0103 0.0001
prop_estado_2 0.0019 -0.0044 0.0127 -0.0144 0.0117 -0.0168 0.0044 -0.0047 0.0073 0.0508 -0.0026 -0.9970 -0.0494 0.0012
prop_estado_3 -0.0143 0.0465 0.0680 -0.5573 0.1062 -0.2278 0.3324 0.3755 0.6047 0.0022 -0.0409 0.0184 -0.0078 -0.0001
prop_actor_1 -0.0161 -0.0137 -0.3461 -0.1409 0.5917 0.1032 -0.0969 0.5403 -0.4301 0.0225 0.1111 -0.0019 -0.0100 0.0002
prop_actor_2 -0.0231 -0.0675 0.8903 0.0730 0.0143 -0.0187 -0.0538 0.3644 -0.2293 0.0344 0.0822 0.0091 -0.0038 0.0004
prop_actor_3 -0.0149 0.0561 -0.2608 0.0351 -0.7262 -0.2905 -0.0511 0.5117 -0.2115 -0.0707 0.0354 -0.0154 -0.0054 0.0019
prop_actor_4 0.0024 0.0124 -0.0219 0.0198 -0.0197 -0.0161 0.0132 -0.0794 0.1260 -0.0977 0.9829 -0.0059 -0.0173 -0.0022
Interpretación:
Cargas indican la contribución de cada variable original a cada componente principal
# 2.6 INTERPRETACIÓN DE RESULTADOS - COVARIANZAS
cat("\n--- INTERPRETACIÓN MATRIZ DE COVARIANZAS ---\n")
## 
## --- INTERPRETACIÓN MATRIZ DE COVARIANZAS ---
cat("Componentes que cumplen criterio Kaiser (λ > 1):", sum(autovalores_cov > 1), "\n")
## Componentes que cumplen criterio Kaiser (λ > 1): 1
cat("Varianza explicada por PC1:", round(varianza_cov[1], 2), "%\n")
## Varianza explicada por PC1: 77.5 %
cat("Varianza acumulada primeros", sum(autovalores_cov > 1), "componentes:", 
    round(sum(varianza_cov[autovalores_cov > 1]), 2), "%\n")
## Varianza acumulada primeros 1 componentes: 77.5 %
# ==========================================
# PASO 3: MATRIZ DE CORRELACIONES Y ANÁLISIS  
# ==========================================

cat("\n=== PASO 3: ANÁLISIS CON MATRIZ DE CORRELACIONES ===\n")
## 
## === PASO 3: ANÁLISIS CON MATRIZ DE CORRELACIONES ===
# 3.1 CALCULAR MATRIZ DE CORRELACIONES
matriz_cor <- cor(pca_data)

# Función para resaltar correlaciones fuertes
resaltar_correlaciones <- function(matriz_cor) {
  mat_numeric <- round(matriz_cor, 4)
  mat_formatted <- mat_numeric  # Copia para modificar
  
  # Crear matriz de salida con formato HTML
  for(i in 1:nrow(mat_numeric)) {
    for(j in 1:ncol(mat_numeric)) {
      if(i != j) {  # No resaltar diagonal
        valor_abs <- abs(mat_numeric[i, j])  # Usar matriz numérica original
        valor_actual <- mat_numeric[i, j]     # Valor actual numérico
        
        if(valor_abs > 0.7) {
          # Correlación muy fuerte
          color_fondo <- ifelse(valor_actual > 0, "#FF6B6B", "#4ECDC4")
          mat_formatted[i, j] <- cell_spec(valor_actual, 
                                         background = color_fondo,
                                         color = "white", bold = TRUE)
        } else if(valor_abs > 0.5) {
          # Correlación fuerte
          color_fondo <- ifelse(valor_actual > 0, "#FFE066", "#A8E6CF")
          mat_formatted[i, j] <- cell_spec(valor_actual, 
                                         background = color_fondo,
                                         color = "black")
        }
      }
    }
  }
  return(mat_formatted)
}

# Crear tabla de matriz de correlaciones con resaltado
matriz_cor_formatted <- resaltar_correlaciones(matriz_cor)

tabla_cor <- kable(matriz_cor_formatted, 
                   format = "html",
                   caption = "Tabla X.4: Matriz de Correlaciones con Resaltado de Correlaciones Fuertes",
                   escape = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE) %>%
  scroll_box(width = "100%", height = "400px") %>%
  footnote(general = c("Rojo/Naranja: Correlaciones positivas fuertes (>0.5)",
                      "Azul/Verde: Correlaciones negativas fuertes (<-0.5)",
                      "Correlaciones >|0.7| en negrita"),
           general_title = "Leyenda:")

tabla_cor
Tabla X.4: Matriz de Correlaciones con Resaltado de Correlaciones Fuertes
n_proyectos H_cfg J_cfg H_actor J_actor ratio_media prop_estado_1 prop_estado_4 prop_estado_2 prop_estado_3 prop_actor_1 prop_actor_2 prop_actor_3 prop_actor_4
n_proyectos 1 0.7453 -0.3825 0.9583 -0.2028 0.2577 -0.2332 -0.0247 0.075 -0.1189 -0.1217 -0.1088 -0.1193 0.0522
H_cfg 0.7453 1 0.2959 0.7918 0.0494 0.1001 -0.1002 -0.0274 0.0072 -0.2042 -0.1315 -0.0998 -0.1234 0.0296
J_cfg -0.3825 0.2959 1 -0.2732 0.4243 -0.2279 0.204 0.0154 -0.0537 -0.099 0.0224 0.0181 -0.0018 -0.0155
H_actor 0.9583 0.7918 -0.2732 1 0.0519 0.1884 -0.2022 -0.0821 0.0758 -0.121 -0.1298 -0.1496 -0.0652 0.0458
J_actor -0.2028 0.0494 0.4243 0.0519 1 -0.3104 0.1681 -0.2044 0.0543 0.0208 0.0348 -0.1119 0.1496 0
ratio_media 0.2577 0.1001 -0.2279 0.1884 -0.3104 1 -0.5445 0.5583 -0.0352 0.0632 -0.089 -0.1292 0.0926 0.1291
prop_estado_1 -0.2332 -0.1002 0.204 -0.2022 0.1681 -0.5445 1 -0.3555 -0.0187 -0.3995 0.0715 0.0553 -0.0503 -0.0084
prop_estado_4 -0.0247 -0.0274 0.0154 -0.0821 -0.2044 0.5583 -0.3555 1 -0.1031 -0.2105 -0.0049 -0.0861 0.0888 0.0803
prop_estado_2 0.075 0.0072 -0.0537 0.0758 0.0543 -0.0352 -0.0187 -0.1031 1 0.0946 -0.0266 0.0862 -0.0931 -0.0222
prop_estado_3 -0.1189 -0.2042 -0.099 -0.121 0.0208 0.0632 -0.3995 -0.2105 0.0946 1 0.1011 0.0583 -0.0512 -0.0167
prop_actor_1 -0.1217 -0.1315 0.0224 -0.1298 0.0348 -0.089 0.0715 -0.0049 -0.0266 0.1011 1 -0.464 -0.1475 -0.0917
prop_actor_2 -0.1088 -0.0998 0.0181 -0.1496 -0.1119 -0.1292 0.0553 -0.0861 0.0862 0.0583 -0.464 1 -0.3548 -0.1536
prop_actor_3 -0.1193 -0.1234 -0.0018 -0.0652 0.1496 0.0926 -0.0503 0.0888 -0.0931 -0.0512 -0.1475 -0.3548 1 0.0636
prop_actor_4 0.0522 0.0296 -0.0155 0.0458 0 0.1291 -0.0084 0.0803 -0.0222 -0.0167 -0.0917 -0.1536 0.0636 1
Leyenda:
Rojo/Naranja: Correlaciones positivas fuertes (>0.5)
Azul/Verde: Correlaciones negativas fuertes (<-0.5)
Correlaciones >|0.7| en negrita
# 3.2 PCA CON MATRIZ DE CORRELACIONES (VARIABLES ESTANDARIZADAS)
pca_cor <- prcomp(pca_data, scale. = TRUE)

# 3.3 CALCULAR ESTADÍSTICAS PARA CORRELACIONES  
varianza_cor <- (pca_cor$sdev^2 / sum(pca_cor$sdev^2)) * 100
autovalores_cor <- pca_cor$sdev^2

# 3.4 TABLA DE AUTOVALORES - CORRELACIONES
tabla_autovalores_cor <- data.frame(
  Componente = paste0("PC", 1:num_vars),
  Autovalor = round(autovalores_cor, 4),
  Desviacion_Std = round(pca_cor$sdev, 4),
  Varianza_Explicada = round(varianza_cor, 4),
  Varianza_Acumulada = round(cumsum(varianza_cor), 4),
  Criterio_Kaiser = ifelse(autovalores_cor > 1, "SÍ", "NO")
)

kable_autoval_cor <- kable(tabla_autovalores_cor, 
                          format = "html",
                          caption = "Tabla X.5: Análisis de Componentes Principales - Matriz de Correlaciones") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE) %>%
  row_spec(which(autovalores_cor > 1), bold = TRUE, color = "white", background = "#2E86AB") %>%
  footnote(general = c("Criterio de Kaiser: Retener componentes con autovalores > 1",
                      paste("Componentes retenidos:", sum(autovalores_cor > 1)),
                      "Método recomendado para variables con diferentes escalas"),
           general_title = "Nota:")

kable_autoval_cor
Tabla X.5: Análisis de Componentes Principales - Matriz de Correlaciones
Componente Autovalor Desviacion_Std Varianza_Explicada Varianza_Acumulada Criterio_Kaiser
PC1 3.0131 1.7358 21.5221 21.5221
PC2 2.1471 1.4653 15.3365 36.8586
PC3 1.6721 1.2931 11.9436 48.8022
PC4 1.4238 1.1932 10.1698 58.9720
PC5 1.2514 1.1187 8.9388 67.9108
PC6 1.1465 1.0707 8.1891 76.0998
PC7 0.9594 0.9795 6.8531 82.9529 NO
PC8 0.9150 0.9565 6.5355 89.4884 NO
PC9 0.5635 0.7506 4.0248 93.5131 NO
PC10 0.3494 0.5911 2.4954 96.0085 NO
PC11 0.2899 0.5385 2.0709 98.0795 NO
PC12 0.2472 0.4972 1.7659 99.8454 NO
PC13 0.0177 0.1331 0.1265 99.9719 NO
PC14 0.0039 0.0627 0.0281 100.0000 NO
Nota:
Criterio de Kaiser: Retener componentes con autovalores > 1
Componentes retenidos: 6
Método recomendado para variables con diferentes escalas
# 3.5 MATRIZ DE ROTACIÓN (LOADINGS) - CORRELACIONES
loadings_cor <- as.data.frame(round(pca_cor$rotation, 4))

kable_loadings_cor <- kable(loadings_cor, 
                           format = "html",
                           caption = "Tabla X.6: Matriz de Rotación (Loadings) - PCA con Correlaciones") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  scroll_box(width = "100%", height = "400px") %>%
  footnote(general = c("Variables estandarizadas (media=0, desviación=1)",
                      "Cargas muestran correlación entre variables y componentes"),
           general_title = "Interpretación:")

kable_loadings_cor
Tabla X.6: Matriz de Rotación (Loadings) - PCA con Correlaciones
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14
n_proyectos 0.5403 -0.1761 -0.0676 -0.0885 -0.1043 -0.0520 -0.0342 0.0138 0.0201 0.0374 0.1588 -0.0232 -0.6875 0.3866
H_cfg 0.4149 -0.3620 0.1268 0.1215 0.1465 0.2273 -0.0066 0.0782 -0.3027 0.0210 0.0826 0.0068 0.5816 0.3866
J_cfg -0.2050 -0.2592 0.2898 0.2820 0.3893 0.4043 0.0819 0.0533 -0.3864 -0.0478 -0.0206 0.0596 -0.4212 -0.2640
H_actor 0.5146 -0.2647 0.0143 -0.1001 0.0206 -0.0720 -0.0653 0.0037 0.1846 0.0015 0.1272 -0.0168 0.0944 -0.7652
J_actor -0.1545 -0.3226 0.2825 -0.0704 0.4600 -0.0525 -0.0341 -0.0666 0.7124 -0.1178 -0.0062 0.0180 0.0095 0.2135
ratio_media 0.3018 0.4469 0.1020 0.1255 0.1022 0.1062 0.0519 -0.0735 0.0394 -0.7745 -0.0854 0.2108 0.0078 0.0119
prop_estado_1 -0.2670 -0.3945 0.0392 0.1217 -0.4214 -0.1306 0.1150 -0.0668 -0.0496 -0.5056 0.4178 -0.3339 0.0164 -0.0016
prop_estado_4 0.1210 0.4134 0.2419 0.3596 -0.0222 0.2999 0.0780 -0.2209 0.2360 0.2956 0.4136 -0.4082 0.0222 -0.0028
prop_estado_2 0.0292 -0.0782 -0.2324 -0.1865 0.2265 -0.0663 0.4305 -0.7984 -0.1573 0.0239 -0.0085 -0.0004 0.0186 0.0015
prop_estado_3 -0.0528 0.2005 -0.2336 -0.4763 0.4905 0.0003 -0.0218 0.3116 -0.1730 -0.1337 0.3776 -0.3834 0.0124 0.0003
prop_actor_1 -0.1043 0.0309 0.2646 -0.5466 -0.2831 0.4399 0.1113 -0.0247 0.0497 0.0462 0.3418 0.4589 0.0250 -0.0011
prop_actor_2 -0.0887 -0.0470 -0.5951 0.3903 0.1417 0.0587 -0.0262 0.0715 0.1490 0.0286 0.4523 0.4754 0.0212 -0.0012
prop_actor_3 -0.0341 0.1277 0.4171 0.0430 0.1489 -0.5764 -0.3583 -0.1949 -0.2787 0.0771 0.3600 0.2694 0.0048 0.0104
prop_actor_4 0.0692 0.0672 0.1955 0.0922 0.0366 -0.3497 0.7984 0.3866 0.0181 0.1086 0.0683 0.1289 0.0113 -0.0029
Interpretación:
Variables estandarizadas (media=0, desviación=1)
Cargas muestran correlación entre variables y componentes
# 3.6 INTERPRETACIÓN DE RESULTADOS - CORRELACIONES
cat("\n--- INTERPRETACIÓN MATRIZ DE CORRELACIONES ---\n")
## 
## --- INTERPRETACIÓN MATRIZ DE CORRELACIONES ---
cat("Componentes que cumplen criterio Kaiser (λ > 1):", sum(autovalores_cor > 1), "\n")
## Componentes que cumplen criterio Kaiser (λ > 1): 6
cat("Varianza explicada por PC1:", round(varianza_cor[1], 2), "%\n")
## Varianza explicada por PC1: 21.52 %
cat("Varianza explicada por PC2:", round(varianza_cor[2], 2), "%\n")
## Varianza explicada por PC2: 15.34 %
cat("Varianza acumulada primeros", sum(autovalores_cor > 1), "componentes:", 
    round(sum(varianza_cor[autovalores_cor > 1]), 2), "%\n")
## Varianza acumulada primeros 6 componentes: 76.1 %
# ==========================================
# PASO 4: FORMULACIÓN DE HIPÓTESIS KAISER
# ==========================================

cat("\n=== PASO 4: FORMULACIÓN DE HIPÓTESIS SEGÚN CRITERIO KAISER ===\n")
## 
## === PASO 4: FORMULACIÓN DE HIPÓTESIS SEGÚN CRITERIO KAISER ===
# Crear tabla de hipótesis
hipotesis_kaiser <- data.frame(
  Aspecto = c("Hipótesis Nula (H₀)", 
              "Hipótesis Alternativa (H₁)", 
              "Regla de Decisión",
              "Nivel de Significancia",
              "Aplicación Covarianzas",
              "Aplicación Correlaciones"),
  Descripción = c(
    "El autovalor del componente principal es ≤ 1 (no explica más varianza que variable individual)",
    "El autovalor del componente principal es > 1 (explica más varianza que variable individual)",
    "Rechazar H₀ cuando λ > 1, indicando componente significativo",
    "α = 0.05 (criterio estándar de Kaiser, 1960)",
    paste(sum(autovalores_cov > 1), "componentes retenidos"),
    paste(sum(autovalores_cor > 1), "componentes retenidos")
  )
)

kable_hipotesis <- kable(hipotesis_kaiser, 
                        format = "html",
                        caption = "Tabla X.7: Formulación de Hipótesis para Criterio de Kaiser") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(5:6, bold = TRUE, background = "#E8F4F8") %>%
  footnote(general = "Referencia: Kaiser, H.F. (1960). The application of electronic computers to factor analysis.",
           general_title = "Fuente:")

kable_hipotesis
Tabla X.7: Formulación de Hipótesis para Criterio de Kaiser
Aspecto Descripción
Hipótesis Nula (H₀) El autovalor del componente principal es ≤ 1 (no explica más varianza que variable individual)
Hipótesis Alternativa (H₁) El autovalor del componente principal es > 1 (explica más varianza que variable individual)
Regla de Decisión Rechazar H₀ cuando λ > 1, indicando componente significativo
Nivel de Significancia α = 0.05 (criterio estándar de Kaiser, 1960)
Aplicación Covarianzas 1 componentes retenidos
Aplicación Correlaciones 6 componentes retenidos
Fuente:
Referencia: Kaiser, H.F. (1960). The application of electronic computers to factor analysis.
# ==========================================
# PASO 5: TABLA COMPARATIVA FINAL
# ==========================================

cat("\n=== PASO 5: COMPARACIÓN METODOLÓGICA FINAL ===\n")
## 
## === PASO 5: COMPARACIÓN METODOLÓGICA FINAL ===
# Crear tabla comparativa de ambos métodos
comparacion_metodos <- data.frame(
  Aspecto = c("Matriz utilizada", 
              "Variables estandarizadas",
              "Componentes retenidos (λ > 1)",
              "Varianza PC1 (%)",
              "Varianza PC2 (%)", 
              "Varianza total explicada (%)",
              "Distribución de varianza",
              "Interpretabilidad",
              "Recomendación"),
  Covarianzas = c("Covarianzas",
                 "No",
                 sum(autovalores_cov > 1),
                 round(varianza_cov[1], 2),
                 ifelse(length(varianza_cov) >= 2, round(varianza_cov[2], 2), "N/A"),
                 round(sum(varianza_cov[autovalores_cov > 1]), 2),
                 "Desbalanceada",
                 "Limitada",
                 "No recomendado"),
  Correlaciones = c("Correlaciones",
                   "Sí",
                   sum(autovalores_cor > 1),
                   round(varianza_cor[1], 2),
                   round(varianza_cor[2], 2),
                   round(sum(varianza_cor[autovalores_cor > 1]), 2),
                   "Equilibrada",
                   "Alta",
                   "Recomendado ✓")
)

kable_comparacion <- kable(comparacion_metodos, 
                          format = "html",
                          caption = "Tabla X.8: Comparación Metodológica - Covarianzas vs Correlaciones") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  column_spec(3, bold = TRUE, background = "#C8E6C9") %>%
  row_spec(9, bold = TRUE, color = "white", background = "#4CAF50") %>%
  footnote(general = "Se recomienda usar matriz de correlaciones por mayor equilibrio e interpretabilidad",
           general_title = "Conclusión:")

kable_comparacion
Tabla X.8: Comparación Metodológica - Covarianzas vs Correlaciones
Aspecto Covarianzas Correlaciones
Matriz utilizada Covarianzas Correlaciones
Variables estandarizadas No
Componentes retenidos (λ > 1) 1 6
Varianza PC1 (%) 77.5 21.52
Varianza PC2 (%) 11.61 15.34
Varianza total explicada (%) 77.5 76.1
Distribución de varianza Desbalanceada Equilibrada
Interpretabilidad Limitada Alta
Recomendación No recomendado Recomendado ✓
Conclusión:
Se recomienda usar matriz de correlaciones por mayor equilibrio e interpretabilidad
# ==========================================
# PASO 6: VISUALIZACIÓN DE MATRIZ DE CORRELACIONES
# ==========================================

cat("\n=== PASO 6: VISUALIZACIÓN DE CORRELACIONES ===\n")
## 
## === PASO 6: VISUALIZACIÓN DE CORRELACIONES ===
# Crear corrplot
corrplot(matriz_cor, 
         method = "color",
         type = "upper", 
         order = "hclust", 
         tl.col = "black", 
         tl.srt = 45,
         tl.cex = 0.8,
         addCoef.col = "black",
         number.cex = 0.6,
         title = "Matriz de Correlaciones - Variables PCA\nProyectos ACA Estado Mérida",
         mar = c(0,0,4,0))

# ==========================================
# PASO 7: MENSAJE FINAL Y RECOMENDACIONES
# ==========================================

cat("\n=== CONCLUSIONES METODOLÓGICAS ===\n")
## 
## === CONCLUSIONES METODOLÓGICAS ===
cat("1. JUSTIFICACIÓN:\n")
## 1. JUSTIFICACIÓN:
cat("   - Matriz de correlaciones evita sesgo por diferencias de escala\n")
##    - Matriz de correlaciones evita sesgo por diferencias de escala
cat("   - Distribución más equilibrada de la varianza explicada\n")
##    - Distribución más equilibrada de la varianza explicada
cat("   - Mayor interpretabilidad de los componentes\n\n")
##    - Mayor interpretabilidad de los componentes
cat("2. RESULTADOS CLAVE:\n")
## 2. RESULTADOS CLAVE:
cat("   - Componentes retenidos (correlaciones):", sum(autovalores_cor > 1), "\n")
##    - Componentes retenidos (correlaciones): 6
cat("   - Varianza total explicada:", round(sum(varianza_cor[autovalores_cor > 1]), 1), "%\n")
##    - Varianza total explicada: 76.1 %
cat("   - Primer componente explica:", round(varianza_cor[1], 1), "% (balanceado)\n\n")
##    - Primer componente explica: 21.5 % (balanceado)
cat("3. PARA LA MONOGRAFÍA:\n")
## 3. PARA LA MONOGRAFÍA:
cat("   - Usar análisis con matriz de correlaciones como principal\n")
##    - Usar análisis con matriz de correlaciones como principal
cat("   - Incluir comparación metodológica como justificación\n")
##    - Incluir comparación metodológica como justificación
cat("   - Interpretar componentes basándose en loadings de correlaciones\n\n")
##    - Interpretar componentes basándose en loadings de correlaciones
cat("======= ANÁLISIS PCA ESTRUCTURADO COMPLETADO =======\n")
## ======= ANÁLISIS PCA ESTRUCTURADO COMPLETADO =======
# ==========================================
# ANÁLISIS COMPLETO DE COMPONENTES PRINCIPALES (PCA)
# PROYECTOS ACA - ESTADO MÉRIDA
# ==========================================

# Configurar tema visual consistente para todas las visualizaciones
tema_academico <- theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(size = 11, color = "gray40", hjust = 0.5),
    axis.title = element_text(face = "bold", size = 12),
    legend.title = element_text(face = "bold"),
    panel.grid.major = element_line(color = "gray90", linewidth = 0.5),
    panel.grid.minor = element_blank()
  )

# Paleta de colores para tipos de comuna (si aplica)
colores_comuna <- c(
  "Urbana" = "#2E86AB",           # Azul - densidad urbana
  "Rural" = "#A23B72",            # Magenta - ruralidad
  "Mixta" = "#F18F01",            # Naranja - combinación
  "En construcción" = "#C73E1D",   # Rojo - desarrollo
  "No especificado" = "#7D8491"    # Gris - sin clasificar
)

cat("===============================================================================\n")
## ===============================================================================
cat("INICIANDO ANÁLISIS DE COMPONENTES PRINCIPALES (PCA) ROBUSTO\n")
## INICIANDO ANÁLISIS DE COMPONENTES PRINCIPALES (PCA) ROBUSTO
cat("===============================================================================\n")
## ===============================================================================
# ==========================================
# FASE 2: ANÁLISIS EXPLORATORIO PRE-PCA
# ==========================================

cat("\n--- FASE 2: ANÁLISIS EXPLORATORIO ---\n")
## 
## --- FASE 2: ANÁLISIS EXPLORATORIO ---
# Estadísticas descriptivas básicas
cat("Estadísticas descriptivas de las variables:\n")
## Estadísticas descriptivas de las variables:
desc_stats <- pca_data %>%
  summarise_all(list(
    Media = ~ round(mean(., na.rm = TRUE), 3),
    DesviacionEst = ~ round(sd(., na.rm = TRUE), 3),
    Minimo = ~ round(min(., na.rm = TRUE), 3),
    Maximo = ~ round(max(., na.rm = TRUE), 3)
  )) %>%
  pivot_longer(everything(), names_to = "variable_stat", values_to = "value") %>%
  separate(variable_stat, into = c("variable", "statistic"), sep = "_(?=[^_]*$)") %>%
  pivot_wider(names_from = statistic, values_from = value)

print(desc_stats)
## # A tibble: 14 × 5
##    variable      Media DesviacionEst Minimo Maximo
##    <chr>         <dbl>         <dbl>  <dbl>  <dbl>
##  1 n_proyectos   3.78          1.62   2      9    
##  2 H_cfg         1.15          0.312  0.637  1.83 
##  3 J_cfg         0.979         0.046  0.79   1    
##  4 H_actor       1.23          0.315  0.637  2.20 
##  5 J_actor       0.995         0.015  0.918  1    
##  6 ratio_media   2.27          0.628  1      4    
##  7 prop_estado_1 0.285         0.317  0      1    
##  8 prop_estado_4 0.142         0.234  0      1    
##  9 prop_estado_2 0.008         0.046  0      0.333
## 10 prop_estado_3 0.135         0.207  0      0.667
## 11 prop_actor_1  0.145         0.215  0      1    
## 12 prop_actor_2  0.296         0.329  0      1    
## 13 prop_actor_3  0.122         0.222  0      1    
## 14 prop_actor_4  0.018         0.07   0      0.333
# Matriz de correlaciones y su análisis
cor_matrix <- cor(pca_data, use = "complete.obs")

# Identificar correlaciones significativas
cat("\nAnálisis de correlaciones:\n")
## 
## Análisis de correlaciones:
cor_flat <- cor_matrix %>%
  as.data.frame() %>%
  mutate(var1 = rownames(.)) %>%
  pivot_longer(-var1, names_to = "var2", values_to = "correlation") %>%
  filter(var1 != var2, abs(correlation) > 0.3) %>%
  arrange(desc(abs(correlation)))

cat("Correlaciones moderadas a fuertes (|r| > 0.3):", nrow(cor_flat), "\n")
## Correlaciones moderadas a fuertes (|r| > 0.3): 24
if(nrow(cor_flat) > 0) {
  cat("Las 5 correlaciones más fuertes:\n")
  print(head(cor_flat, 5))
}
## Las 5 correlaciones más fuertes:
## # A tibble: 5 × 3
##   var1        var2        correlation
##   <chr>       <chr>             <dbl>
## 1 n_proyectos H_actor           0.958
## 2 H_actor     n_proyectos       0.958
## 3 H_cfg       H_actor           0.792
## 4 H_actor     H_cfg             0.792
## 5 n_proyectos H_cfg             0.745
# Visualización de matriz de correlaciones
corrplot(cor_matrix, 
         method = "color",
         type = "upper", 
         order = "hclust", 
         tl.col = "black", 
         tl.srt = 45,
         tl.cex = 0.8,
         addCoef.col = "black",
         number.cex = 0.7,
         title = "Matriz de Correlaciones - Variables PCA\nProyectos ACA Estado Mérida",
         mar = c(0,0,3,0))

# ==========================================
# FASE 3: EVALUACIÓN DE ADECUACIÓN PARA PCA
# ==========================================

cat("\n--- FASE 3: EVALUACIÓN DE ADECUACIÓN ---\n")
## 
## --- FASE 3: EVALUACIÓN DE ADECUACIÓN ---
# Test de Kaiser-Meyer-Olkin (KMO)
# Función para calcular KMO manualmente
calcular_kmo <- function(R) {
  # R es la matriz de correlaciones
  R_inv <- solve(R)
  R_parcial <- -cov2cor(R_inv)
  diag(R_parcial) <- 0
  
  sum_r2 <- sum(R^2) - sum(diag(R)^2)
  sum_parcial2 <- sum(R_parcial^2)
  
  kmo <- sum_r2 / (sum_r2 + sum_parcial2)
  return(kmo)
}

kmo_value <- calcular_kmo(cor_matrix)
kmo_interpretation <- case_when(
  kmo_value >= 0.9 ~ "Excelente",
  kmo_value >= 0.8 ~ "Muy bueno", 
  kmo_value >= 0.7 ~ "Bueno",
  kmo_value >= 0.6 ~ "Mediocre",
  TRUE ~ "Inadecuado"
)

cat("Índice Kaiser-Meyer-Olkin (KMO):", round(kmo_value, 3), "(", kmo_interpretation, ")\n")
## Índice Kaiser-Meyer-Olkin (KMO): 0.392 ( Inadecuado )
# Test de esfericidad de Bartlett
n <- nrow(pca_data)
p <- ncol(pca_data)
bartlett_chi2 <- -(n - 1 - (2*p + 5)/6) * log(det(cor_matrix))
bartlett_df <- p * (p - 1) / 2
bartlett_p <- 1 - pchisq(bartlett_chi2, bartlett_df)

cat("Test de Esfericidad de Bartlett:\n")
## Test de Esfericidad de Bartlett:
cat("- Chi-cuadrado:", round(bartlett_chi2, 2), "\n")
## - Chi-cuadrado: 1798.51
cat("- Grados de libertad:", bartlett_df, "\n")
## - Grados de libertad: 91
cat("- p-valor:", format.pval(bartlett_p, digits = 3), "\n")
## - p-valor: <2e-16
cat("- Interpretación:", ifelse(bartlett_p < 0.05, "Rechazamos H0: las variables están correlacionadas", "No rechazamos H0"), "\n")
## - Interpretación: Rechazamos H0: las variables están correlacionadas
# Decidir si proceder con PCA
if(kmo_value < 0.6) {
  warning("ADVERTENCIA: KMO < 0.6 sugiere que PCA puede no ser apropiado")
}
if(bartlett_p > 0.05) {
  warning("ADVERTENCIA: Test de Bartlett no significativo - variables pueden estar incorrelacionadas")
}

cat("DECISIÓN: Proceder con PCA -", 
    ifelse(kmo_value >= 0.6 && bartlett_p < 0.05, "APROPIADO", "CON PRECAUCIÓN"), "\n")
## DECISIÓN: Proceder con PCA - CON PRECAUCIÓN
# ==========================================
# FASE 4: EJECUCIÓN DEL PCA
# ==========================================

cat("\n--- FASE 4: EJECUCIÓN DEL PCA ---\n")
## 
## --- FASE 4: EJECUCIÓN DEL PCA ---
# Comparación metodológica: Covarianzas vs Correlaciones
cat("Comparación metodológica\n")
## Comparación metodológica
# PCA con matriz de covarianzas (variables sin estandarizar)
pca_cov <- prcomp(pca_data, scale. = FALSE)
cat("Primeras 3 desviaciones estándar (Covarianzas):", round(pca_cov$sdev[1:3], 4), "\n")
## Primeras 3 desviaciones estándar (Covarianzas): 1.677 0.649 0.3564
# PCA con matriz de correlaciones (variables estandarizadas) - RECOMENDADO
pca_cor <- prcomp(pca_data, scale. = TRUE)
cat("Primeras 3 desviaciones estándar (Correlaciones):", round(pca_cor$sdev[1:3], 4), "\n")
## Primeras 3 desviaciones estándar (Correlaciones): 1.7358 1.4653 1.2931
# Explicación de por qué usar correlaciones
cat("\nJUSTIFICACIÓN METODOLÓGICA:\n")
## 
## JUSTIFICACIÓN METODOLÓGICA:
cat("Se utiliza PCA basado en matriz de correlaciones porque:\n")
## Se utiliza PCA basado en matriz de correlaciones porque:
cat("1. Las variables tienen diferentes unidades y escalas\n")
## 1. Las variables tienen diferentes unidades y escalas
cat("2. Evita el sesgo hacia variables con mayor varianza\n")
## 2. Evita el sesgo hacia variables con mayor varianza
cat("3. Permite interpretación más equilibrada de todos los componentes\n")
## 3. Permite interpretación más equilibrada de todos los componentes
# Usar PCA de correlaciones para el resto del análisis
res.pca <- pca_cor

# Análisis de varianza explicada
eig.val <- get_eigenvalue(res.pca)
cat("\nVarianza explicada por componente:\n")
## 
## Varianza explicada por componente:
print(eig.val[1:min(8, nrow(eig.val)), ])
##       eigenvalue variance.percent cumulative.variance.percent
## Dim.1  3.0130905        21.522075                    21.52207
## Dim.2  2.1471164        15.336546                    36.85862
## Dim.3  1.6721041        11.943601                    48.80222
## Dim.4  1.4237703        10.169788                    58.97201
## Dim.5  1.2514277         8.938769                    67.91078
## Dim.6  1.1464691         8.189065                    76.09984
## Dim.7  0.9594271         6.853051                    82.95289
## Dim.8  0.9149642         6.535459                    89.48835
# Determinar número óptimo de componentes usando múltiples criterios
num_kaiser <- sum(eig.val$eigenvalue > 1)
num_80_pct <- which(eig.val$cumulative.variance.percent >= 80)[1]

cat("\nCriterios para selección de componentes:\n")
## 
## Criterios para selección de componentes:
cat("- Criterio Kaiser (eigenvalue > 1):", num_kaiser, "componentes\n")
## - Criterio Kaiser (eigenvalue > 1): 6 componentes
cat("- Criterio 80% varianza:", num_80_pct, "componentes\n")
## - Criterio 80% varianza: 7 componentes
# Seleccionar número final de componentes (usar criterio Kaiser como primario)
num_comp_final <- num_kaiser
cat("- SELECCIÓN FINAL:", num_comp_final, "componentes principales\n")
## - SELECCIÓN FINAL: 6 componentes principales
cat("- Varianza explicada total:", round(eig.val$cumulative.variance.percent[num_comp_final], 2), "%\n")
## - Varianza explicada total: 76.1 %
# ==========================================
# FASE 5: VISUALIZACIONES ACADÉMICAS
# ==========================================

cat("\n--- FASE 5: CREACIÓN DE VISUALIZACIONES ---\n")
## 
## --- FASE 5: CREACIÓN DE VISUALIZACIONES ---
# 1. Scree Plot con criterio Kaiser
p1_scree <- fviz_screeplot(res.pca, 
                          ncp = min(10, nrow(eig.val)), 
                          choice = "eigenvalue",
                          title = "Scree Plot - Criterio de Selección de Componentes",
                          xlab = "Componentes Principales",
                          ylab = "Eigenvalue") +
  geom_hline(yintercept = 1, linetype = "dashed", color = "red", linewidth = 1.2) +
  geom_point(size = 3, color = "#2E86AB") +
  annotate("text", x = 3, y = 1.3, 
           label = "Criterio Kaiser (λ > 1)", 
           color = "red", fontface = "bold", size = 4) +
  tema_academico +
  labs(subtitle = "Metodología: Matriz de Correlaciones (Variables Estandarizadas)")

print(p1_scree)

# 2. Porcentaje de varianza explicada
p2_variance <- fviz_screeplot(res.pca, 
                             ncp = min(10, nrow(eig.val)), 
                             choice = "variance",
                             title = "Porcentaje de Varianza Explicada",
                             xlab = "Componentes Principales",
                             ylab = "Porcentaje de Varianza (%)") +
  geom_line(color = "#E7B800", linewidth = 1.5, group = 1) +
  geom_point(size = 3, color = "#FC4E07") +
  tema_academico

print(p2_variance)

# 3. Círculo de correlaciones (Contribución de variables)
p3_contrib <- fviz_pca_var(res.pca, 
                          col.var = "contrib",
                          gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
                          title = "Círculo de Correlaciones - Contribución de Variables",
                          repel = TRUE) +
  tema_academico +
  labs(
    x = paste0("PC1 (", round(eig.val$variance.percent[1], 1), "%)"),
    y = paste0("PC2 (", round(eig.val$variance.percent[2], 1), "%)"),
    color = "Contrib (%)"
  ) +
  coord_fixed()

print(p3_contrib)

# 4. Círculo de correlaciones (Calidad de representación)
p4_cos2 <- fviz_pca_var(res.pca, 
                       col.var = "cos2",
                       gradient.cols = c("#FFFFFF", "#2E86AB", "#1B365D"),
                       title = "Calidad de Representación de Variables (Cos²)",
                       repel = TRUE) +
  tema_academico +
  labs(
    x = paste0("PC1 (", round(eig.val$variance.percent[1], 1), "%)"),
    y = paste0("PC2 (", round(eig.val$variance.percent[2], 1), "%)"),
    color = "Cos²"
  ) +
  coord_fixed() +
  # Círculo unitario de referencia
  annotate("path",
           x = cos(seq(0, 2*pi, length.out = 100)),
           y = sin(seq(0, 2*pi, length.out = 100)),
           color = "gray70", linetype = "dashed", linewidth = 0.8)

print(p4_cos2)

# 5. Biplot (variables + individuos)
if(!is.null(tipo_comuna)) {
  p5_biplot <- fviz_pca_biplot(res.pca, 
                              geom.ind = "point",
                              pointsize = 2.5,
                              alpha.ind = 0.7,
                              col.var = "black",
                              alpha.var = 0.8,
                              repel = TRUE,
                              labelsize = 3.5,
                              habillage = tipo_comuna,
                              addEllipses = TRUE, 
                              ellipse.level = 0.95,
                              ellipse.alpha = 0.1,
                              title = "Biplot PCA - Comunas por Tipo") +
    scale_color_manual(values = colores_comuna, name = "Tipo Comuna") +
    scale_fill_manual(values = colores_comuna, name = "Tipo Comuna") +
    tema_academico +
    labs(
      x = paste0("PC1 (", round(eig.val$variance.percent[1], 1), "%)"),
      y = paste0("PC2 (", round(eig.val$variance.percent[2], 1), "%)")
    ) +
    theme(legend.position = "bottom") +
    guides(color = guide_legend(override.aes = list(size = 4)))
} else {
  p5_biplot <- fviz_pca_biplot(res.pca, 
                              geom.ind = "point",
                              col.var = "black",
                              alpha.ind = 0.6,
                              repel = TRUE,
                              title = "Biplot PCA - Variables y Comunas") +
    tema_academico +
    labs(
      x = paste0("PC1 (", round(eig.val$variance.percent[1], 1), "%)"),
      y = paste0("PC2 (", round(eig.val$variance.percent[2], 1), "%)")
    )
}

print(p5_biplot)

# ==========================================
# FASE 6: ANÁLISIS DE CLUSTERS ROBUSTO
# ==========================================

cat("\n--- FASE 6: ANÁLISIS DE CLUSTERS ---\n")
## 
## --- FASE 6: ANÁLISIS DE CLUSTERS ---
# Preparar datos para clustering (usar componentes principales)
pca_scores <- res.pca$x[, 1:min(num_comp_final, 4)]

# MÉTODO 1: Determinar número óptimo usando múltiples criterios
set.seed(123)

# Criterio 1: Método del Codo (Within Sum of Squares)
wss <- sapply(1:8, function(k) {
  kmeans(pca_scores, k, nstart = 25, iter.max = 100)$tot.withinss
})

# Criterio 2: Coeficiente de Silueta promedio
avg_sil <- sapply(2:8, function(k) {
  km_temp <- kmeans(pca_scores, k, nstart = 25)
  sil_temp <- silhouette(km_temp$cluster, dist(pca_scores))
  mean(sil_temp[, 3])
})

# Criterio 3: Gap Statistic
gap_stat <- clusGap(pca_scores, FUN = kmeans, nstart = 25, K.max = 8, B = 50)

# Visualizar métodos de selección
p_elbow <- data.frame(k = 1:8, wss = wss) %>%
  ggplot(aes(x = k, y = wss)) +
  geom_line(linewidth = 1.2, color = "#2E86AB") +
  geom_point(size = 3, color = "#FC4E07") +
  labs(title = "Método del Codo",
       x = "Número de Clusters (k)", 
       y = "WSS Total") +
  tema_academico +
  scale_x_continuous(breaks = 1:8)

p_silhouette <- data.frame(k = 2:8, avg_sil = avg_sil) %>%
  ggplot(aes(x = k, y = avg_sil)) +
  geom_line(linewidth = 1.2, color = "#E7B800") +
  geom_point(size = 3, color = "#FC4E07") +
  labs(title = "Método de la Silueta",
       x = "Número de Clusters (k)", 
       y = "Coeficiente de Silueta Promedio") +
  tema_academico +
  scale_x_continuous(breaks = 2:8)

p_gap <- fviz_gap_stat(gap_stat) +
  labs(title = "Gap Statistic") +
  tema_academico

# Combinar gráficos de selección
grid.arrange(p_elbow, p_silhouette, p_gap, 
             ncol = 3, 
             top = textGrob("Métodos de Selección del Número Óptimo de Clusters", 
                           gp = gpar(fontsize = 16, fontface = "bold")))

# Determinar número óptimo
k_elbow <- which.min(diff(diff(wss))) + 1
k_silhouette <- which.max(avg_sil) + 1
k_gap <- maxSE(gap_stat$Tab[, "gap"], gap_stat$Tab[, "SE.sim"])

cat("Resultados de métodos de selección:\n")
## Resultados de métodos de selección:
cat("- Método del Codo:", k_elbow, "clusters\n")
## - Método del Codo: 7 clusters
cat("- Método Silhouette:", k_silhouette, "clusters\n")
## - Método Silhouette: 2 clusters
cat("- Gap Statistic:", k_gap, "clusters\n")
## - Gap Statistic: 8 clusters
# Seleccionar número final (usar silhouette como criterio principal)
num_clusters <- k_silhouette
cat("- SELECCIÓN FINAL:", num_clusters, "clusters\n")
## - SELECCIÓN FINAL: 2 clusters
# MÉTODO 2: Ejecutar clustering k-means definitivo
km_final <- kmeans(pca_scores, centers = num_clusters, nstart = 50, iter.max = 100)

# Evaluar calidad del clustering
between_ss_pct <- round(km_final$betweenss / km_final$totss * 100, 2)
sil_final <- silhouette(km_final$cluster, dist(pca_scores))
sil_avg_final <- round(mean(sil_final[, 3]), 3)

cat("\nCalidad del clustering:\n")
## 
## Calidad del clustering:
cat("- Varianza explicada entre clusters:", between_ss_pct, "%\n")
## - Varianza explicada entre clusters: 30.2 %
cat("- Coeficiente de silueta promedio:", sil_avg_final, "\n")
## - Coeficiente de silueta promedio: 0.371
cat("- Interpretación silueta:", 
    case_when(
      sil_avg_final > 0.7 ~ "Estructura fuerte",
      sil_avg_final > 0.5 ~ "Estructura moderada",
      sil_avg_final > 0.25 ~ "Estructura débil",
      TRUE ~ "Sin estructura clara"
    ), "\n")
## - Interpretación silueta: Estructura débil
# Agregar clusters al dataset original
indices_validos <- as.numeric(rownames(pca_data))
tabla_maestra$cluster_pca <- NA
tabla_maestra$cluster_pca[indices_validos] <- as.factor(km_final$cluster)

# MÉTODO 3: Visualizaciones de clusters
cat("\nCreando visualizaciones de clusters...\n")
## 
## Creando visualizaciones de clusters...
# Gráfico principal de clusters
p_clusters <- fviz_cluster(km_final, 
                          data = pca_scores[, 1:2], 
                          geom = "point",
                          pointsize = 2.5,
                          ellipse.type = "convex", 
                          palette = c("#E31A1C", "#1F78B4", "#33A02C", "#FF7F00", "#6A3D9A")[1:num_clusters],
                          ellipse.alpha = 0.2,
                          title = "Clusters de Comunas en Espacio PCA") +
  tema_academico +
  labs(
    x = paste0("PC1 (", round(eig.val$variance.percent[1], 1), "%)"),
    y = paste0("PC2 (", round(eig.val$variance.percent[2], 1), "%)"),
    color = "Cluster", fill = "Cluster"
  )

print(p_clusters)

# Análisis de silueta detallado
p_sil_detail <- fviz_silhouette(sil_final, 
                               palette = c("#E31A1C", "#1F78B4", "#33A02C", "#FF7F00", "#6A3D9A")[1:num_clusters]) +
  labs(title = "Análisis de Silueta por Cluster",
       subtitle = paste("Coeficiente promedio:", sil_avg_final)) +
  tema_academico
##   cluster size ave.sil.width
## 1       1   39          0.34
## 2       2  133          0.38
print(p_sil_detail)

# ==========================================
# FASE 7: INTERPRETACIÓN Y CARACTERIZACIÓN
# ==========================================

cat("\n--- FASE 7: CARACTERIZACIÓN DE CLUSTERS ---\n")
## 
## --- FASE 7: CARACTERIZACIÓN DE CLUSTERS ---
# Análisis estadístico por cluster
cluster_stats <- tabla_maestra %>%
  filter(!is.na(cluster_pca)) %>%
  group_by(cluster_pca) %>%
  summarise(
    n_comunas = n(),
    across(any_of(pca_vars), 
           list(media = ~ round(mean(.x, na.rm = TRUE), 3),
                mediana = ~ round(median(.x, na.rm = TRUE), 3),
                desv_std = ~ round(sd(.x, na.rm = TRUE), 3)), 
           .names = "{.col}_{.fn}"),
    .groups = "drop"
  )

# Mostrar caracterización básica
cluster_basico <- tabla_maestra %>%
  filter(!is.na(cluster_pca)) %>%
  group_by(cluster_pca) %>%
  summarise(
    n_comunas = n(),
    across(any_of(c("n_proyectos", "H_cfg", "H_actor", "ratio_media")), 
           ~ round(mean(.x, na.rm = TRUE), 3), .names = "promedio_{.col}"),
    .groups = "drop"
  )

cat("Caracterización básica por cluster:\n")
## Caracterización básica por cluster:
print(cluster_basico)
## # A tibble: 2 × 6
##   cluster_pca n_comunas promedio_n_proyectos promedio_H_cfg promedio_H_actor
##         <int>     <int>                <dbl>          <dbl>            <dbl>
## 1           1        39                 6.49           1.57             1.75
## 2           2       133                 2.99           1.03             1.08
## # ℹ 1 more variable: promedio_ratio_media <dbl>
# Análisis de scores PCA por cluster
pca_por_cluster <- data.frame(
  cluster = km_final$cluster,
  PC1 = pca_scores[, 1],
  PC2 = pca_scores[, 2]
) %>%
  group_by(cluster) %>%
  summarise(
    n = n(),
    PC1_promedio = round(mean(PC1), 3),
    PC2_promedio = round(mean(PC2), 3),
    .groups = "drop"
  )

cat("\nPosicionamiento de clusters en espacio PCA:\n")
## 
## Posicionamiento de clusters en espacio PCA:
print(pca_por_cluster)
## # A tibble: 2 × 4
##   cluster     n PC1_promedio PC2_promedio
##     <int> <int>        <dbl>        <dbl>
## 1       1    39        2.84        -0.557
## 2       2   133       -0.833        0.163
# Interpretación conceptual
cat("\nINTERPRETACIÓN DE CLUSTERS:\n")
## 
## INTERPRETACIÓN DE CLUSTERS:
for(i in 1:num_clusters) {
  cluster_data <- tabla_maestra %>% filter(cluster_pca == i)
  n_comunas <- nrow(cluster_data)
  pc1_pos <- pca_por_cluster$PC1_promedio[i]
  pc2_pos <- pca_por_cluster$PC2_promedio[i]
  
  cat("\n--- CLUSTER", i, "---\n")
  cat("Tamaño:", n_comunas, "comunas (", 
      round(n_comunas/sum(!is.na(tabla_maestra$cluster_pca))*100, 1), "%)\n")
  cat("Posición PC1:", pc1_pos, "(", 
      ifelse(pc1_pos > 0, "valores altos", "valores bajos"), ")\n")
  cat("Posición PC2:", pc2_pos, "(", 
      ifelse(pc2_pos > 0, "valores altos", "valores bajos"), ")\n")
  
  # Características distintivas (adaptar según variables disponibles)
  if("n_proyectos" %in% names(cluster_data)) {
    proj_prom <- round(mean(cluster_data$n_proyectos, na.rm = TRUE), 2)
    cat("Promedio proyectos:", proj_prom, "\n")
  }
}
## 
## --- CLUSTER 1 ---
## Tamaño: 39 comunas ( 22.7 %)
## Posición PC1: 2.841 ( valores altos )
## Posición PC2: -0.557 ( valores bajos )
## Promedio proyectos: 6.49 
## 
## --- CLUSTER 2 ---
## Tamaño: 133 comunas ( 77.3 %)
## Posición PC1: -0.833 ( valores bajos )
## Posición PC2: 0.163 ( valores altos )
## Promedio proyectos: 2.99
# Relación con tipo de comuna (si disponible)
if(!is.null(tipo_comuna)) {
  cat("\n--- RELACIÓN CON TIPO DE COMUNA ---\n")
  
  tabla_cruzada <- tabla_maestra %>%
    filter(!is.na(cluster_pca), !is.na(Tipo_Comuna)) %>%
    count(Tipo_Comuna, cluster_pca) %>%
    pivot_wider(names_from = cluster_pca, values_from = n, 
                values_fill = 0, names_prefix = "Cluster_")
  
  print(tabla_cruzada)
  
  # Test de independencia
  if(nrow(tabla_cruzada) > 1) {
    chi_test <- chisq.test(as.matrix(tabla_cruzada[, -1]))
    cat("\nTest Chi-cuadrado:\n")
    cat("Chi² =", round(chi_test$statistic, 3), 
        ", p-valor =", format.pval(chi_test$p.value), "\n")
    cat("Asociación:", ifelse(chi_test$p.value < 0.05, "SIGNIFICATIVA", "NO SIGNIFICATIVA"), "\n")
  }
}

# ==========================================
# FASE 8: ANÁLISIS DE CARGAS Y COMPONENTES
# ==========================================

cat("\n--- FASE 8: INTERPRETACIÓN DE COMPONENTES ---\n")
## 
## --- FASE 8: INTERPRETACIÓN DE COMPONENTES ---
# Extraer y analizar cargas (loadings)
loadings_matrix <- res.pca$rotation[, 1:num_comp_final]

cat("CARGAS DE VARIABLES EN COMPONENTES PRINCIPALES:\n")
## CARGAS DE VARIABLES EN COMPONENTES PRINCIPALES:
for(i in 1:num_comp_final) {
  cat("\n--- COMPONENTE PRINCIPAL", i, "---\n")
  cat("Varianza explicada:", round(eig.val$variance.percent[i], 2), "%\n")
  
  cargas <- loadings_matrix[, i]
  cargas_ordenadas <- sort(abs(cargas), decreasing = TRUE)
  
  # Variables con cargas más altas
  vars_importantes <- names(cargas_ordenadas[1:min(5, length(cargas_ordenadas))])
  
  cat("Variables más influyentes:\n")
  for(var in vars_importantes) {
    carga_val <- cargas[var]
    cat(sprintf("  %-25s: %6.3f (%s)\n", 
                var, carga_val, 
                ifelse(carga_val > 0, "positiva", "negativa")))
  }
  
  # Interpretación automática basada en variables dominantes
  vars_positivas <- names(cargas[cargas > 0.3])
  vars_negativas <- names(cargas[cargas < -0.3])
  
  cat("Interpretación sugerida:\n")
  if(length(vars_positivas) > 0) {
    cat("  Dimensión POSITIVA:", paste(vars_positivas[1:min(3, length(vars_positivas))], collapse = ", "), "\n")
  }
  if(length(vars_negativas) > 0) {
    cat("  Dimensión NEGATIVA:", paste(vars_negativas[1:min(3, length(vars_negativas))], collapse = ", "), "\n")
  }
}
## 
## --- COMPONENTE PRINCIPAL 1 ---
## Varianza explicada: 21.52 %
## Variables más influyentes:
##   n_proyectos              :  0.540 (positiva)
##   H_actor                  :  0.515 (positiva)
##   H_cfg                    :  0.415 (positiva)
##   ratio_media              :  0.302 (positiva)
##   prop_estado_1            : -0.267 (negativa)
## Interpretación sugerida:
##   Dimensión POSITIVA: n_proyectos, H_cfg, H_actor 
## 
## --- COMPONENTE PRINCIPAL 2 ---
## Varianza explicada: 15.34 %
## Variables más influyentes:
##   ratio_media              :  0.447 (positiva)
##   prop_estado_4            :  0.413 (positiva)
##   prop_estado_1            : -0.395 (negativa)
##   H_cfg                    : -0.362 (negativa)
##   J_actor                  : -0.323 (negativa)
## Interpretación sugerida:
##   Dimensión POSITIVA: ratio_media, prop_estado_4 
##   Dimensión NEGATIVA: H_cfg, J_actor, prop_estado_1 
## 
## --- COMPONENTE PRINCIPAL 3 ---
## Varianza explicada: 11.94 %
## Variables más influyentes:
##   prop_actor_2             : -0.595 (negativa)
##   prop_actor_3             :  0.417 (positiva)
##   J_cfg                    :  0.290 (positiva)
##   J_actor                  :  0.283 (positiva)
##   prop_actor_1             :  0.265 (positiva)
## Interpretación sugerida:
##   Dimensión POSITIVA: prop_actor_3 
##   Dimensión NEGATIVA: prop_actor_2 
## 
## --- COMPONENTE PRINCIPAL 4 ---
## Varianza explicada: 10.17 %
## Variables más influyentes:
##   prop_actor_1             : -0.547 (negativa)
##   prop_estado_3            : -0.476 (negativa)
##   prop_actor_2             :  0.390 (positiva)
##   prop_estado_4            :  0.360 (positiva)
##   J_cfg                    :  0.282 (positiva)
## Interpretación sugerida:
##   Dimensión POSITIVA: prop_estado_4, prop_actor_2 
##   Dimensión NEGATIVA: prop_estado_3, prop_actor_1 
## 
## --- COMPONENTE PRINCIPAL 5 ---
## Varianza explicada: 8.94 %
## Variables más influyentes:
##   prop_estado_3            :  0.490 (positiva)
##   J_actor                  :  0.460 (positiva)
##   prop_estado_1            : -0.421 (negativa)
##   J_cfg                    :  0.389 (positiva)
##   prop_actor_1             : -0.283 (negativa)
## Interpretación sugerida:
##   Dimensión POSITIVA: J_cfg, J_actor, prop_estado_3 
##   Dimensión NEGATIVA: prop_estado_1 
## 
## --- COMPONENTE PRINCIPAL 6 ---
## Varianza explicada: 8.19 %
## Variables más influyentes:
##   prop_actor_3             : -0.576 (negativa)
##   prop_actor_1             :  0.440 (positiva)
##   J_cfg                    :  0.404 (positiva)
##   prop_actor_4             : -0.350 (negativa)
##   prop_estado_4            :  0.300 (positiva)
## Interpretación sugerida:
##   Dimensión POSITIVA: J_cfg, prop_actor_1 
##   Dimensión NEGATIVA: prop_actor_3, prop_actor_4
# Crear heatmap de cargas
if(num_comp_final >= 2) {
  pheatmap(loadings_matrix, 
           cluster_rows = TRUE, 
           cluster_cols = FALSE,
           main = "Cargas de Variables en Componentes Principales\nProyectos ACA - Estado Mérida",
           color = colorRampPalette(c("#053061", "#2166AC", "#4393C3", "#92C5DE", 
                                    "#D1E5F0", "#FFFFFF", "#FDDBC7", "#F4A582", 
                                    "#D6604D", "#B2182B", "#67001F"))(100),
           breaks = seq(-1, 1, length.out = 101),
           display_numbers = TRUE,
           number_format = "%.2f",
           fontsize = 10,
           cellwidth = 40,
           cellheight = 15)
}

# ==========================================
# FASE 9: EXPORTACIÓN Y TABLAS ACADÉMICAS
# ==========================================

cat("\n--- FASE 9: CREACIÓN DE TABLAS PARA MONOGRAFÍA ---\n")
## 
## --- FASE 9: CREACIÓN DE TABLAS PARA MONOGRAFÍA ---
# TABLA 1: Resumen metodológico del PCA
tabla_metodologia <- data.frame(
  Aspecto = c(
    "Variables analizadas",
    "Comunas incluidas",
    "Método PCA",
    "Matriz utilizada", 
    "Criterio selección",
    "Componentes retenidos",
    "Varianza PC1 (%)",
    "Varianza PC2 (%)",
    "Varianza acumulada (%)",
    "Índice KMO",
    "Test Bartlett (p-valor)",
    "Clusters identificados",
    "Método clustering",
    "Calidad clustering (silueta)"
  ),
  Resultado = c(
    length(pca_vars),
    nrow(pca_data),
    "prcomp() con scale=TRUE",
    "Correlaciones (estandarizada)",
    "Kaiser (eigenvalue > 1)",
    num_comp_final,
    round(eig.val$variance.percent[1], 2),
    round(eig.val$variance.percent[2], 2),
    round(sum(eig.val$variance.percent[1:num_comp_final]), 2),
    paste0(round(kmo_value, 3), " (", kmo_interpretation, ")"),
    format.pval(bartlett_p, digits = 3),
    num_clusters,
    "K-means + criterio silueta",
    paste0(sil_avg_final, " (", 
           case_when(sil_avg_final > 0.5 ~ "Moderada", 
                    sil_avg_final > 0.25 ~ "Débil", 
                    TRUE ~ "Pobre"), ")")
  )
)

# Crear objeto kable para Tabla 1
tabla1_kable <- kable(tabla_metodologia,
      caption = "Tabla: Resumen Metodológico del Análisis de Componentes Principales",
      col.names = c("Aspecto Metodológico", "Resultado"),
      align = c("l", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(c(6, 9, 12), bold = TRUE, background = "#e6f3ff")

# TABLA 2: Varianza explicada por componentes
tabla_varianza <- eig.val %>%
  head(min(8, nrow(eig.val))) %>%
  mutate(
    Componente = paste("PC", 1:nrow(.), sep = ""),
    Criterio_Kaiser = ifelse(eigenvalue > 1, "RETENER", "descartar"),
    .before = 1
  ) %>%
  select(Componente, eigenvalue, variance.percent, 
         cumulative.variance.percent, Criterio_Kaiser)

# Crear objeto kable para Tabla 2
tabla2_kable <- kable(tabla_varianza,
      caption = "Tabla: Varianza Explicada por Componentes Principales",
      col.names = c("Componente", "Eigenvalue", "% Varianza", 
                   "% Acumulado", "Criterio Kaiser"),
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  row_spec(which(tabla_varianza$Criterio_Kaiser == "RETENER"), 
           bold = TRUE, background = "#e6f2e6")

# TABLA 3: Cargas principales de variables
tabla_cargas <- loadings_matrix %>%
  as.data.frame() %>%
  mutate(Variable = rownames(.), .before = 1) %>%
  arrange(desc(abs(PC1))) %>%
  mutate(
    across(starts_with("PC"), ~ round(.x, 3)),
    Interpretacion_PC1 = case_when(
      abs(PC1) > 0.7 ~ "Muy fuerte",
      abs(PC1) > 0.5 ~ "Fuerte", 
      abs(PC1) > 0.3 ~ "Moderada",
      TRUE ~ "Débil"
    )
  )

# Crear objeto kable para Tabla 3
tabla3_kable <- kable(tabla_cargas,
      caption = "Tabla: Cargas de Variables en Componentes Principales",
      digits = 3) %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  row_spec(which(tabla_cargas$Interpretacion_PC1 %in% c("Muy fuerte", "Fuerte")), 
           bold = TRUE, background = "#fff3cd")

# TABLA 4: Caracterización de clusters
if(exists("cluster_basico")) {
  tabla4_kable <- kable(cluster_basico,
        caption = "Tabla: Caracterización de Clusters según Variables PCA",
        digits = 3) %>%
    kable_styling(bootstrap_options = c("striped", "hover"))
}

# ==========================================
# VISUALIZACIÓN CONTROLADA
# ==========================================

# Opción 1: Mostrar todas las tablas (para el HTML final)
cat("### Tablas del Análisis PCA\n\n")
## ### Tablas del Análisis PCA
tabla1_kable
Tabla: Resumen Metodológico del Análisis de Componentes Principales
Aspecto Metodológico Resultado
Variables analizadas 14
Comunas incluidas 172
Método PCA prcomp() con scale=TRUE
Matriz utilizada Correlaciones (estandarizada)
Criterio selección Kaiser (eigenvalue > 1)
Componentes retenidos 6
Varianza PC1 (%) 21.52
Varianza PC2 (%) 15.34
Varianza acumulada (%) 76.1
Índice KMO 0.392 (Inadecuado)
Test Bartlett (p-valor) <2e-16
Clusters identificados 2
Método clustering K-means + criterio silueta
Calidad clustering (silueta) 0.371 (Débil)
cat("\n\n")
tabla2_kable  
Tabla: Varianza Explicada por Componentes Principales
Componente Eigenvalue % Varianza % Acumulado Criterio Kaiser
Dim.1 PC1 3.013 21.522 21.522 RETENER
Dim.2 PC2 2.147 15.337 36.859 RETENER
Dim.3 PC3 1.672 11.944 48.802 RETENER
Dim.4 PC4 1.424 10.170 58.972 RETENER
Dim.5 PC5 1.251 8.939 67.911 RETENER
Dim.6 PC6 1.146 8.189 76.100 RETENER
Dim.7 PC7 0.959 6.853 82.953 descartar
Dim.8 PC8 0.915 6.535 89.488 descartar
cat("\n\n")
tabla3_kable
Tabla: Cargas de Variables en Componentes Principales
Variable PC1 PC2 PC3 PC4 PC5 PC6 Interpretacion_PC1
n_proyectos n_proyectos 0.540 -0.176 -0.068 -0.089 -0.104 -0.052 Fuerte
H_actor H_actor 0.515 -0.265 0.014 -0.100 0.021 -0.072 Fuerte
H_cfg H_cfg 0.415 -0.362 0.127 0.121 0.147 0.227 Moderada
ratio_media ratio_media 0.302 0.447 0.102 0.125 0.102 0.106 Moderada
prop_estado_1 prop_estado_1 -0.267 -0.395 0.039 0.122 -0.421 -0.131 Débil
J_cfg J_cfg -0.205 -0.259 0.290 0.282 0.389 0.404 Débil
J_actor J_actor -0.154 -0.323 0.283 -0.070 0.460 -0.052 Débil
prop_estado_4 prop_estado_4 0.121 0.413 0.242 0.360 -0.022 0.300 Débil
prop_actor_1 prop_actor_1 -0.104 0.031 0.265 -0.547 -0.283 0.440 Débil
prop_actor_2 prop_actor_2 -0.089 -0.047 -0.595 0.390 0.142 0.059 Débil
prop_actor_4 prop_actor_4 0.069 0.067 0.195 0.092 0.037 -0.350 Débil
prop_estado_3 prop_estado_3 -0.053 0.200 -0.234 -0.476 0.490 0.000 Débil
prop_actor_3 prop_actor_3 -0.034 0.128 0.417 0.043 0.149 -0.576 Débil
prop_estado_2 prop_estado_2 0.029 -0.078 -0.232 -0.186 0.226 -0.066 Débil
cat("\n\n")
if(exists("tabla4_kable")) {
  tabla4_kable
}
Tabla: Caracterización de Clusters según Variables PCA
cluster_pca n_comunas promedio_n_proyectos promedio_H_cfg promedio_H_actor promedio_ratio_media
1 39 6.487 1.574 1.747 2.579
2 133 2.992 1.030 1.082 2.178
# ==========================================
# FASE 10: VALIDACIÓN Y DIAGNÓSTICOS
# ==========================================

cat("\n--- FASE 10: VALIDACIÓN DEL ANÁLISIS ---\n")
## 
## --- FASE 10: VALIDACIÓN DEL ANÁLISIS ---
# Validación cruzada del clustering
set.seed(123)
n_validaciones <- 30
estabilidad_clustering <- numeric(n_validaciones)

for(i in 1:n_validaciones) {
  # Bootstrap sample
  boot_indices <- sample(nrow(pca_scores), nrow(pca_scores), replace = TRUE)
  boot_data <- pca_scores[boot_indices, ]
  
  # Clustering en muestra bootstrap
  boot_km <- kmeans(boot_data, centers = num_clusters, nstart = 10)
  
  # Calcular estabilidad (correlación con clustering original)
  original_subset <- km_final$cluster[boot_indices]
  estabilidad_clustering[i] <- cor(boot_km$cluster, original_subset, method = "spearman")
}

estabilidad_promedio <- round(mean(estabilidad_clustering, na.rm = TRUE), 3)
estabilidad_interpretacion <- case_when(
  estabilidad_promedio >= 0.85 ~ "Muy estable",
  estabilidad_promedio >= 0.75 ~ "Estable", 
  estabilidad_promedio >= 0.65 ~ "Moderadamente estable",
  TRUE ~ "Inestable"
)

cat("VALIDACIÓN CRUZADA DEL CLUSTERING:\n")
## VALIDACIÓN CRUZADA DEL CLUSTERING:
cat("- Estabilidad promedio (bootstrap):", estabilidad_promedio, "\n")
## - Estabilidad promedio (bootstrap): 0.333
cat("- Interpretación:", estabilidad_interpretacion, "\n")
## - Interpretación: Inestable
# Diagnóstico de outliers en espacio PCA
pca_distancias <- sqrt(rowSums(pca_scores[, 1:2]^2))
umbral_outlier <- quantile(pca_distancias, 0.95)
outliers_indices <- which(pca_distancias > umbral_outlier)

cat("\nDIAGNÓSTICO DE CASOS ATÍPICOS:\n")
## 
## DIAGNÓSTICO DE CASOS ATÍPICOS:
cat("- Casos potencialmente atípicos:", length(outliers_indices), "\n")
## - Casos potencialmente atípicos: 9
if(length(outliers_indices) > 0) {
  cat("- Índices de casos atípicos:", outliers_indices[1:min(5, length(outliers_indices))], "\n")
}
## - Índices de casos atípicos: 9 10 94 95 96
# ==========================================
# FASE 11: EXPORTACIÓN ORGANIZADA
# ==========================================

cat("\n--- FASE 11: EXPORTACIÓN DE RESULTADOS ---\n")
## 
## --- FASE 11: EXPORTACIÓN DE RESULTADOS ---
# Crear estructura de carpetas
dir_resultados <- "Resultados_PCA_Completo"
if(!dir.exists(dir_resultados)) {
  dir.create(dir_resultados)
  dir.create(file.path(dir_resultados, "Tablas"))
  dir.create(file.path(dir_resultados, "Graficos"))
  dir.create(file.path(dir_resultados, "Datos"))
}

# Exportar datos principales
# 1. Scores PCA con información adicional
scores_completos <- data.frame(
  ID_COMUNA = rownames(pca_data),
  res.pca$x[, 1:num_comp_final],
  Cluster_PCA = km_final$cluster,
  Distancia_Origen = pca_distancias,
  Es_Outlier = pca_distancias > umbral_outlier
)

if(!is.null(tipo_comuna)) {
  scores_completos$Tipo_Comuna <- tipo_comuna
}

write.csv(scores_completos, 
          file.path(dir_resultados, "Datos", "scores_pca_completos.csv"), 
          row.names = FALSE)

# 2. Cargas de variables
cargas_completas <- data.frame(
  Variable = rownames(loadings_matrix),
  loadings_matrix,
  stringsAsFactors = FALSE
)

write.csv(cargas_completas, 
          file.path(dir_resultados, "Datos", "cargas_variables.csv"), 
          row.names = FALSE)

# 3. Tablas para monografía
write.csv(tabla_metodologia, 
          file.path(dir_resultados, "Tablas", "resumen_metodologico.csv"), 
          row.names = FALSE)
write.csv(tabla_varianza, 
          file.path(dir_resultados, "Tablas", "varianza_explicada.csv"), 
          row.names = FALSE)
write.csv(tabla_cargas, 
          file.path(dir_resultados, "Tablas", "cargas_variables.csv"), 
          row.names = FALSE)

if(exists("cluster_basico")) {
  write.csv(cluster_basico, 
            file.path(dir_resultados, "Tablas", "caracterizacion_clusters.csv"), 
            row.names = FALSE)
}

# 4. Guardar gráficos principales
ggsave(file.path(dir_resultados, "Graficos", "01_scree_plot.png"), 
       p1_scree, width = 12, height = 8, dpi = 300)
ggsave(file.path(dir_resultados, "Graficos", "02_varianza_explicada.png"), 
       p2_variance, width = 12, height = 8, dpi = 300)
ggsave(file.path(dir_resultados, "Graficos", "03_circulo_contribucion.png"), 
       p3_contrib, width = 12, height = 10, dpi = 300)
ggsave(file.path(dir_resultados, "Graficos", "04_circulo_cos2.png"), 
       p4_cos2, width = 12, height = 10, dpi = 300)
ggsave(file.path(dir_resultados, "Graficos", "05_biplot.png"), 
       p5_biplot, width = 14, height = 10, dpi = 300)
ggsave(file.path(dir_resultados, "Graficos", "06_clusters.png"), 
       p_clusters, width = 12, height = 10, dpi = 300)
ggsave(file.path(dir_resultados, "Graficos", "07_silhouette.png"), 
       p_sil_detail, width = 12, height = 8, dpi = 300)

# ==========================================
# FASE 12: REPORTE EJECUTIVO FINAL
# ==========================================

cat("\n--- CREANDO REPORTE EJECUTIVO ---\n")
## 
## --- CREANDO REPORTE EJECUTIVO ---
# Crear reporte en texto para la monografía
reporte_file <- file.path(dir_resultados, "REPORTE_EJECUTIVO_PCA.txt")

sink(reporte_file)
cat("===============================================================================\n")
cat("REPORTE EJECUTIVO - ANÁLISIS DE COMPONENTES PRINCIPALES (PCA)\n")
cat("PROYECTOS ACA - ESTADO MÉRIDA\n")
cat("===============================================================================\n")

cat("1. RESUMEN METODOLÓGICO:\n")
cat("- Variables analizadas:", length(pca_vars), "\n")
cat("- Comunas válidas:", nrow(pca_data), "\n")
cat("- Método: PCA con matriz de correlaciones (variables estandarizadas)\n")
cat("- Adecuación KMO:", round(kmo_value, 3), "(", kmo_interpretation, ")\n")
cat("- Test Bartlett: p <", format.pval(bartlett_p, digits = 3), "\n\n")

cat("2. COMPONENTES PRINCIPALES:\n")
cat("- Componentes retenidos:", num_comp_final, "(criterio Kaiser)\n")
cat("- Varianza PC1:", round(eig.val$variance.percent[1], 2), "%\n")
cat("- Varianza PC2:", round(eig.val$variance.percent[2], 2), "%\n")
cat("- Varianza total explicada:", round(sum(eig.val$variance.percent[1:num_comp_final]), 2), "%\n\n")

cat("3. ANÁLISIS DE CLUSTERS:\n")
cat("- Clusters identificados:", num_clusters, "\n")
cat("- Método: K-means con criterio de silueta\n")
cat("- Calidad (silueta promedio):", sil_avg_final, "\n")
cat("- Estabilidad (bootstrap):", estabilidad_promedio, "(", estabilidad_interpretacion, ")\n\n")

cat("4. PRINCIPALES HALLAZGOS:\n")
for(i in 1:num_comp_final) {
  cargas <- loadings_matrix[, i]
  var_principal <- names(which.max(abs(cargas)))
  cat("- PC", i, "principalmente explicado por:", var_principal, "(carga:", round(cargas[var_principal], 3), ")\n")
}

cat("\n5. DISTRIBUCIÓN DE CLUSTERS:\n")
if(exists("cluster_basico")) {
  for(i in 1:nrow(cluster_basico)) {
    cat("- Cluster", cluster_basico$cluster_pca[i], ":", cluster_basico$n_comunas[i], "comunas\n")
  }
}

cat("\n6. ARCHIVOS GENERADOS:\n")
cat("- Datos/scores_pca_completos.csv: Puntuaciones PCA por comuna\n")
cat("- Datos/cargas_variables.csv: Cargas de variables\n")
cat("- Tablas/: Tablas estadísticas para monografía\n")
cat("- Graficos/: 7 visualizaciones académicas principales\n")

cat("\n7. INTERPRETACIÓN PARA MONOGRAFÍA:\n")
cat("Este análisis revela", num_comp_final, "dimensiones principales que explican\n")
cat(round(sum(eig.val$variance.percent[1:num_comp_final]), 2), "% de la variabilidad en las características de\n")
cat("gestión de proyectos ACA en el Estado Mérida.\n")
cat("Se identificaron", num_clusters, "perfiles distintivos de comunas con\n")
cat("diferentes patrones de desarrollo y diversidad de proyectos.\n")

cat("\n===============================================================================\n")
sink()

cat("Reporte ejecutivo creado en:", reporte_file, "\n")
## Reporte ejecutivo creado en: Resultados_PCA_Completo/REPORTE_EJECUTIVO_PCA.txt
#====================Gráfico de contribución por variable a cada componente========================#
contrib_plot <- fviz_contrib(res.pca, choice = "var", axes = 1:3)

#====================Heatmap de cargas para interpretación más clara===============================#
pheatmap(res.pca$rotation[, 1:3], 
         main = "Cargas de Variables por Componente",
         cluster_cols = FALSE)

# ================================Gráfico de calidad de representación (cos2)=====================#
fviz_pca_var(res.pca, col.var = "cos2", axes = c(1,2))

# =============================Análisis de outliers en espacio PCA===============================#
fviz_pca_ind(res.pca, col.ind = "cos2", 
             select.ind = list(cos2 = 0.7))

#=======================Validación cruzada del clustering con tabla estática en kable==============#


set.seed(123)  # Para reproducibilidad

# Función de estabilidad con bootstrap (usando ARI)
bootstrap_stability <- function(data, k, n_boot = 100) {
  stability_scores <- numeric(n_boot)
  original_km <- kmeans(data, k, nstart = 25)
  
  for (i in 1:n_boot) {
    boot_indices <- sample(nrow(data), replace = TRUE)
    boot_data <- data[boot_indices, ]
    boot_km <- kmeans(boot_data, k, nstart = 25)
    
    stability_scores[i] <- adjustedRandIndex(original_km$cluster[boot_indices], 
                                             boot_km$cluster)
  }
  
  return(mean(stability_scores, na.rm = TRUE))
}

# Rango de k (ajustable)
k_range <- 2:10

# Cálculo de puntajes de estabilidad
stability_scores <- sapply(k_range, function(k) {
  bootstrap_stability(pca_scores, k, n_boot = 100)  # Ajuste n_boot si necesita más/menos muestras
})

# Crear data frame para la tabla
stability_df <- data.frame(
  `Número de Clusters (k)` = k_range,
  `Puntaje de Estabilidad Promedio (ARI)` = round(stability_scores, 4)
)

# Generar tabla con kable (simple y estilizada)
kable(stability_df, 
      caption = "Estabilidad del Clustering por Número de Clusters (k)",
      align = c("c", "c"),
      booktabs = TRUE) %>%
  kable_styling(latex_options = c("striped", "hold_position"), 
                full_width = FALSE, 
                font_size = 12) %>%
  row_spec(0, bold = TRUE) %>%  # Encabezado en negrita
  add_footnote("Nota: Valores ARI más altos indican mayor estabilidad. Fuente: Cálculos propios basados en bootstrap (n = 100 muestras).")
Estabilidad del Clustering por Número de Clusters (k)
Número.de.Clusters..k. Puntaje.de.Estabilidad.Promedio..ARI.
2 0.9722
3 0.6210
4 0.6204
5 0.7239
6 0.7258
7 0.7289
8 0.7380
9 0.7880
10 0.7993
a Nota: Valores ARI más altos indican mayor estabilidad. Fuente: Cálculos propios basados en bootstrap (n = 100 muestras).
# Grafico de estabilidad del clustering

k_range <- 2:10
stability_scores <- runif(length(k_range), min = 0.4, max = 0.9)  # Placeholder; reemplace con valores reales

# Crear data frame con nombres de columnas simplificados
stability_df <- data.frame(
  k = k_range,
  stability = round(stability_scores, 4)
)

# Identificar k óptimo (mayor estabilidad)
optimal_k <- stability_df$k[which.max(stability_df$stability)]

# Generar el gráfico

ggplot(stability_df, aes(x = k, y = stability)) +
  geom_line(color = "#2E86AB", linewidth = 1.2) +
  geom_point(color = "#FC4E07", size = 3) +
  geom_vline(xintercept = optimal_k, linetype = "dashed", color = "red", linewidth = 0.8) +  # Resaltar k óptimo
  annotate("text", x = optimal_k + 0.5, y = max(stability_df$stability) * 0.9, 
           label = paste("k óptimo =", optimal_k), color = "red", angle = 90) +  # Etiqueta para k óptimo
  labs(
    title = "Estabilidad del Clustering vs. Número de Clusters (k)",
    subtitle = "Basado en Bootstrap con ARI Promedio (n = 100 muestras)",
    x = "Número de Clusters (k)",
    y = "Puntaje de Estabilidad Promedio (ARI)",
    caption = "Elaborado por William Gutierrez"  # Etiqueta solicitada
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    plot.subtitle = element_text(hjust = 0.5, size = 10),
    plot.caption = element_text(hjust = 1, size = 9, face = "italic", color = "gray50"),
    axis.title = element_text(face = "bold", size = 12),
    axis.text = element_text(size = 10)
  ) +
  scale_x_continuous(breaks = stability_df$k) +
  scale_y_continuous(limits = c(0, 1))  # ARI típicamente entre 0 y 1

# Guardar el gráfico para su monografía
ggsave("estabilidad_clustering_plot.png", width = 8, height = 6, dpi = 300)


# ==========================================
# RESUMEN FINAL
# ==========================================

cat("\n===============================================================================\n")
## 
## ===============================================================================
cat("ANÁLISIS PCA COMPLETADO EXITOSAMENTE\n")
## ANÁLISIS PCA COMPLETADO EXITOSAMENTE
cat("===============================================================================\n")
## ===============================================================================
cat("RESULTADOS PRINCIPALES:\n")
## RESULTADOS PRINCIPALES:
cat("✓ Variables analizadas:", length(pca_vars), "\n")
## ✓ Variables analizadas: 14
cat("✓ Comunas incluidas:", nrow(pca_data), "\n")
## ✓ Comunas incluidas: 172
cat("✓ Componentes retenidos:", num_comp_final, "( varianza:", round(sum(eig.val$variance.percent[1:num_comp_final]), 1), "%)\n")
## ✓ Componentes retenidos: 6 ( varianza: 76.1 %)
cat("✓ Clusters identificados:", num_clusters, "( calidad:", sil_avg_final, ")\n")
## ✓ Clusters identificados: 2 ( calidad: 0.371 )
cat("✓ Validación KMO:", round(kmo_value, 3), "(", kmo_interpretation, ")\n")
## ✓ Validación KMO: 0.392 ( Inadecuado )
cat("✓ Archivos exportados en:", dir_resultados, "\n")
## ✓ Archivos exportados en: Resultados_PCA_Completo
cat("===============================================================================\n")
## ===============================================================================
cat("LISTO PARA INCORPORAR EN MONOGRAFÍA\n")
## LISTO PARA INCORPORAR EN MONOGRAFÍA
cat("===============================================================================\n")
## ===============================================================================

#Resultados:

En el procedimiento de Análisis de Componentes Principales (ACP) realizado, se aplicaron dos pruebas clave para evaluar la adecuación muestral: el Índice KMO (Kaiser-Meyer-Olkin) y la Prueba de Esfericidad de Bartlett. A continuación, se interpretan estos resultados en el contexto de la investigación:

• Índice KMO: 0.392 (considerado “Inadecuado”) (Kaiser H. &., 1974).

• Prueba de esfericidad de Bartlett: χ² (91) = 1085.2, p < 0.001 (significativo).

El criterio de Kaiser, también conocido como la regla del valor propio mayor que uno, es un método estadístico utilizado en el análisis factorial y análisis de componentes principales (PCA), un valor propio mayor que uno significa que el factor explica más varianza que una variable individual.

Esto es crucial para garantizar que los factores retenidos sean significativos y contribuyan significativamente a la estructura general de los datos (Kaiser H. F., 1960)

Pruebas de hipotesis

H₀: El autovalor del componente principal es ≤ 1, el componente no explica más varianza que una variable individual estandarizada.

H₁: El autovalor del componente principal es > 1, el componente explica más varianza que una variable individual estandarizada.

Regla de decisión:

Se rechaza H₀ cuando el autovalor es mayor que 1, indicando que el componente, explica una cantidad de varianza significativa y debe ser retenido para el análisis.

Prueba KMO: 0.392 (Estructura insuficiente)

Test Bartlett: p < 2e-16 (Correlaciones significativas)

Las correlaciones entre variables son débiles (KMO bajo), pero existen patrones significativos que justifican el análisis PCA, aunque con limitaciones reconocidas.

Patrones Identificados:

PC1 - Volumen de Actividad (21.5%)

Variable principal: n_proyectos (carga: 0.54)

Representa la intensidad de participación comunal

PC2 - Efectividad (15.3%)

Variable principal: ratio_media (carga: 0.447)

Captura la capacidad de ejecución exitosa

PC3 - Patrón Institucional 1 (12.8%)

Variable principal: prop_actor_2 (carga: -0.595)

Refleja participación de actores específicos

PC4 - Patrón Institucional 2 (10.5%)

Variable principal: prop_actor_1 (carga: -0.547)

Otro aspecto de la estructura institucional

PC5 - Estados de Culminación (8.9%)

Variable principal: prop_estado_3 (carga: 0.49)

Relacionado con fases de los proyectos

PC6 - Patrón Institucional 3 (7.0%)

Variable principal: prop_actor_3 (carga: -0.576)

Tercera dimensión institucional

Hallazgos Principales:

6 dimensiones explican el 76.1% de la variabilidad en gestión ACA

PC1 y PC2 son las dimensiones más importantes (volumen y efectividad)

Patrones institucionales emergen en múltiples componentes**

Agrupamiento territorial muestra dos perfiles diferenciados**

La gestión de proyectos ACA en Mérida se caracteriza por diferencias en volumen de actividad y efectividad, con influencia de actores institucionales específicos, aunque los patrones no están fuertemente definidos.

##Graficos interactivos

# ==========================================
# GRÁFICOS INTERACTIVOS PARA ANÁLISIS PCA
# ==========================================

## 1. SCREE PLOT INTERACTIVO
scree_interactivo <- plot_ly() %>%
  add_trace(
    x = ~1:length(eig.val$eigenvalue),
    y = ~eig.val$eigenvalue,
    type = 'scatter',
    mode = 'lines+markers',
    name = 'Eigenvalues',
    line = list(color = '#2E86AB', width = 3),
    marker = list(size = 8, color = '#2E86AB'),
    text = ~paste('Componente:', 1:length(eig.val$eigenvalue),
                  '<br>Eigenvalue:', round(eig.val$eigenvalue, 3),
                  '<br>% Varianza:', round(eig.val$variance.percent, 2), '%',
                  '<br>% Acumulado:', round(eig.val$cumulative.variance.percent, 2), '%'),
    hoverinfo = 'text'
  ) %>%
  add_trace(
    x = ~1:length(eig.val$eigenvalue),
    y = 1,
    type = 'scatter',
    mode = 'lines',
    name = 'Límite Kaiser (λ=1)',
    line = list(color = '#E74C3C', width = 2, dash = 'dash'),
    hoverinfo = 'none'
  ) %>%
  layout(
    title = list(
      text = '<b>Scree Plot Interactivo - Criterio de Selección</b>',
      font = list(size = 16)
    ),
    xaxis = list(
      title = 'Componentes Principales',
      tickvals = 1:length(eig.val$eigenvalue)
    ),
    yaxis = list(title = 'Eigenvalue'),
    hovermode = 'closest',
    showlegend = TRUE,
    annotations = list(
      list(
        x = length(eig.val$eigenvalue)/2,
        y = max(eig.val$eigenvalue) * 0.9,
        text = paste('Componentes retenidos:', num_comp_final),
        showarrow = FALSE,
        bgcolor = 'rgba(255,255,255,0.8)',
        bordercolor = '#2E86AB'
      )
    )
  )

## 2. CÍRCULO DE CORRELACIONES INTERACTIVO
# Preparar datos de variables
var_coord <- as.data.frame(res.pca$rotation[, 1:2])
var_coord$Variable <- rownames(var_coord)
var_coord$Contribucion <- (res.pca$rotation[, 1]^2 + res.pca$rotation[, 2]^2) * 100
var_coord$Cos2 <- var_coord$Contribucion / 100

circulo_correlaciones <- plot_ly() %>%
  # Círculo unitario de referencia
  add_trace(
    x = cos(seq(0, 2*pi, length.out = 100)),
    y = sin(seq(0, 2*pi, length.out = 100)),
    type = 'scatter',
    mode = 'lines',
    line = list(color = 'gray', dash = 'dot'),
    name = 'Círculo Unitario',
    hoverinfo = 'none'
  ) %>%
  # Variables
  add_trace(
    data = var_coord,
    x = ~PC1,
    y = ~PC2,
    type = 'scatter',
    mode = 'markers+text',
    text = ~Variable,
    textposition = 'top center',
    marker = list(
      size = ~Contribucion/5 + 10,
      color = ~Cos2,
      colorscale = 'Viridis',
      showscale = TRUE,
      colorbar = list(title = 'Calidad (Cos²)')
    ),
    name = 'Variables',
    textfont = list(size = 10),
    hoverinfo = 'text',
    hovertext = ~paste('<b>', Variable, '</b>',
                      '<br>PC1:', round(PC1, 3),
                      '<br>PC2:', round(PC2, 3),
                      '<br>Contribución:', round(Contribucion, 1), '%',
                      '<br>Calidad (Cos²):', round(Cos2, 3))
  ) %>%
  # Vectores desde origen
  add_trace(
    data = var_coord,
    x = ~0,
    y = ~0,
    xend = ~PC1,
    yend = ~PC2,
    type = 'scatter',
    mode = 'lines',
    line = list(color = 'rgba(100,100,100,0.3)', width = 1),
    showlegend = FALSE,
    hoverinfo = 'none'
  ) %>%
  layout(
    title = list(
      text = '<b>Círculo de Correlaciones Interactivo</b>',
      font = list(size = 16)
    ),
    xaxis = list(
      title = paste0('PC1 (', round(eig.val$variance.percent[1], 1), '%)'),
      scaleanchor = "y",
      scaleratio = 1
    ),
    yaxis = list(
      title = paste0('PC2 (', round(eig.val$variance.percent[2], 1), '%)')
    ),
    showlegend = TRUE
  )

## 3. BIPLOT INTERACTIVO CON CLUSTERS
# Preparar datos de individuos (comunas)
ind_coord <- as.data.frame(res.pca$x[, 1:2])
ind_coord$ID_COMUNA <- rownames(ind_coord)
ind_coord$Cluster <- as.factor(km_final$cluster)

# Colores para clusters
colores_clusters <- c('#E31A1C', '#1F78B4', '#33A02C', '#FF7F00', '#6A3D9A')[1:num_clusters]

biplot_interactivo <- plot_ly() %>%
  # Individuos (comunas)
  add_trace(
    data = ind_coord,
    x = ~PC1,
    y = ~PC2,
    type = 'scatter',
    mode = 'markers',
    color = ~Cluster,
    colors = colores_clusters,
    marker = list(size = 10, opacity = 0.7, line = list(width = 1, color = 'white')),
    text = ~paste('<b>Comuna:</b>', ID_COMUNA,
                  '<br><b>Cluster:</b>', Cluster,
                  '<br><b>PC1:</b>', round(PC1, 3),
                  '<br><b>PC2:</b>', round(PC2, 3)),
    hoverinfo = 'text',
    name = 'Comunas'
  ) %>%
  # Variables
  add_trace(
    data = var_coord,
    x = ~PC1 * 2,  # Escalar para mejor visualización
    y = ~PC2 * 2,
    type = 'scatter',
    mode = 'markers+text',
    text = ~Variable,
    textposition = 'middle center',
    marker = list(
      size = 8,
      color = 'black',
      symbol = 'diamond'
    ),
    textfont = list(color = 'black', size = 11),
    hoverinfo = 'text',
    hovertext = ~paste('<b>Variable:</b>', Variable,
                      '<br><b>PC1:</b>', round(PC1, 3),
                      '<br><b>PC2:</b>', round(PC2, 3)),
    name = 'Variables',
    showlegend = FALSE
  ) %>%
  # Vectores de variables
  add_trace(
    data = var_coord,
    x = ~0,
    y = ~0,
    xend = ~PC1 * 2,
    yend = ~PC2 * 2,
    type = 'scatter',
    mode = 'lines',
    line = list(color = 'rgba(0,0,0,0.5)', width = 1.5),
    showlegend = FALSE,
    hoverinfo = 'none'
  ) %>%
  layout(
    title = list(
      text = '<b>Biplot Interactivo - Comunas y Variables</b>',
      font = list(size = 16)
    ),
    xaxis = list(
      title = paste0('PC1 (', round(eig.val$variance.percent[1], 1), '%)')
    ),
    yaxis = list(
      title = paste0('PC2 (', round(eig.val$variance.percent[2], 1), '%)')
    ),
    showlegend = TRUE,
    legend = list(
      title = list(text = '<b>Cluster</b>')
    )
  )

## 4. HEATMAP INTERACTIVO DE CARGAS PCA
cargas_matrix <- as.matrix(res.pca$rotation[, 1:num_comp_final])

heatmap_cargas <- plot_ly(
  x = colnames(cargas_matrix),
  y = rownames(cargas_matrix),
  z = cargas_matrix,
  type = 'heatmap',
  colorscale = 'RdBu',
  zmid = 0,
  colorbar = list(title = 'Carga'),
  hoverinfo = 'x+y+z',
  hovertemplate = paste(
    'Variable: %{y}<br>',
    'Componente: %{x}<br>',
    'Carga: %{z:.3f}<br>',
    '<extra></extra>'
  )
) %>%
  layout(
    title = list(
      text = '<b>Heatmap de Cargas PCA</b>',
      font = list(size = 16)
    ),
    xaxis = list(title = 'Componentes Principales'),
    yaxis = list(title = 'Variables', tickangle = -30),
    margin = list(l = 150)
  )

## 5. GRÁFICO 3D INTERACTIVO DE COMPONENTES
if(num_comp_final >= 3) {
  # Preparar datos 3D
  coord_3d <- as.data.frame(res.pca$x[, 1:3])
  coord_3d$ID_COMUNA <- rownames(coord_3d)
  coord_3d$Cluster <- as.factor(km_final$cluster)
  
  plot_3d <- plot_ly(
    data = coord_3d,
    x = ~PC1,
    y = ~PC2,
    z = ~PC3,
    type = 'scatter3d',
    mode = 'markers',
    color = ~Cluster,
    colors = colores_clusters,
    marker = list(size = 5, opacity = 0.8),
    text = ~paste('<b>Comuna:</b>', ID_COMUNA,
                  '<br><b>Cluster:</b>', Cluster,
                  '<br><b>PC1:</b>', round(PC1, 3),
                  '<br><b>PC2:</b>', round(PC2, 3),
                  '<br><b>PC3:</b>', round(PC3, 3)),
    hoverinfo = 'text'
  ) %>%
  layout(
    title = list(
      text = '<b>Visualización 3D - Primeros 3 Componentes</b>',
      font = list(size = 16)
    ),
    scene = list(
      xaxis = list(title = paste0('PC1 (', round(eig.val$variance.percent[1], 1), '%)')),
      yaxis = list(title = paste0('PC2 (', round(eig.val$variance.percent[2], 1), '%)')),
      zaxis = list(title = paste0('PC3 (', round(eig.val$variance.percent[3], 1), '%)'))
    )
  )
} else {
  plot_3d <- plot_ly() %>%
    layout(
      title = list(
        text = '<b>Visualización 3D No Disponible</b>',
        font = list(size = 16)
      ),
      annotations = list(
        list(
          text = "Se requieren al menos 3 componentes para visualización 3D",
          xref = "paper", yref = "paper",
          x = 0.5, y = 0.5, xanchor = "center", yanchor = "center",
          showarrow = FALSE
        )
      )
    )
}

## 6. TABLA INTERACTIVA DE CARGAS
# Crear tabla interactiva de cargas
cargas_interactiva <- cargas_matrix %>%
  as.data.frame() %>%
  rownames_to_column("Variable") %>%
  DT::datatable(
    rownames = FALSE,
    extensions = c('Buttons', 'Scroller'),
    options = list(
      dom = 'Bfrtip',
      buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
      pageLength = 10,
      scrollX = TRUE,
      scrollY = "400px",
      scroller = TRUE
    ),
    caption = htmltools::tags$caption(
      style = 'caption-side: top; text-align: center;',
      htmltools::strong('Tabla Interactiva de Cargas PCA')
    )
  ) %>%
  DT::formatRound(columns = 2:(ncol(cargas_matrix)+1), digits = 3)

## 7. GRÁFICO DE CONTRIBUCIÓN ACUMULADA INTERACTIVO
contrib_acumulada <- plot_ly(
  x = 1:length(eig.val$cumulative.variance.percent),
  y = eig.val$cumulative.variance.percent,
  type = 'scatter',
  mode = 'lines+markers',
  line = list(color = '#27AE60', width = 3),
  marker = list(size = 8, color = '#27AE60'),
  text = ~paste('Componentes: 1-', 1:length(eig.val$cumulative.variance.percent),
                '<br>Varianza Acumulada:', round(eig.val$cumulative.variance.percent, 2), '%'),
  hoverinfo = 'text'
) %>%
  add_trace(
    x = num_comp_final,
    y = eig.val$cumulative.variance.percent[num_comp_final],
    type = 'scatter',
    mode = 'markers',
    marker = list(size = 12, color = '#E74C3C', symbol = 'star'),
    name = paste('Selección (', num_comp_final, ' comp.)'),
    text = paste('Punto de corte:<br>', num_comp_final, 'componentes<br>',
                 round(eig.val$cumulative.variance.percent[num_comp_final], 2), '% varianza'),
    hoverinfo = 'text'
  ) %>%
  layout(
    title = list(
      text = '<b>Varianza Acumulada por Componentes</b>',
      font = list(size = 16)
    ),
    xaxis = list(
      title = 'Número de Componentes',
      tickvals = 1:length(eig.val$cumulative.variance.percent)
    ),
    yaxis = list(
      title = 'Varianza Acumulada (%)',
      range = c(0, 105)
    ),
    showlegend = FALSE,
    annotations = list(
      list(
        x = num_comp_final,
        y = eig.val$cumulative.variance.percent[num_comp_final] + 5,
        text = paste(num_comp_final, 'componentes'),
        showarrow = TRUE,
        arrowhead = 4,
        arrowsize = 1,
        ax = 0,
        ay = -40
      )
    )
  )

# ==========================================
# PANEL DE CONTROL INTERACTIVO
# ==========================================

cat("### Panel de Gráficos Interactivos PCA\n\n")
## ### Panel de Gráficos Interactivos PCA
cat("A continuación se presentan los gráficos interactivos del análisis de componentes principales:\n\n")
## A continuación se presentan los gráficos interactivos del análisis de componentes principales:
# Mostrar los gráficos en orden
cat("#### 1. Scree Plot Interactivo\n")
## #### 1. Scree Plot Interactivo
scree_interactivo
cat("\n#### 2. Círculo de Correlaciones Interactivo\n")
## 
## #### 2. Círculo de Correlaciones Interactivo
circulo_correlaciones
cat("\n#### 3. Biplot Interactivo con Clusters\n")
## 
## #### 3. Biplot Interactivo con Clusters
biplot_interactivo
cat("\n#### 4. Heatmap de Cargas PCA\n")
## 
## #### 4. Heatmap de Cargas PCA
heatmap_cargas
cat("\n#### 5. Visualización 3D de Componentes\n")
## 
## #### 5. Visualización 3D de Componentes
plot_3d
cat("\n#### 6. Varianza Acumulada Interactiva\n")
## 
## #### 6. Varianza Acumulada Interactiva
contrib_acumulada
cat("\n#### 7. Tabla Interactiva de Cargas\n")
## 
## #### 7. Tabla Interactiva de Cargas
cargas_interactiva
# ==========================================
# FUNCIONES DE EXPORTACIÓN
# ==========================================

# Función para exportar gráficos interactivos
exportar_graficos_interactivos <- function() {
  dir_interactivos <- file.path(dir_resultados, "Graficos_Interactivos")
  if(!dir.exists(dir_interactivos)) {
    dir.create(dir_interactivos)
  }
  
  # Exportar como HTML
  htmlwidgets::saveWidget(
    scree_interactivo,
    file.path(dir_interactivos, "01_scree_interactivo.html")
  )
  
  htmlwidgets::saveWidget(
    circulo_correlaciones,
    file.path(dir_interactivos, "02_circulo_correlaciones.html")
  )
  
  htmlwidgets::saveWidget(
    biplot_interactivo,
    file.path(dir_interactivos, "03_biplot_interactivo.html")
  )
  
  htmlwidgets::saveWidget(
    heatmap_cargas,
    file.path(dir_interactivos, "04_heatmap_cargas.html")
  )
  
  if(num_comp_final >= 3) {
    htmlwidgets::saveWidget(
      plot_3d,
      file.path(dir_interactivos, "05_visualizacion_3d.html")
    )
  }
  
  htmlwidgets::saveWidget(
    contrib_acumulada,
    file.path(dir_interactivos, "06_varianza_acumulada.html")
  )
  
  cat("✓ Gráficos interactivos exportados en:", dir_interactivos, "\n")
}

# Ejecutar exportación (opcional)
# exportar_graficos_interactivos()

cat("\n### Instrucciones de Uso:\n")
## 
## ### Instrucciones de Uso:
cat("- **Hover**: Pase el cursor sobre puntos para ver detalles\n")
## - **Hover**: Pase el cursor sobre puntos para ver detalles
cat("- **Zoom**: Use el mouse para hacer zoom en áreas específicas\n")
## - **Zoom**: Use el mouse para hacer zoom en áreas específicas
cat("- **Selección**: Click y arrastre para seleccionar regiones\n")
## - **Selección**: Click y arrastre para seleccionar regiones
cat("- **Reset**: Doble click para resetear la vista\n")
## - **Reset**: Doble click para resetear la vista
cat("- **Descarga**: Use el menú de herramientas para descargar imágenes\n")
## - **Descarga**: Use el menú de herramientas para descargar imágenes
cat("\n### Interpretación Interactiva:\n")
## 
## ### Interpretación Interactiva:
cat("1. **Scree Plot**: Identifique componentes con eigenvalue > 1 (línea roja)\n")
## 1. **Scree Plot**: Identifique componentes con eigenvalue > 1 (línea roja)
cat("2. **Círculo de Correlaciones**: Variables cerca del círculo están bien representadas\n")
## 2. **Círculo de Correlaciones**: Variables cerca del círculo están bien representadas
cat("3. **Biplot**: Relacione comunas (puntos) con variables (vectores)\n")
## 3. **Biplot**: Relacione comunas (puntos) con variables (vectores)
cat("4. **Heatmap**: Identifique variables más influyentes en cada componente\n")
## 4. **Heatmap**: Identifique variables más influyentes en cada componente
cat("5. **3D**: Explore relaciones tridimensionales entre componentes\n")
## 5. **3D**: Explore relaciones tridimensionales entre componentes

20 Análisis territorial

# ==============================================================================
# ANÁLISIS TERRITORIAL COMPLETO Y MEJORADO - PROYECTOS ACA ESTADO MÉRIDA
# ==============================================================================

# Resolver conflictos
conflicts_prefer(dplyr::first)
conflict_prefer("select", "dplyr")
conflict_prefer("filter", "dplyr")

# ==============================================================================
# FASE 1: CONFIGURACIÓN ESTÉTICA PROFESIONAL
# ==============================================================================

# Tema cartográfico profesional mejorado
tema_mapa_profesional <- theme_void() +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5, 
                             color = "#2c3e50", margin = margin(b = 15)),
    plot.subtitle = element_text(size = 14, hjust = 0.5, color = "#34495e", 
                                margin = margin(b = 20)),
    plot.caption = element_text(size = 11, hjust = 1, color = "#7f8c8d", 
                               margin = margin(t = 15)),
    legend.position = "right",
    legend.title = element_text(face = "bold", size = 12, color = "#2c3e50"),
    legend.text = element_text(size = 11, color = "#34495e"),
    legend.key.size = unit(1.2, "cm"),
    legend.margin = margin(l = 20),
    panel.background = element_rect(fill = "#f8f9fa", color = NA),
    plot.background = element_rect(fill = "white", color = NA),
    plot.margin = margin(25, 25, 25, 25),
    # Mejora para los elementos de escala y norte
    axis.title = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank()
  )

# Paleta de colores sofisticada y consistente
colores_estado_merida <- c(
  "Urbana" = "#1f77b4",           # Azul institucional
  "Rural" = "#d62728",            # Rojo terroso
  "Mixta" = "#ff7f0e",            # Naranja vibrante
  "En construcción" = "#2ca02c",  # Verde progreso
  "No especificado" = "#9467bd"   # Púrpura neutro
)

# Función para bordes del estado más visibles
crear_borde_estado <- function(shapefile_estado) {
  geom_sf(data = shapefile_estado, 
          fill = NA, 
          color = "#34495e", 
          size = 1.2, 
          linetype = "solid")
}

# ==============================================================================
# FASE 2: CARGA Y PREPARACIÓN DE DATOS MEJORADA
# ==============================================================================

cat("================================================================================\n")
## ================================================================================
cat("INICIANDO ANÁLISIS TERRITORIAL INTEGRAL - VERSIÓN MEJORADA\n")
## INICIANDO ANÁLISIS TERRITORIAL INTEGRAL - VERSIÓN MEJORADA
cat("================================================================================\n")
## ================================================================================
# Cargar todos los shapefiles con verificación
cat("Cargando shapefiles del Estado Mérida...\n")
## Cargando shapefiles del Estado Mérida...
# 1. Parroquias (base principal)
parroquias_sf <- st_read("C:/Users/william/Desktop/monografia aca merida/datos/MERIDA/DPT_PARROQUIAl/merida.shx", quiet = TRUE)
cat("✓ Parroquias cargadas:", nrow(parroquias_sf), "registros\n")
## ✓ Parroquias cargadas: 86 registros
# 2. Municipios
municipios_sf <- st_read("C:/Users/william/Desktop/monografia aca merida/datos/MERIDA/DPT_MUNICIPAL/merida_mun.shx", quiet = TRUE)
cat("✓ Municipios cargados:", nrow(municipios_sf), "registros\n")
## ✓ Municipios cargados: 23 registros
# 3. Centros poblados
centros_sf <- st_read("C:/Users/william/Desktop/monografia aca merida/datos/MERIDA/merida.shx", quiet = TRUE)
cat("✓ Centros poblados cargados:", nrow(centros_sf), "registros\n")
## ✓ Centros poblados cargados: 86 registros
# 4. Estado completo (para bordes)
estados_sf <- st_read("C:/Users/william/Desktop/monografia aca merida/datos/MERIDA/DPT_ESTADO/vzla_estados.shx", quiet = TRUE)
merida_estado <- estados_sf %>% filter(ESTADO == "MERIDA")
cat("✓ Límites estatales cargados\n")
## ✓ Límites estatales cargados
# Preparar datos de proyectos con mejoras
df_raw$COD_UBIGEO <- as.character(df_raw$COD_UBIGEO)

# Clasificación mejorada de tipos de comuna
df_raw <- df_raw %>%
  mutate(
    Tipo_Comuna = case_when(
      str_detect(COD_CC, "C-URB") ~ "Urbana",
      str_detect(COD_CC, "C-RUR") ~ "Rural", 
      str_detect(COD_CC, "C-MIX") ~ "Mixta",
      str_detect(COD_CC, "^\\d{2}-\\d{2}-\\d{4}$") ~ "En construcción",
      str_detect(COD_CC, "^\\d{2}-\\d{2}-\\d{2}") ~ "En construcción",
      str_detect(COD_CC, "^CEC") ~ "En construcción",
      TRUE ~ "No especificado"
    ),
    # Variables auxiliares para análisis territorial
    Codigo_Municipal = str_sub(COD_UBIGEO, 1, 4),
    Intensidad_Proyectos = case_when(
      n_proyectos >= 4 ~ "Alta (4+)",
      n_proyectos == 3 ~ "Media (3)",
      n_proyectos <= 2 ~ "Baja (≤2)"
    ),
    Efectividad_Categoria = case_when(
      RATIO_ACA_PROYECTO_CULMINADO >= 4 ~ "Muy Alta",
      RATIO_ACA_PROYECTO_CULMINADO == 3 ~ "Alta",
      RATIO_ACA_PROYECTO_CULMINADO == 2 ~ "Media", 
      RATIO_ACA_PROYECTO_CULMINADO == 1 ~ "Baja"
    )
  )

# ==============================================================================
# FASE 3: MAPAS BÁSICOS MEJORADOS CON BORDES DEL ESTADO
# ==============================================================================

cat("\n--- CREANDO MAPAS BÁSICOS MEJORADOS ---\n")
## 
## --- CREANDO MAPAS BÁSICOS MEJORADOS ---
# Unión principal con estadísticas mejoradas
parroquias_proyectos <- parroquias_sf %>%
  left_join(df_raw, by = c("ID" = "COD_UBIGEO")) %>%
  # Agregar estadísticas por parroquia
  group_by(ID) %>%
  mutate(
    proyectos_parroquia = n(),
    diversidad_tipologias = n_distinct(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG, na.rm = TRUE),
    ratio_promedio = mean(RATIO_ACA_PROYECTO_CULMINADO, na.rm = TRUE)
  ) %>%
  ungroup()

# MAPA 1: Distribución de proyectos con bordes mejorados
mapa_distribucion_pro <- ggplot() +
  # Base: Parroquias con proyectos
  geom_sf(data = parroquias_proyectos, 
          aes(fill = n_proyectos), 
          color = "white", 
          size = 0.2) +
  # Borde del Estado Mérida más visible
  geom_sf(data = merida_estado, 
          fill = NA, 
          color = "#2c3e50", 
          size = 1.5, 
          linetype = "solid") +
  # Escala de colores mejorada
  scale_fill_viridis_c(
    name = "N° Proyectos\nACA",
    option = "plasma",
    na.value = "grey95",
    trans = "sqrt",
    breaks = pretty_breaks(n = 5),
    labels = function(x) round(x, 0),
    guide = guide_colorbar(
      title.position = "top",
      barwidth = 1.5,
      barheight = 12,
      frame.colour = "#34495e",
      frame.linewidth = 0.5
    )
  ) +
  # Elementos cartográficos mejorados
  annotation_scale(
    location = "br", 
    width_hint = 0.3,
    text_cex = 1.1,
    text_face = "bold",
    text_col = "#2c3e50",
    bar_cols = c("#2c3e50", "white")
  ) +
  annotation_north_arrow(
    location = "tl", 
    style = north_arrow_fancy_orienteering,
    height = unit(1.8, "cm"), 
    width = unit(1.8, "cm")
  ) +
  labs(
    title = "Distribución Territorial de Proyectos ACA",
    subtitle = "Estado Mérida por Parroquia (2019-2025) • Análisis de Cobertura Territorial",
    caption = "Fuente: Elaboración propia • William A. Gutiérrez V. • Datos: Agendas Concretas de Acción"
  ) +
  tema_mapa_profesional

print(mapa_distribucion_pro)

# MAPA 2: Efectividad territorial con mejoras
mapa_efectividad_pro <- ggplot() +
  geom_sf(data = parroquias_proyectos, 
          aes(fill = RATIO_ACA_PROYECTO_CULMINADO), 
          color = "white", 
          size = 0.2) +
  geom_sf(data = merida_estado, 
          fill = NA, 
          color = "#2c3e50", 
          size = 1.5) +
  scale_fill_gradient2(
    name = "Ratio de\nEfectividad",
    low = "#d73027", 
    mid = "#fee08b", 
    high = "#1a9850",
    midpoint = 2.5,
    na.value = "grey95",
    breaks = 1:4,
    labels = c("Baja (1)", "Media (2)", "Alta (3)", "Muy Alta (4)"),
    guide = guide_colorbar(
      title.position = "top",
      barwidth = 1.5,
      barheight = 12,
      frame.colour = "#34495e",
      frame.linewidth = 0.5
    )
  ) +
  annotation_scale(location = "br", width_hint = 0.3, text_cex = 1.1, text_face = "bold") +
  annotation_north_arrow(location = "tl", style = north_arrow_fancy_orienteering,
                         height = unit(1.8, "cm"), width = unit(1.8, "cm")) +
  labs(
    title = "Efectividad Territorial de Proyectos ACA",
    subtitle = "Ratio de Culminación por Parroquia • Análisis de Resultados",
    caption = "Fuente: Elaboración propia • William A. Gutiérrez V. • Escala: 1 (Baja) a 4 (Muy Alta)"
  ) +
  tema_mapa_profesional

print(mapa_efectividad_pro)

# MAPA 3: Tipos de comuna con estadísticas integradas
mapa_tipos_comuna_pro <- ggplot() +
  geom_sf(data = parroquias_proyectos %>% filter(!is.na(Tipo_Comuna)), 
          aes(fill = Tipo_Comuna), 
          color = "white", 
          size = 0.2) +
  geom_sf(data = merida_estado, 
          fill = NA, 
          color = "#2c3e50", 
          size = 1.5) +
  scale_fill_manual(
    name = "Tipo de\nComuna",
    values = colores_estado_merida,
    na.value = "grey95",
    guide = guide_legend(
      title.position = "top",
      keywidth = unit(1.5, "cm"),
      keyheight = unit(1, "cm"),
      override.aes = list(size = 0)
    )
  ) +
  annotation_scale(location = "br", width_hint = 0.3, text_cex = 1.1, text_face = "bold") +
  annotation_north_arrow(location = "tl", style = north_arrow_fancy_orienteering,
                         height = unit(1.8, "cm"), width = unit(1.8, "cm")) +
  labs(
    title = "Clasificación Territorial de Comunas",
    subtitle = "Tipología Organizacional del Estado Mérida • Análisis Institucional",
    caption = "Fuente: Elaboración propia • Clasificación basada en códigos de comuna"
  ) +
  tema_mapa_profesional

print(mapa_tipos_comuna_pro)

# ==============================================================================
# FASE 4: MAPAS AVANZADOS Y ANÁLISIS MULTI-ESCALA
# ==============================================================================

cat("\n--- CREANDO MAPAS AVANZADOS ---\n")
## 
## --- CREANDO MAPAS AVANZADOS ---
# MAPA 4: Análisis municipal con población
datos_municipales <- df_raw %>%
  mutate(Codigo_Municipal = str_sub(COD_UBIGEO, 1, 4)) %>%
  group_by(Codigo_Municipal) %>%
  summarise(
    total_proyectos = n(),
    total_comunas = n_distinct(ID_COMUNA),
    ratio_promedio = mean(RATIO_ACA_PROYECTO_CULMINADO, na.rm = TRUE),
    tipo_comuna_dominante = names(sort(table(Tipo_Comuna), decreasing = TRUE))[1],
    .groups = "drop"
  )

municipios_enriquecidos <- municipios_sf %>%
  left_join(datos_municipales, by = c("ID_MUNICIP" = "Codigo_Municipal"))

mapa_municipal_pro <- ggplot() +
  geom_sf(data = municipios_enriquecidos, 
          aes(fill = total_proyectos), 
          color = "white", 
          size = 0.4) +
  geom_sf(data = merida_estado, 
          fill = NA, 
          color = "#2c3e50", 
          size = 1.5) +
  geom_sf_text(data = municipios_enriquecidos %>% filter(!is.na(total_proyectos)), 
               aes(label = str_wrap(FIRST_MUNI, 12)), 
               size = 3, color = "#2c3e50", fontface = "bold",
               check_overlap = TRUE) +
  scale_fill_gradient2(
    name = "Proyectos\nACA",
    low = "#eff3ff", 
    mid = "#6baed6", 
    high = "#08519c",
    midpoint = median(municipios_enriquecidos$total_proyectos, na.rm = TRUE),
    na.value = "grey95",
    guide = guide_colorbar(
      title.position = "top",
      barwidth = 1.5,
      barheight = 12
    )
  ) +
  annotation_scale(location = "br", width_hint = 0.3, text_cex = 1.1, text_face = "bold") +
  annotation_north_arrow(location = "tl", style = north_arrow_fancy_orienteering,
                         height = unit(1.8, "cm"), width = unit(1.8, "cm")) +
  labs(
    title = "Distribución Municipal de Proyectos ACA",
    subtitle = "Análisis Regional • 23 Municipios del Estado Mérida",
    caption = "Fuente: Elaboración propia • Incluye nombres municipales para referencia geográfica"
  ) +
  tema_mapa_profesional

print(mapa_municipal_pro)

# MAPA 5: Mapa de densidad con centros poblados
centros_con_datos <- centros_sf %>%
  mutate(
    COD_PARROQUIA = str_pad(str_sub(as.character(CODIGO_CP), 1, 6), 6, pad = "0")
  ) %>%
  left_join(
    parroquias_proyectos %>% 
      st_drop_geometry() %>%
      group_by(ID) %>%
      summarise(
        proyectos_parroquia = first(n_proyectos),
        efectividad_parroquia = first(RATIO_ACA_PROYECTO_CULMINADO),
        tipo_comuna_parroquia = first(Tipo_Comuna),
        .groups = "drop"
      ),
    by = c("COD_PARROQUIA" = "ID")
  ) %>%
  filter(!is.na(proyectos_parroquia))

mapa_densidad_pro <- ggplot() +
  geom_sf(data = parroquias_proyectos, 
          aes(fill = n_proyectos), 
          color = "white", 
          size = 0.1, 
          alpha = 0.7) +
  geom_sf(data = centros_con_datos, 
          aes(size = proyectos_parroquia, 
              color = efectividad_parroquia), 
          alpha = 0.8) +
  geom_sf(data = merida_estado, 
          fill = NA, 
          color = "#2c3e50", 
          size = 1.5) +
  scale_fill_viridis_c(
    name = "Proyectos\n(Base)",
    option = "plasma",
    na.value = "grey95",
    trans = "sqrt",
    guide = guide_colorbar(
      title.position = "top",
      barwidth = 1,
      barheight = 8
    )
  ) +
  scale_size_continuous(
    name = "Intensidad\n(Puntos)",
    range = c(1, 4),
    guide = guide_legend(
      title.position = "top",
      override.aes = list(color = "#2c3e50")
    )
  ) +
  scale_color_gradient2(
    name = "Efectividad\n(Color)",
    low = "#d73027", 
    mid = "#fee08b", 
    high = "#1a9850",
    midpoint = 2.5,
    guide = guide_colorbar(
      title.position = "top",
      barwidth = 1,
      barheight = 8
    )
  ) +
  annotation_scale(location = "br", width_hint = 0.25, text_cex = 1, text_face = "bold") +
  annotation_north_arrow(location = "tl", style = north_arrow_fancy_orienteering,
                         height = unit(1.5, "cm"), width = unit(1.5, "cm")) +
  labs(
    title = "Análisis Multi-escala: Parroquias y Centros Poblados",
    subtitle = "Densidad Territorial • Doble Representación Espacial",
    caption = "Fuente: Elaboración propia • Base: Parroquias, Overlay: Centros poblados"
  ) +
  tema_mapa_profesional +
  theme(legend.box = "vertical")

print(mapa_densidad_pro)

# ==============================================================================
# FASE 5: MAPAS COMPLEMENTARIOS CON NUEVOS ANÁLISIS
# ==============================================================================

# MAPA 6: Diversidad de tipologías por territorio
diversidad_parroquial <- parroquias_proyectos %>%
  st_drop_geometry() %>%
  filter(!is.na(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG)) %>%
  group_by(ID, PARROQUIA, MUNICIPIO) %>%
  summarise(
    n_proyectos = n(),
    diversidad_tipologias = n_distinct(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG),
    shannon_tipologia = vegan::diversity(table(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG)),
    tipologia_principal = names(sort(table(CLASIFICACIÓN_DEL_NUDO_CRITICO_TIPOLOGIA_CFG), 
                                   decreasing = TRUE))[1],
    .groups = "drop"
  )

parroquias_diversidad <- parroquias_sf %>%
  left_join(diversidad_parroquial, by = "ID")

mapa_diversidad_pro <- ggplot() +
  geom_sf(data = parroquias_diversidad, 
          aes(fill = shannon_tipologia), 
          color = "white", 
          size = 0.2) +
  geom_sf(data = merida_estado, 
          fill = NA, 
          color = "#2c3e50", 
          size = 1.5) +
  scale_fill_viridis_c(
    name = "Diversidad\nShannon\n(H')",
    option = "cividis",
    na.value = "grey95",
    breaks = pretty_breaks(n = 5),
    guide = guide_colorbar(
      title.position = "top",
      barwidth = 1.5,
      barheight = 12
    )
  ) +
  annotation_scale(location = "br", width_hint = 0.3, text_cex = 1.1, text_face = "bold") +
  annotation_north_arrow(location = "tl", style = north_arrow_fancy_orienteering,
                         height = unit(1.8, "cm"), width = unit(1.8, "cm")) +
  labs(
    title = "Diversidad de Nudos Críticos por Territorio",
    subtitle = "Índice de Shannon para Tipologías CFG • Análisis de Variedad Temática",
    caption = "Fuente: Elaboración propia • Valores altos = mayor diversidad problemática"
  ) +
  tema_mapa_profesional

print(mapa_diversidad_pro)

# ==============================================================================
# FASE 6: PANEL INTEGRADO Y COMPARATIVO
# ==============================================================================

cat("\n--- CREANDO PANEL COMPARATIVO FINAL ---\n")
## 
## --- CREANDO PANEL COMPARATIVO FINAL ---
# Crear panel de 2x3 con los mejores mapas
panel_territorial <- (mapa_distribucion_pro + mapa_efectividad_pro) / 
                    (mapa_tipos_comuna_pro + mapa_municipal_pro) /
                    (mapa_densidad_pro + mapa_diversidad_pro)

panel_territorial <- panel_territorial + 
  plot_annotation(
    title = "ANÁLISIS TERRITORIAL INTEGRAL - PROYECTOS ACA ESTADO MÉRIDA",
    subtitle = "Distribución, Efectividad, Tipologías y Análisis Multi-escala",
    caption = "Elaboración: William A. Gutiérrez V. | Fuente: Agendas Concretas de Acción 2019-2025",
    theme = theme(
      plot.title = element_text(size = 20, face = "bold", hjust = 0.5, color = "#2c3e50"),
      plot.subtitle = element_text(size = 16, hjust = 0.5, color = "#34495e"),
      plot.caption = element_text(size = 12, hjust = 1, color = "#7f8c8d")
    )
  )

print(panel_territorial)

# ==============================================================================
# FASE 7: ESTADÍSTICAS Y RESUMEN FINAL
# ==============================================================================

cat("\n--- GENERANDO ESTADÍSTICAS TERRITORIALES ---\n")
## 
## --- GENERANDO ESTADÍSTICAS TERRITORIALES ---
# Estadísticas comprehensivas
estadisticas_territoriales <- list(
  cobertura_general = parroquias_proyectos %>%
    st_drop_geometry() %>%
    summarise(
      total_parroquias = n_distinct(ID),
      parroquias_con_proyectos = sum(!is.na(n_proyectos)),
      cobertura_pct = round(parroquias_con_proyectos / total_parroquias * 100, 1),
      total_proyectos = sum(n_proyectos, na.rm = TRUE)
    ),
  
  por_tipo_comuna = parroquias_proyectos %>%
    st_drop_geometry() %>%
    filter(!is.na(Tipo_Comuna)) %>%
    group_by(Tipo_Comuna) %>%
    summarise(
      n_parroquias = n_distinct(ID),
      total_proyectos = n(),
      proyectos_promedio = round(mean(n_proyectos, na.rm = TRUE), 2),
      efectividad_promedio = round(mean(RATIO_ACA_PROYECTO_CULMINADO, na.rm = TRUE), 2),
      .groups = "drop"
    ),
  
  ranking_parroquias = parroquias_proyectos %>%
    st_drop_geometry() %>%
    filter(!is.na(n_proyectos)) %>%
    arrange(desc(n_proyectos)) %>%
    head(10) %>%
    select(PARROQUIA, MUNICIPIO, n_proyectos, RATIO_ACA_PROYECTO_CULMINADO, Tipo_Comuna)
)

# Mostrar estadísticas
cat("\n=== RESUMEN ESTADÍSTICO TERRITORIAL ===\n")
## 
## === RESUMEN ESTADÍSTICO TERRITORIAL ===
cat("Cobertura:", estadisticas_territoriales$cobertura_general$cobertura_pct, "%\n")
## Cobertura: 216.3 %
cat("Proyectos totales:", estadisticas_territoriales$cobertura_general$total_proyectos, "\n")
## Proyectos totales: 694
print(estadisticas_territoriales$por_tipo_comuna)
## # A tibble: 4 × 5
##   Tipo_Comuna     n_parroquias total_proyectos proyectos_promedio
##   <chr>                  <int>           <int>              <dbl>
## 1 En construcción           14              64               3.59
## 2 Mixta                     15              77               3.81
## 3 Rural                      6              30               3.8 
## 4 Urbana                     5              15               3.8 
## # ℹ 1 more variable: efectividad_promedio <dbl>
print(estadisticas_territoriales$ranking_parroquias)
## # A tibble: 10 × 5
##    PARROQUIA            MUNICIPIO n_proyectos RATIO_ACA_PROYECTO_C…¹ Tipo_Comuna
##    <chr>                <chr>           <dbl>                  <dbl> <chr>      
##  1 PRESIDENTE BETANCOU… ALBERTO …           4                      1 Mixta      
##  2 PRESIDENTE BETANCOU… ALBERTO …           4                      1 Mixta      
##  3 PRESIDENTE BETANCOU… ALBERTO …           4                      1 Mixta      
##  4 PRESIDENTE BETANCOU… ALBERTO …           4                      4 Urbana     
##  5 PRESIDENTE BETANCOU… ALBERTO …           4                      4 Urbana     
##  6 PRESIDENTE BETANCOU… ALBERTO …           4                      4 Urbana     
##  7 PRESIDENTE BETANCOU… ALBERTO …           4                      1 Rural      
##  8 PRESIDENTE BETANCOU… ALBERTO …           4                      4 Rural      
##  9 PRESIDENTE BETANCOU… ALBERTO …           4                      1 Rural      
## 10 PRESIDENTE PAEZ      ALBERTO …           4                      3 En constru…
## # ℹ abbreviated name: ¹​RATIO_ACA_PROYECTO_CULMINADO
# Exportar mapas mejorados
ggsave("mapa_01_distribucion_profesional.png", mapa_distribucion_pro, 
       width = 14, height = 11, dpi = 300, bg = "white")
ggsave("mapa_02_efectividad_profesional.png", mapa_efectividad_pro, 
       width = 14, height = 11, dpi = 300, bg = "white")
ggsave("mapa_03_tipos_comuna_profesional.png", mapa_tipos_comuna_pro, 
       width = 14, height = 11, dpi = 300, bg = "white")
ggsave("mapa_04_municipal_profesional.png", mapa_municipal_pro, 
       width = 14, height = 11, dpi = 300, bg = "white")
ggsave("mapa_05_densidad_profesional.png", mapa_densidad_pro, 
       width = 16, height = 12, dpi = 300, bg = "white")
ggsave("mapa_06_diversidad_profesional.png", mapa_diversidad_pro, 
       width = 14, height = 11, dpi = 300, bg = "white")
ggsave("panel_territorial_completo.png", panel_territorial, 
       width = 24, height = 18, dpi = 300, bg = "white")

cat("\n================================================================================\n")
## 
## ================================================================================
cat("ANÁLISIS TERRITORIAL PROFESIONAL COMPLETADO EXITOSAMENTE\n")
## ANÁLISIS TERRITORIAL PROFESIONAL COMPLETADO EXITOSAMENTE
cat("================================================================================\n")
## ================================================================================
cat("MAPAS GENERADOS:\n")
## MAPAS GENERADOS:
cat("1. Distribución territorial con bordes mejorados\n")
## 1. Distribución territorial con bordes mejorados
cat("2. Efectividad territorial con escala mejorada\n") 
## 2. Efectividad territorial con escala mejorada
cat("3. Tipos de comuna con colores profesionales\n")
## 3. Tipos de comuna con colores profesionales
cat("4. Análisis municipal con etiquetas\n")
## 4. Análisis municipal con etiquetas
cat("5. Análisis multi-escala (parroquias + centros)\n")
## 5. Análisis multi-escala (parroquias + centros)
cat("6. Diversidad de tipologías (Shannon)\n")
## 6. Diversidad de tipologías (Shannon)
cat("7. Panel territorial integrado (2x3)\n")
## 7. Panel territorial integrado (2x3)
cat("================================================================================\n")
## ================================================================================

Estoy creando un HTML a través de R Markdown para la exposición de mis pasantías, de mis resultados de la tesis monografía que desarrolle, me puedes ayudar a plantear la sección de analisis territorial para colocarla en ese HTML que será mi instrumento para la exposición, como podría construir digamos ese analisis territorial , viendo el código y viendo el texto que los interpreta, para hacerlo en ese HTML y que pueda expresar lo mas interesante que conseguí en la tesis monografica, puedes ayudarme a interpretar de forma concisa este analisis territorial , estoy planteando así las diapositivas digamos en el html, presento una introducción corta, las graficas interactivas junto con las tablas, e interpreto los resultados concisos como para una diapositiva, me puedes ayudar con ese analisis territorial, este es mi codigo con imagenes fijas, quiero darte ademas la estructura de los shapefile, para mejorar los mapas interactivos o cualquier optimización:

##Mapas interactivos

Síntesis de Resultados

Distribución desigual: 65% de proyectos concentrados en 30% del territorio, principalmente en eje urbano Mérida-Ejido

Efectividad diferenciada: Comunas urbanas muestran 40% mayor efectividad que rurales

Diversidad correlacionada: Mayor número de proyectos = mayor diversidad tipológica (ρ = 0.82 en zonas mixtas)

Segmentación territorial clara: Urbano (alta densidad), Rural (enfoque específico), Mixto (comportamiento intermedio)

Brecha de planificación: Correlación perfecta diagnóstico-gestión en electricidad (ρ = 1.0) vs desconexión en otros sectores

Patrón centro-periferia: Disminución progresiva de proyectos desde núcleos urbanos hacia áreas rurales

Oportunidad réplica: Modelos exitosos en comunas mixtas pueden escalarse a contextos similares

Priorización necesaria: 4 tipologías concentran 62.6% de nudos críticos, indicando focos de intervención

Eficiencia territorial: Zonas con clusters de centros poblados muestran mejor coordinación institucional

Política diferenciada: Urge adaptar estrategias por tipo comuna para maximizar impacto

## Iniciando preparación de datos espaciales...
## ✓ Parroquias transformadas a WGS84 y textos limpiados
## ✓ Municipios transformados a WGS84 y textos limpiados
## ✓ Centros poblados transformados a WGS84 y textos limpiados
## ✓ Estado Mérida transformado a WGS84
## ✓ Todos los shapefiles transformados a WGS84 correctamente
## Preparando datos para mapas interactivos...
## ✓ Datos preparados para mapas interactivos
## Creando Mapa 1: Distribución territorial...
## Rango de proyectos por parroquia: 0 - 20
## Creando Mapa 2: Efectividad y diversidad...
## Creando Mapa 3: Tipos de comuna...
## Tipos de comuna encontrados: Rural, Mixta, En construccion, Urbana
## Mostrando resultados...
## ### Mapa 1: Distribución Territorial
## ### Mapa 2: Efectividad y Diversidad
## ### Mapa 3: Tipos de Comuna
## ### Resumen Estadístico del Análisis
Resumen General del Análisis de Agendas Concretas de Acción - Estado Mérida 2019-2025
Métrica Valor
Total Proyectos Analizados 198.00
Comunas Evaluadas 59.00
Parroquias con Proyectos 30.00
Efectividad Promedio General 2.26
Tipologías Diferentes Identificadas 16.00
Municipios Involucrados 13.00
## 
## --- ANÁLISIS COMPLETADO ---
## Se han generado 3 mapas interactivos
LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZSBBZ2VuZGFzIENvbmNyZXRhcyBkZSBBY2Npw7NuIChBQ0EpIg0Kc3VidGl0bGU6ICJFc3RhZG8gTcOpcmlkYSwgVmVuZXp1ZWxhIHwgUHJlc2VudGFjacOzbiBJbnRlcmFjdGl2YSBkZSBSZXN1bHRhZG9zIg0KYXV0aG9yOiAiV2lsbGlhbSBBLiBHdXRpw6lycmV6IFYuIg0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQgZGUgJUIsICVZJylgIg0KDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlICAgICAgIyBDQU1CSUFSIGEgdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgdGhlbWU6IGZsYXRseSAgICAgICAgICAgICANCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgZmlnX3dpZHRoOiAxMg0KICAgIGZpZ19oZWlnaHQ6IDgNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyA9IFRSVUUsDQogIHdhcm5pbmcgPSBGQUxTRSwNCiAgbWVzc2FnZSA9IEZBTFNFLA0KICBmaWcuYWxpZ24gPSAnY2VudGVyJywNCiAgb3V0LndpZHRoID0gJzk1JScNCikNCg0KDQpsaWJyYXJ5KHBsb3RseSkNClN5cy5zZXRlbnYoIlBMT1RMWV9BUElfS0VZIiA9ICIiKQ0KU3lzLnNldGVudigiUExPVExZX1VTRVJOQU1FIiA9ICIiKQ0KDQpsaWJyYXJ5KERUKSAgICAgICAgICANCmxpYnJhcnkobGVhZmxldCkgICAgIA0KbGlicmFyeShoaWdoY2hhcnRlcikgDQpsaWJyYXJ5KGNyb3NzdGFsaykgICANCmxpYnJhcnkoaHRtbHdpZGdldHMpIA0KbGlicmFyeShodG1sdG9vbHMpICAgDQpsaWJyYXJ5KHJlYWR4bCkgICANCmxpYnJhcnkoZHBseXIpICAgIA0KbGlicmFyeSh3cml0ZXhsKQ0KbGlicmFyeShyZXNoYXBlMikNCmxpYnJhcnkodmVnYW4pDQpsaWJyYXJ5KHBlcm11dGUpDQpsaWJyYXJ5KGZhc3REdW1taWVzKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KEFFUikNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoY2FyRGF0YSkNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkocHVycnIpDQpsaWJyYXJ5KGNvd3Bsb3QpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkodmlyaWRpcykNCmxpYnJhcnkoZ2dzcGF0aWFsKQ0KbGlicmFyeShnZ3B1YnIpDQpsaWJyYXJ5KG5vcnRlc3QpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkodGliYmxlKQ0KbGlicmFyeShyZXNoYXBlMikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZm9ybWF0dGFibGUpDQpsaWJyYXJ5KERUKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkoZ2dyaWRnZXMpDQpsaWJyYXJ5KHRyZWVtYXBpZnkpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoaWdyYXBoKQ0KbGlicmFyeShnZ3JhcGgpDQpsaWJyYXJ5KGdnZGVuZHJvKQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KHBoZWF0bWFwKQ0KbGlicmFyeShncmlkKQ0KbGlicmFyeShjbHVzdGVyKSAgDQpsaWJyYXJ5KG1jbHVzdCkNCmxpYnJhcnkoRFQpICAgIA0KbGlicmFyeShmYWN0b2V4dHJhKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShnZ2VmZmVjdHMpDQpsaWJyYXJ5KG1hcmdpbnMpDQpsaWJyYXJ5KHRtYXApDQpsaWJyYXJ5KHNwKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KbGlicmFyeShiaXNjYWxlKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KbGlicmFyeShsZWFmbGV0KQ0KbGlicmFyeShsZWFmbGV0LmV4dHJhcykNCg0KY29uZmxpY3RfcHJlZmVyKCJzZWxlY3QiLCAiZHBseXIiKQ0KY29uZmxpY3RfcHJlZmVyKCJmaWx0ZXIiLCAiZHBseXIiKQ0KY29uZmxpY3RfcHJlZmVyKCJsYXlvdXQiLCAicGxvdGx5IikNCmNvbmZsaWN0X3ByZWZlcigiYWRkX3RyYWNlIiwgInBsb3RseSIpDQpjb25mbGljdF9wcmVmZXIoImdyb3VwX3Jvd3MiLCAia2FibGVFeHRyYSIpDQpgYGANCg0KIyMgKipEZXNhcnJvbGxhbW9zIGxhcyBlc3RpbWFjaW9uZXMgZGUgbGFzIHRpcG9sb2fDrWFzIGRlIHByb3llY3RvcyoqDQoNCkxhIFRhYmxhIDEgcHJlc2VudGEgbG9zIHByaW1lcm9zIDEwIHJlZ2lzdHJvcyBkZWwgZGF0YXNldCBvcmlnaW5hbCwgcXVlIGlsdXN0cmFuIGxhIHZhcmllZGFkIGRlIG51ZG9zIGNyw610aWNvcyBpZGVudGlmaWNhZG9zIGVuIGxhcyBjb211bmFzIGRlbCBFc3RhZG8gTcOpcmlkYSBkdXJhbnRlIGVsIHBlcsOtb2RvIGRlIGVzdHVkaW8uIFNlIG9ic2VydmEgcXVlIGxhIGNvbXVuYSAiU0lNT04gQk9Mw41WQVIiIHJlZ2lzdHLDsyB0cmVzIG51ZG9zIGNyw610aWNvcyBkaWZlcmVudGVzIGJham8gZWwgbWlzbW8gY8OzZGlnbyBkZSB1YmljYWNpw7NuIGdlb2dyw6FmaWNhIChVQklHRU8gMTQwMTAyKSB5IGPDs2RpZ28gZGUgY2lyY3VpdG8gY29tdW5hbCAoQ0MgMTQtMDEtMjAwNyk6IGluZnJhZXN0cnVjdHVyYSAoZHJlbmFqZXMpLCBlbGVjdHJpY2lkYWQgeSB0ZWxlY29tdW5pY2FjaW9uZXMuIEVzdGEgbXVsdGlwbGljaWRhZCBkZSBwcm9ibGVtw6F0aWNhcyBzdWdpZXJlIHF1ZSBlc3RhIGNvbXVuYSBlbmZyZW50YSBkZXNhZsOtb3Mgc2ltdWx0w6FuZW9zIGVuIG3Dumx0aXBsZXMgZnJlbnRlcywgbG8gcXVlIHBvZHLDrWEgcmVxdWVyaXIgdW5hIGludGVydmVuY2nDs24gY29vcmRpbmFkYSB5IG11bHRpc2VjdG9yaWFsLg0KDQpFbCBzaXN0ZW1hIGRlIGNvZGlmaWNhY2nDs24gdXRpbGl6YWRvIGV2aWRlbmNpYSBsYSBlc3RydWN0dXJhIGplcsOhcnF1aWNhIGRlIGxhIHBsYW5pZmljYWNpw7NuIHRlcnJpdG9yaWFsLiBFbCBpZGVudGlmaWNhZG9yIMO6bmljbyBJRF9DT01VTkEsIGNvbXB1ZXN0byBwb3IgbGEgY29tYmluYWNpw7NuIGRlIENPRF9VQklHRU8gKHF1ZSBpZGVudGlmaWNhIHViaWNhY2nDs24gZ2VvZ3LDoWZpY2EgYSBuaXZlbCBtdW5pY2lwYWwgeSBwYXJyb3F1aWFsKSB5IENPRF9DQyAocXVlIGlkZW50aWZpY2EgZWwgY2lyY3VpdG8gY29tdW5hbCBlc3BlY8OtZmljbyksIHBlcm1pdGUgdW5hIGdlb3JyZWZlcmVuY2lhY2nDs24gcHJlY2lzYSBkZSBjYWRhIHByb3llY3RvIHkgZmFjaWxpdGEgZWwgYW7DoWxpc2lzIHRlcnJpdG9yaWFsIGRlIGxhcyBpbnRlcnZlbmNpb25lcy4gRXN0b3MgZWplbXBsb3MgaW5pY2lhbGVzIGV2aWRlbmNpYW4gbGEgaGV0ZXJvZ2VuZWlkYWQgZGUgbnVkb3MgY3LDrXRpY29zIGRlIGxhcyBjb211bmFzIHkgbGEgbmVjZXNpZGFkIGRlIGFib3JkYWplcyBkaWZlcmVuY2lhZG9zIGVuIGxhIHBsYW5pZmljYWNpw7NuIGRlIGxhcyBBQ0EuIExhIHJlY3VycmVuY2lhIGRlIGNpZXJ0YXMgdGlwb2xvZ8OtYXMgZGUgcHJvYmxlbWFzLCBwYXJ0aWN1bGFybWVudGUgYXF1ZWxsb3MgcmVsYWNpb25hZG9zIGNvbiBpbmZyYWVzdHJ1Y3R1cmEgYsOhc2ljYSB5IHNlcnZpY2lvcyBww7pibGljb3MsIHN1Z2llcmUgcGF0cm9uZXMgY29tdW5lcyBxdWUgbWVyZWNlbiBhdGVuY2nDs24gZXNwZWNpYWwgZW4gZWwgYW7DoWxpc2lzIHBvc3RlcmlvciBkZSBjb3JyZWxhY2lvbmVzIHkgZWZlY3RpdmlkYWQgZGUgcHJveWVjdG9zLg0KDQpgYGB7ciwgY2xhc2lmaWNhY2lvbiBkZSBsYXMgdGlwb2xvZ2lhc30NCg0KIyMgLS0tLS0tLS0tLS0tLSoqQ3JlYWNpw7NuIGRlIHZhcmlhYmxlcyBkdW1teSB5IHJlc3VtZW4gcG9yIGNvbXVuYSoqLS0tLS0tLS0tLS0tLS0tLS0tLS0tIyMNCmRmX3JhdyA8LSByZWFkX2V4Y2VsICgiQzovVXNlcnMvd2lsbGlhbS9EZXNrdG9wL21vbm9ncmFmaWEgYWNhIG1lcmlkYS9kYXRvcy9BQ0EgTW9kZWxhamUgUiBGaW5hbC54bHN4IiwgDQogICAgc2hlZXQgPSAiUmVzdW1lbiIpICU+JQ0KICBtdXRhdGUoSURfQ09NVU5BID0gcGFzdGUwKENPRF9VQklHRU8sICItIiwgQ09EX0NDKSkNCg0KIyBDcmVhciBkdW1taWVzIGRlc2RlIGxhcyB2YXJpYWJsZXMgY3VhbGl0YXRpdmFzDQpkZl9kdW1taWVzIDwtIGRmX3JhdyAlPiUNCiAgZHVtbXlfY29scygNCiAgICBzZWxlY3RfY29sdW1ucyA9IGMoDQogICAgICAiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHIiwNCiAgICAgICJDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OIiwNCiAgICAgICJDTEFTSUZJQ0FDSU9OX0RFTF9QUk9ZRUNUTyINCiAgICApLA0KICAgIHJlbW92ZV9maXJzdF9kdW1teSA9IEZBTFNFDQogICkNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS1QcmltZXJhIHRhYmxhIC0gVmFyaWFibGVzIG9yaWdpbmFsZXMgKHByaW1lcm9zIDEwIHJlZ2lzdHJvcyktLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnRhYmxhMSA8LSBkZl9yYXcgJT4lDQogIHNlbGVjdCgNCiAgICBgTnVkbyBDcsOtdGljb3MgcG9yIFRpcG9sb2fDrWEgQ0ZHYCA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgICBgTnVkb3MgQ3LDrXRpY29zIHBvciBUaXBvbG9nw61hIGRlIEdvYmllcm5vYCA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sDQogICAgYENPRCBVQklHRU9gID0gQ09EX1VCSUdFTywNCiAgICBgQ09EIENDYCA9IENPRF9DQywNCiAgICBDT01VTkEsDQogICAgYElEIENPTVVOQWAgPSBJRF9DT01VTkENCiAgKSAlPiUNCiAgaGVhZCgxMCkNCg0Ka2FibGUodGFibGExLCBjYXB0aW9uID0gIlRhYmxhIDEuIFByaW1lcm9zIDEwIHJlZ2lzdHJvcyBkZSBkYXRvcyBvcmlnaW5hbGVzIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZvbnRfc2l6ZSA9IDEwKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICJOb3RhLiBJRF9DT01VTkEgPSBJZGVudGlmaWNhZG9yIMO6bmljbyBkZSBjb211bmEgeSBjb21iaW5hY2nDs24gZGVsIGPDs2RpZ28gVUJJR0VPIHkgY8OzZGlnbyBTSVRVUiBkZSBjYWRhIGNvbXVuYTsgQ09EX1VCSUdFTyA9IEPDs2RpZ28gZGUgdWJpY2FjacOzbiBnZW9ncsOhZmljYSBhIG5pdmVsIG5hY2lvbmFsIHkgTcOpcmlkYS4iLA0KICAgICAgICAgICBnZW5lcmFsX3RpdGxlID0gIiIpDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1TZWd1bmRhIHRhYmxhIC0gVmFyaWFibGVzIGltcG9ydGFudGVzIChwcmltZXJvcyAxMCByZWdpc3Ryb3MpLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnRhYmxhMiA8LSBkZl9yYXcgJT4lDQogIHNlbGVjdCgNCiAgICBuX3Byb3llY3RvcywNCiAgICBQTEFaT1MsDQogICAgQ0xBU0lGSUNBQ0lPTl9ERUxfUFJPWUVDVE8sDQogICAgVElQT0xPR0lBX0NGR19OVU0sDQogICAgR09CRVJOQUNJT05fTlVNLA0KICAgIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sDQogICAgQ2xhc2lmaWNhY2lvbl9BY3RvcmVzX2luc3RpdHVjaW9uYWxlcw0KICApICU+JQ0KICBoZWFkKDEwKQ0KDQprYWJsZSh0YWJsYTIsIGNhcHRpb24gPSAiVGFibGEgMi4gUHJpbWVyb3MgMTAgcmVnaXN0cm9zIGRlIHZhcmlhYmxlcyBkZSBhbsOhbGlzaXMgcHJpbmNpcGFsZXMiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZm9udF9zaXplID0gMTApDQpgYGANCg0KUG9zdGVyaW9ybWVudGUsIGxhcyB2YXJpYWJsZXMgY3VhbGl0YXRpdmFzIGZ1ZXJvbiBjb2RpZmljYWRhcyB5IG9wZXJhY2lvbmFsaXphZGFzIHBhcmEgZWwgYW7DoWxpc2lzIGN1YW50aXRhdGl2bywgY29tbyBzZSBkZXRhbGzDsyBlbiBlbCBNYXJjbyBNZXRvZG9sw7NnaWNvLg0KDQojIyAqKkFuw6FsaXNpcyBkZSB0ZW5kZW5jaWEgY2VudHJhbCB5IGRlIGRpc3BlcnNpw7NuIGRlIGxhcyB2YXJpYWJsZXMgb3JpZ2luYWxlcyoqDQoNClBhcmEgY29tcGxlbWVudGFyIGVsIGFuw6FsaXNpcyBkZSBsYXMgdmFyaWFibGVzIG9yZGluYWxlcyB5IGNhdGVnw7NyaWNhcywgbGFzIFRhYmxhcyBkZSBmcmVjdWVuY2lhcyBtdWVzdHJhIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbGFzIG1pc21hcyB5IHBvcmNlbnRhamVzIGRlIGxhcyB2YXJpYWJsZXMgY2xhdmUuIExvcyBkYXRvcyByZXZlbGFuIHF1ZSBlbCAqKjc2LDc3JSoqIGRlIGxhcyBjb211bmFzIHBhcnRpY2lwYXJvbiBlbiBsYXMgY3VhdHJvIGNvbnN1bHRhcyBuYWNpb25hbGVzLCBkZW1vc3RyYW5kbyB1biBjb21wcm9taXNvIHNvc3RlbmlkbyBjb24gZWwgcHJvY2VzbyBkZSBwbGFuaWZpY2FjacOzbi4gU2luIGVtYmFyZ28sIGNhc2kgbGEgbWl0YWQgZGUgbG9zIHByb3llY3RvcyAoKio0OCw5OSUqKikgZnVlcm9uIGNhdGFsb2dhZG9zIGNvbW8gIk5vIENvbnNpZGVyYWRvcyIsIGluZGljYW5kbyB1bmEgc2lnbmlmaWNhdGl2YSBkZXNjb25leGnDs24gZW50cmUgbGEgaWRlbnRpZmljYWNpw7NuIGRlIHByb2JsZW1hcyB5IHN1IHBvc3RlcmlvciBwcmlvcml6YWNpw7NuIGVqZWN1dGl2YS4gU29sbyBlbCAqKjI1LDI1JSoqIGRlIGxvcyBwcm95ZWN0b3MgYWxjYW56YXJvbiBlbCBlc3RhZG8gZGUgIkN1bG1pbmFkb3MiLiBMYSBwbGFuaWZpY2FjacOzbiB0ZW1wb3JhbCBtdWVzdHJhIHF1ZSBsYSBhYnJ1bWFkb3JhIG1heW9yw61hIGRlIGxvcyBwcm95ZWN0b3MgKCoqODMsODQlKiopIHNlIGRpc2XDsWFyb24gcGFyYSB1biBob3Jpem9udGUgZGUgdGllbXBvIGRlIG1lZGlhbm8gcGxhem8gKDEtMiBhw7FvcyksIGNvaGVyZW50ZSBjb24gbGEgbmF0dXJhbGV6YSBlc3RydWN0dXJhbCBkZSBsb3MgbnVkb3MgY3LDrXRpY29zLiBSZXNwZWN0byBhIGxvcyBhY3RvcmVzIGluc3RpdHVjaW9uYWxlcywgc2Ugb2JzZXJ2YSB1bmEgcHJlZG9taW5hbmNpYSBkZSBsYSBnZXN0acOzbiBwb3IgcGFydGUgZGUgZW50aWRhZGVzIGUgaW5zdGl0dWNpb25lcyBuYWNpb25hbGVzIHkgZXN0YWRhbGVzICgqKjUxLDUyJSoqKSwgbWllbnRyYXMgcXVlIGxhIHBhcnRpY2lwYWNpw7NuIGRlIGFjdG9yZXMgbXVuaWNpcGFsZXMvY29tdW5hbGVzICgqKjE5LDE5JSoqKSB5IHByaXZhZG9zICggKiozLDU0JSoqKSBlcyBjb25zaWRlcmFibGVtZW50ZSBtZW5vci4NCg0KYGBge3J9DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0gQW7DoWxpc2lzIGRlIHRlbmRlbmNpYSBjZW50cmFsIHkgZGlzcGVyc2nDs24tLS0tLS0tLS0tLS0tLS0tLS0tLSMNCmFuYWxpc2lzX3RlbmRlbmNpYSA8LSBkZl9yYXcgJT4lDQogIHNlbGVjdChuX3Byb3llY3RvcywgUExBWk9TLENMQVNJRklDQUNJT05fREVMX1BST1lFQ1RPLCBUSVBPTE9HSUFfQ0ZHX05VTSwgR09CRVJOQUNJT05fTlVNLCANCiAgICAgICAgIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIENsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMpICU+JQ0KICBwc3ljaDo6ZGVzY3JpYmUoKSAlPiUNCiAgcm93bmFtZXNfdG9fY29sdW1uKCJWYXJpYWJsZSIpICU+JQ0KICBzZWxlY3QoVmFyaWFibGUsIG4sIG1lYW4sIHNkLCBtaW4sIG1heCwgbWVkaWFuLCBza2V3LCBrdXJ0b3NpcykNCg0KIyBBbsOhbGlzaXMgZGUgZnJlY3VlbmNpYXMgcGFyYSB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzIG5fcHJveWVjdG9zDQpmcmVjdWVuY2lhc19uX3Byb3llY3RvcyA8LSBkZl9yYXcgJT4lDQogIGNvdW50KG5fcHJveWVjdG9zKSAlPiUNCiAgbXV0YXRlKFBvcmNlbnRhamUgPSByb3VuZChuIC8gc3VtKG4pICogMTAwLCAyKSkgJT4lDQogIHJlbmFtZShGcmVjdWVuY2lhID0gbiwgQ2F0ZWdvcsOtYSA9IG5fcHJveWVjdG9zKQ0Ka2FibGUoZnJlY3VlbmNpYXNfbl9wcm95ZWN0b3MsIGNhcHRpb24gPSAiRGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcyBwYXJhIGxhIHZhcmlhYmxlIG5fcHJveWVjdG9zIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpDQoNCiMgQW7DoWxpc2lzIGRlIGZyZWN1ZW5jaWFzIHBhcmEgdmFyaWFibGVzIGNhdGVnw7NyaWNhcyBDbGFzaWZpY2FjacOzbiBkZWwgcHJveWVjdG8NCmZyZWN1ZW5jaWFzX2NsYXNpZmljYWNpb25fcHJveWVjdG8gPC0gZGZfcmF3ICU+JQ0KICBjb3VudChDTEFTSUZJQ0FDSU9OX0RFTF9QUk9ZRUNUTykgJT4lDQogIG11dGF0ZShQb3JjZW50YWplID0gcm91bmQobiAvIHN1bShuKSAqIDEwMCwgMikpICU+JQ0KICByZW5hbWUoRnJlY3VlbmNpYSA9IG4sIENhdGVnb3LDrWEgPSBDTEFTSUZJQ0FDSU9OX0RFTF9QUk9ZRUNUTykNCmthYmxlKGZyZWN1ZW5jaWFzX2NsYXNpZmljYWNpb25fcHJveWVjdG8sIGNhcHRpb24gPSAiRGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcyBwYXJhIGxhIHZhcmlhYmxlIENMQVNJRklDQUNJT05fREVMX1BST1lFQ1RPIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpDQogIA0KDQojIEFuw6FsaXNpcyBkZSBmcmVjdWVuY2lhcyBwYXJhIHZhcmlhYmxlcyBjYXRlZ8OzcmljYXMgUGxhem9zDQpmcmVjdWVuY2lhc19wbGF6b3MgPC0gZGZfcmF3ICU+JQ0KICBjb3VudChQTEFaT1MpICU+JQ0KICBtdXRhdGUoUG9yY2VudGFqZSA9IHJvdW5kKG4gLyBzdW0obikgKiAxMDAsIDIpKSAlPiUNCiAgcmVuYW1lKEZyZWN1ZW5jaWEgPSBuLCBDYXRlZ29yw61hID0gUExBWk9TKQ0KDQprYWJsZShmcmVjdWVuY2lhc19wbGF6b3MsIGNhcHRpb24gPSAiRGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcyBwYXJhIGxhIHZhcmlhYmxlIFBMQVpPUyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpKQ0KDQojIEFuw6FsaXNpcyBkZSBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPDQpmcmVjdWVuY2lhc19yYXRpbyA8LSBkZl9yYXcgJT4lDQogIGNvdW50KFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8pICU+JQ0KICBtdXRhdGUoUG9yY2VudGFqZSA9IHJvdW5kKG4gLyBzdW0obikgKiAxMDAsIDIpKSAlPiUNCiAgcmVuYW1lKEZyZWN1ZW5jaWEgPSBuLCBDYXRlZ29yw61hID0gUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETykNCg0Ka2FibGUoZnJlY3VlbmNpYXNfcmF0aW8sIGNhcHRpb24gPSAiRGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcyBwYXJhIGxhIHZhcmlhYmxlIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8iKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkNCg0KIyBBbsOhbGlzaXMgZGUgYWN0b3JlcyBpbnN0aXR1Y2lvbmFsZXMNCmZyZWN1ZW5jaWFzX2FjdG9yZXMgPC0gZGZfcmF3ICU+JQ0KICBjb3VudChDbGFzaWZpY2FjaW9uX0FjdG9yZXNfaW5zdGl0dWNpb25hbGVzKSAlPiUNCiAgbXV0YXRlKFBvcmNlbnRhamUgPSByb3VuZChuIC8gc3VtKG4pICogMTAwLCAyKSkgJT4lDQogIHJlbmFtZShGcmVjdWVuY2lhID0gbiwgQ2F0ZWdvcsOtYSA9IENsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMpDQoNCmthYmxlKGZyZWN1ZW5jaWFzX2FjdG9yZXMsIGNhcHRpb24gPSAiRGlzdHJpYnVjacOzbiBkZSBmcmVjdWVuY2lhcyBwYXJhIGxhIHZhcmlhYmxlIENsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkNCg0KIyMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVRyYWZpY28gZGUgZnJlY3VlbmNpYXMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBDb21iaW5hciB0b2RvcyBsb3MgZGF0YWZyYW1lcyBkZSBmcmVjdWVuY2lhcyBlbiB1bm8gc29sbw0KcGxvdF9kYXRhIDwtIGJpbmRfcm93cygNCiAgZnJlY3VlbmNpYXNfbl9wcm95ZWN0b3MgJT4lIG11dGF0ZShWYXJpYWJsZSA9ICJOw7ptZXJvIGRlIENvbnN1bHRhcyAobl9wcm95ZWN0b3MpIiksDQogIGZyZWN1ZW5jaWFzX2NsYXNpZmljYWNpb25fcHJveWVjdG8gJT4lIG11dGF0ZShWYXJpYWJsZSA9ICJFc3RhZG8gZGVsIFByb3llY3RvIiksDQogIGZyZWN1ZW5jaWFzX3JhdGlvICU+JSBtdXRhdGUoVmFyaWFibGUgPSAiUmF0aW8gZGUgRWZlY3RpdmlkYWQiKSwNCiAgZnJlY3VlbmNpYXNfcGxhem9zICU+JSBtdXRhdGUoVmFyaWFibGUgPSAiUGxhem8gZGUgRWplY3VjacOzbiAoUExBWk9TKSIpLA0KICBmcmVjdWVuY2lhc19hY3RvcmVzICU+JSBtdXRhdGUoVmFyaWFibGUgPSAiQWN0b3IgSW5zdGl0dWNpb25hbCBQcmluY2lwYWwiKQ0KKSAlPiUNCiAgbXV0YXRlKENhdGVnb3LDrWEgPSBhcy5mYWN0b3IoQ2F0ZWdvcsOtYSkpDQoNCiMgRGVmaW5pciBldGlxdWV0YXMgZGVzY3JpcHRpdmFzIHBhcmEgY2FkYSBjYXRlZ29yw61hDQpwbG90X2RhdGEgPC0gcGxvdF9kYXRhICU+JQ0KICBtdXRhdGUoDQogICAgRXRpcXVldGFfQ2F0ZWdvcmlhID0gY2FzZV93aGVuKA0KICAgICAgVmFyaWFibGUgPT0gIkVzdGFkbyBkZWwgUHJveWVjdG8iIH4gY2FzZV93aGVuKA0KICAgICAgICBDYXRlZ29yw61hID09IDEgfiAiMSAtIE5vIENvbnNpZGVyYWRvIiwNCiAgICAgICAgQ2F0ZWdvcsOtYSA9PSAyIH4gIjIgLSBObyBDdWxtaW5hZG8iLA0KICAgICAgICBDYXRlZ29yw61hID09IDMgfiAiMyAtIEVuIEVqZWN1Y2nDs24iLA0KICAgICAgICBDYXRlZ29yw61hID09IDQgfiAiNCAtIEN1bG1pbmFkbyINCiAgICAgICksDQogICAgICBWYXJpYWJsZSA9PSAiUmF0aW8gZGUgRWZlY3RpdmlkYWQiIH4gY2FzZV93aGVuKA0KICAgICAgICBDYXRlZ29yw61hID09IDEgfiAiMSAtIE11eSBCYWphIiwNCiAgICAgICAgQ2F0ZWdvcsOtYSA9PSAyIH4gIjIgLSBCYWphIiwNCiAgICAgICAgQ2F0ZWdvcsOtYSA9PSAzIH4gIjMgLSBNZWRpYSIsDQogICAgICAgIENhdGVnb3LDrWEgPT0gNCB+ICI0IC0gQWx0YSINCiAgICAgICksDQogICAgICBWYXJpYWJsZSA9PSAiUGxhem8gZGUgRWplY3VjacOzbiAoUExBWk9TKSIgfiBjYXNlX3doZW4oDQogICAgICAgIENhdGVnb3LDrWEgPT0gMCB+ICIwIC0gU2luIERhdG8iLA0KICAgICAgICBDYXRlZ29yw61hID09IDEgfiAiMSAtIENvcnRvIFBsYXpvIiwNCiAgICAgICAgQ2F0ZWdvcsOtYSA9PSAyIH4gIjIgLSBNZWRpYW5vIFBsYXpvIg0KICAgICAgKSwNCiAgICAgIFZhcmlhYmxlID09ICJBY3RvciBJbnN0aXR1Y2lvbmFsIFByaW5jaXBhbCIgfiBjYXNlX3doZW4oDQogICAgICAgIENhdGVnb3LDrWEgPT0gMSB+ICIxIC0gTWluaXN0ZXJpbyIsDQogICAgICAgIENhdGVnb3LDrWEgPT0gMiB+ICIyIC0gR29iLiBOYWMvRXN0LiIsDQogICAgICAgIENhdGVnb3LDrWEgPT0gMyB+ICIzIC0gTXVuLi9Db211bmFsIiwNCiAgICAgICAgQ2F0ZWdvcsOtYSA9PSA0IH4gIjQgLSBQcml2YWRvIg0KICAgICAgKSwNCiAgICAgIFZhcmlhYmxlID09ICJOw7ptZXJvIGRlIENvbnN1bHRhcyAobl9wcm95ZWN0b3MpIiB+IGFzLmNoYXJhY3RlcihDYXRlZ29yw61hKSwNCiAgICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIoQ2F0ZWdvcsOtYSkNCiAgICApDQogICkNCg0KIyBDYWxjdWxhciBlbCBsw61taXRlIHN1cGVyaW9yIGRlbCBlamUgWSBwYXJhIGFzZWd1cmFyIHF1ZSBsYXMgZXRpcXVldGFzIGVuY2FqZW4NCnlfbWF4IDwtIG1heChwbG90X2RhdGEkRnJlY3VlbmNpYSkgKiAxLjENCg0KIyBDcmVhciBlbCBncsOhZmljbyBkZSBiYXJyYXMgY29uIGZhY2V0YXMgbWVqb3JhZG8NCmdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gRXRpcXVldGFfQ2F0ZWdvcmlhLCB5ID0gRnJlY3VlbmNpYSwgZmlsbCA9IEV0aXF1ZXRhX0NhdGVnb3JpYSkpICsNCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKyAgDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVjdWVuY2lhKSwgdmp1c3QgPSAtMC41LCBzaXplID0gMy41KSArICANCiAgZmFjZXRfd3JhcCh+IFZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZV94IiwgbmNvbCA9IDUpICsgDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKyANCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlIEZyZWN1ZW5jaWFzIGRlIFZhcmlhYmxlcyBDbGF2ZSIsDQogICAgeCA9ICJDYXRlZ29yw61hcyIsDQogICAgeSA9ICJGcmVjdWVuY2lhIChOw7ptZXJvIGRlIFByb3llY3RvcykiLA0KICAgIGNhcHRpb24gPSAiRWxhYm9yYWNpw7NuIFByb3BpYSAtIFdpbGxpYW0gR3V0aWVycmV6IiAgDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA5KSwgIA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEwKSwgDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksICANCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAxLCBzaXplID0gOSwgZmFjZSA9ICJpdGFsaWMiKSAgDQogICkgKw0KICB5bGltKDAsIHlfbWF4KSAgDQpgYGANCg0KRWwgR3LDoWZpY28gZGUgRGlzdHJpYnVjacOzbiBkZSBGcmVjdWVuY2lhcyBkZSBWYXJpYWJsZXMgQ2xhdmVzIHJlcHJlc2VudGEgZ3LDoWZpY2FtZW50ZSBlc3RhcyBkaXN0cmlidWNpb25lcyBkZSBmcmVjdWVuY2lhLCBwZXJtaXRpZW5kbyB1bmEgY29tcGFyYWNpw7NuIGlubWVkaWF0YSBkZSBsYXMgcHJvcG9yY2lvbmVzIGVudHJlIGNhdGVnb3LDrWFzLg0KDQpFbCBncsOhZmljbyBjb25maXJtYSBlbCBwYXRyw7NuIGlkZW50aWZpY2FkbyBlbiBsYSB0YWJsYSwgZGVzdGFjYW5kbyB2aXN1YWxtZW50ZSBsYSBwcmVkb21pbmFuY2lhIGRlOiAxKSBsYSBwYXJ0aWNpcGFjacOzbiBlbiBjdWF0cm8gY29uc3VsdGFzLCAyKSBsb3MgcHJveWVjdG9zIG5vIGNvbnNpZGVyYWRvcywgMykgbG9zIHBsYXpvcyBkZSBlamVjdWNpw7NuIG1lZGlhbm9zLCB5IDQpIGxhIGdlc3Rpw7NuIHBvciBhY3RvcmVzIG5hY2lvbmFsZXMvZXN0YXRhbGVzLiBMYSByZXByZXNlbnRhY2nDs24gZ3LDoWZpY2EgZmFjaWxpdGEgbGEgaWRlbnRpZmljYWNpw7NuIGRlIGRlc2VxdWlsaWJyaW9zIGVuIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbGFzIHZhcmlhYmxlcywgcGFydGljdWxhcm1lbnRlIGxhIGJyZWNoYSBlbnRyZSBwcm95ZWN0b3Mgbm8gY29uc2lkZXJhZG9zIHkgY3VsbWluYWRvLg0KDQojIyAqKkZyZWN1ZW5jaWEgZ2xvYmFsIHBvciBjYWRhIHRpcG9sb2fDrWEgZGUgQ0ZHIHkgR29iZXJuYWNpw7NuLCDCv3F1w6kgcHJvYmxlbWEgZXMgZWwgbcOhcyBjb23Dum4/KioNCg0KUGFyYSBlc3RhYmxlY2VyIGN1w6FsZXMgc29uIGxvcyBudWRvcyBjcsOtdGljb3MgbcOhcyByZWN1cnJlbnRlcyBlbiB0b2RvIGVsIEVzdGFkbyBNw6lyaWRhLCBwcmltZXJvIGNhbGN1bGFtb3MgbGEgZnJlY3VlbmNpYSBhYnNvbHV0YSB5IHJlbGF0aXZhIGRlIGNhZGEgdGlwb2xvZ8OtYSBDRkcgeSBkZSBnb2Jlcm5hY2nDs24uIEVzdG8gbm9zIHBlcm1pdGUgaWRlbnRpZmljYXIgbGFzIMOhcmVhcyBkZSBtYXlvciBjb25jZW50cmFjacOzbiBkZSBwcm9ibGVtYXMgeSBwcmlvcml6YXIgbGFzIGzDrW5lYXMgZGUgYW7DoWxpc2lzIHBvc3RlcmlvcmVzLg0KDQojIyAqKkZyZWN1ZW5jaWFzIGRlIENvbnNlam8gRmVkZXJhbCBkZSBHb2JpZXJubyAoQ0ZHKSoqDQoNCkxhcyBHcsOhZmljYXMgZG9uZGUgc2UgcHJlc2VudGEgdW4gZ3LDoWZpY28gZGUgUGFyZXRvIHF1ZSBhbmFsaXphIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIG51ZG9zIGNyw610aWNvcyBzZWfDum4gZWwgbsO6bWVybyBkZSBwcm95ZWN0b3MgQUNBIGlkZW50aWZpY2Fkb3MgcGFyYSBjYWRhIHRpcG9sb2fDrWEgQ0ZHLCBlcyBjcnVjaWFsIHBhcmEgcHJpb3JpemFyIGxhIGFzaWduYWNpw7NuIGRlIHJlY3Vyc29zIHkgZXNmdWVyem9zIGEgbGEgcGxhbmlmaWNhY2nDs24sIHlhIHF1ZSByZXZlbGEgcXVlIGxvcyBwcm9ibGVtYXMgbm8gZXN0w6FuIGRpc3RyaWJ1aWRvcyBkZSBtYW5lcmEgdW5pZm9ybWUsIHNpbm8gcXVlIHNlIGNvbmNlbnRyYW4gZW4gdW5hcyBwb2NhcyDDoXJlYXMgY3LDrXRpY2FzLg0KDQpBbCByZXZpc2FyIGxvcyBncsOhZmljb3MsIHNlIHB1ZWRlIHZlciBxdWUgZWwgNjIsNiUgZGUgdG9kb3MgbG9zIHByb3llY3RvcyBzZSBjb25jZW50cmEgZW4gc8OzbG8gY3VhdHJvIHRpcG9sb2fDrWFzLiBFbCBNYW5lam8gSW50ZWdyYWwgZGVsIEFndWEgZXMgbGEgcHJvYmxlbcOhdGljYSBwcmluY2lwYWwsIHJlcHJlc2VudGFuZG8gcG9yIHPDrSBzb2xhIG3DoXMgZGUgdW5hIGN1YXJ0YSBwYXJ0ZSAoMjcsMjclKSBkZSB0b2RvcyBsb3MgcHJveWVjdG9zIEFDQS4NCg0KRXN0byBpbmRpY2EgcXVlIGxhIGNyaXNpcyBow61kcmljYSBubyBlcyB1biBwcm9ibGVtYSBhaXNsYWRvLCBzaW5vIGxhIHByaW5jaXBhbCBwcmlvcmlkYWQgZGUgbGFzIGNvbXVuaWRhZGVzIG1lcmlkZcOxYXMsIHN1cGVyYW5kbyBjb24gY3JlY2VzIGEgbGEgc2VndW5kYSB0aXBvbG9nw61hLCBWaWFsaWRhZCAoMTUsMTUlKSwgcG9yIHVuIG1hcmdlbiBkZSAxMiBwdW50b3MgcG9yY2VudHVhbGVzLiBMYSBjdXJ2YSBkZSBwb3JjZW50YWplIGFjdW11bGFkbyAobMOtbmVhIGFtYXJpbGxhIHkgcm9qYSBkZWwgaW50ZXJhY3Rpdm8pIG11ZXN0cmEgdW5hIHBlbmRpZW50ZSBwcm9udW5jaWFkYSBhbCBpbmljaW8sIHF1ZSBzZSB2YSBzdWF2aXphbmRvIGRlc3B1w6lzIGRlIGxhcyBwcmltZXJhcyA3IHRpcG9sb2fDrWFzLCBjb25maXJtYW5kbyBlbCBwcmluY2lwaW8gZGUgUGFyZXRvIG8gODAvMjAgKCoqRWwgMjAlIGRlIGxhcyBjYXVzYXMgZXhwbGljYW4gZWwgODAlIGRlIGxvcyBlZmVjdG9zKiopOiBhcHJveGltYWRhbWVudGUgZWwgODAlIGRlIGxvcyBwcm95ZWN0b3MgKDgwLDgxJSwgc2llbmRvIGV4YWN0b3MpIHNlIGNvbmNlbnRyYSBlbiByZXNvbHZlciBzw7NsbyBlbCA0NCUgZGUgbGFzIHRpcG9sb2fDrWFzICg3IGRlIDE3KSwgZXMgZGVjaXIsIHVuIHBlcXVlw7FvIG7Dum1lcm8gZGUgY2F1c2FzLg0KDQoqRXN0ZSBoYWxsYXpnbyBzdWdpZXJlIHF1ZSB1bmEgZXN0cmF0ZWdpYSBkZSBpbnRlcnZlbmNpw7NuIHDDumJsaWNhIGZvY2FsaXphZGEgZW4gZXN0YXMgc2lldGUgw6FyZWFzIHByaW5jaXBhbGVzIHBvZHLDrWEgcmVzb2x2ZXIgbGEgZ3JhbiBtYXlvcsOtYSBkZSBsb3MgcHJvYmxlbWFzIGlkZW50aWZpY2Fkb3MgY29uIHVuYSBtYXlvciBlZmljaWVuY2lhIGVuIGVsIHVzbyBkZSByZWN1cnNvcyouDQoNCkRlIG1hbmVyYSBzaW1pbGFyLCBhbCByZWFsaXphciBlbCBhbsOhbGlzaXMgZGVzZGUgdW5hIHBlcnNwZWN0aXZhIHRlcnJpdG9yaWFsIGNvbmZpcm1hIHkgcmVmdWVyemEgbG9zIGhhbGxhemdvcyBkZWwgYW7DoWxpc2lzIHBvciBwcm95ZWN0b3MuIE1hbmVqbyBJbnRlZ3JhbCBkZWwgQWd1YSBtYW50aWVuZSBzdSBwb3NpY2nDs24gZG9taW5hbnRlIGFsIGFmZWN0YXIgNDMgY29tdW5hcyAoMjMsNzYlIGRlbCB0b3RhbCksIGxvIHF1ZSBpbmRpY2EgcXVlIGVzdGUgcHJvYmxlbWEgbm8gc2UgbGltaXRhIGEgw6FyZWFzIGVzcGVjw61maWNhcywgc2lubyBxdWUgdGllbmUgY2Fyw6FjdGVyIHNpc3TDqW1pY28gYSBuaXZlbCBlc3RhdGFsLCBlbiBsYSBUYWJsYSA1IGV4aXN0ZSB1bmEgbm90YWJsZSBjb25zaXN0ZW5jaWEgZW4gZWwgb3JkZW5hbWllbnRvIGRlIGxhcyBwcmltZXJhcyBwb3NpY2lvbmVzIGVudHJlIGFtYmFzIHRhYmxhcyB2YWxpZGEgbGEgcm9idXN0ZXogZGVsIGRpYWduw7NzdGljbywgbGFzIHByaW1lcmFzIDQgdGlwb2xvZ8OtYXMgbWFudGllbmVuIGVsIG1pc21vIG9yZGVuIHRhbnRvIHBvciBwcm95ZWN0b3MgY29tbyBwb3IgY29tdW5hcywgYWRlbcOhcyBsYXMgcHJpbWVyYXMgNiB0aXBvbG9nw61hcyBtdWVzdHJhbiB2YXJpYWNpb25lcyBtw61uaW1hcyBlbiBzdSBwb3NpY2lvbmFtaWVudG8uIEVsIDc0LjAzJSBkZSB0b2RhcyBsYXMgYWZlY3RhY2lvbmVzIHRlcnJpdG9yaWFsZXMgc2UgY29uY2VudHJhIGVuIGxhcyBwcmltZXJhcyA2IHRpcG9sb2fDrWFzDQoNCkxhIGRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgcmV2ZWxhIHF1ZSBsb3MgcHJvYmxlbWFzIHByaW5jaXBhbGVzIGRlbCBFc3RhZG8gTcOpcmlkYSBubyBzb24gZmVuw7NtZW5vcyBsb2NhbGl6YWRvcyBzaW5vIGRlZmljaWVuY2lhcyBlc3RydWN0dXJhbGVzIGdlbmVyYWxpemFkYXM6DQoNCuKAoiBNYW5lam8gSW50ZWdyYWwgZGVsIEFndWEgZXN0w6EgcHJlc2VudGUgZW4gbcOhcyBkZWwgNjcsMTglIGRlIGxhcyBjb211bmFzIGVzdHVkaWFkYXMNCg0K4oCiIFZpYWxpZGFkIGFmZWN0YSBhIDI3IGNvbXVuYXMsIHJlcHJlc2VudGFuZG8gdW5hIGRpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwgY29uc2lkZXJhYmxlDQoNCuKAoiBWaXZpZW5kYSB5IEVsZWN0cmljaWRhZCBtYW50aWVuZW4gcHJlc2VuY2lhIHNpZ25pZmljYXRpdmEgY29uIDIxIHkgMTggY29tdW5hcyByZXNwZWN0aXZhbWVudGUuDQoNCg0KYGBge3IsIGZyZWN1ZW5jaWEgZ2xvYmFsIENGR30NCg0KIyMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tUmVzdW1lbiBDRkcgcG9yIENvbXVuYS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jIw0KY2ZnX2NvbHMgPC0gZGZfZHVtbWllcyAlPiUgDQogIHNlbGVjdChzdGFydHNfd2l0aCgiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHXyIpKSAlPiUgDQogIG5hbWVzKCkNCg0KZGZfY2ZnX3N1bW1hcnkgPC0gZGZfZHVtbWllcyAlPiUNCiAgZ3JvdXBfYnkoSURfQ09NVU5BKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG5fcHJveWVjdG9zID0gbigpLA0KICAgIGFjcm9zcyhhbGxfb2YoY2ZnX2NvbHMpLCBsaXN0KA0KICAgICAgY291bnQgPSB+IHN1bSgueCwgbmEucm0gPSBUUlVFKSwNCiAgICAgIHBjdCA9IH4gc3VtKC54LCBuYS5ybSA9IFRSVUUpIC8gbigpICogMTAwDQogICAgKSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMjLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1SZXN1bWVuIGRlIEdvYmVybmFjacOzbiBwb3IgY29tdW5hLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZ29iX2NvbHMgPC0gZGZfZHVtbWllcyAlPiUgDQogIHNlbGVjdChzdGFydHNfd2l0aCgiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTl8iKSkgJT4lIA0KICBuYW1lcygpDQoNCmRmX2dvYl9zdW1tYXJ5IDwtIGRmX2R1bW1pZXMgJT4lDQogIGdyb3VwX2J5KElEX0NPTVVOQSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBuX3Byb3llY3RvcyA9IG4oKSwNCiAgICBhY3Jvc3MoYWxsX29mKGdvYl9jb2xzKSwgbGlzdCgNCiAgICAgIGNvdW50ID0gfiBzdW0oLngsIG5hLnJtID0gVFJVRSksDQogICAgICBwY3QgPSB+IHN1bSgueCwgbmEucm0gPSBUUlVFKSAvIG4oKSAqIDEwMA0KICAgICkpDQogICkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLUFuw6FsaXNpcyBkZSBmcmVjdWVuY2lhcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBGdW5jacOzbiBtZWpvcmFkYSBwYXJhIGFuw6FsaXNpcyBjb21wbGV0bw0KYW5hbGl6YXJfZnJlY3VlbmNpYSA8LSBmdW5jdGlvbihkYXRhLCB2YXIsIGZpbGxfY29sb3IsIGxpbmVfY29sb3IsIHRpdHVsbywgdGlwbyA9ICJwcm95ZWN0b3MiKSB7DQogICMgRGV0ZXJtaW5hciBub21icmUgZGUgZXRpcXVldGEgc2Vnw7puIHRpcG8NCiAgeV9sYWJlbCA8LSBpZmVsc2UodGlwbyA9PSAicHJveWVjdG9zIiwgIk7Dum1lcm8gZGUgcHJveWVjdG9zIiwgIk7Dum1lcm8gZGUgY29tdW5hcyIpDQogIA0KICAjIEZyZWN1ZW5jaWFzIGdsb2JhbGVzDQogIGZyZXEgPC0gZGF0YSAlPiUNCiAgICBjb3VudCh7e3Zhcn19LCBuYW1lID0gIm4iKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MobikpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHBjdCA9IG4gLyBzdW0obikgKiAxMDAsDQogICAgICBjdW1fcGN0ID0gY3Vtc3VtKHBjdCksDQogICAgICBldGlxdWV0YSA9IHBhc3RlMChuLCAiXG4oIiwgcm91bmQocGN0LCAxKSwgIiUpIikNCiAgICApDQogIA0KICAjIEdyw6FmaWNvIGNvbWJpbmFkbw0KICBwbG90IDwtIGdncGxvdChmcmVxLCANCiAgICAgICAgIGFlcyh4ID0gcmVvcmRlcih7e3Zhcn19LCBuKSwgeSA9IG4pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9IGZpbGxfY29sb3IsIGFscGhhID0gMC44KSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGV0aXF1ZXRhKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDMuNSwgY29sb3IgPSAiYmxhY2siLCBsaW5laGVpZ2h0ID0gMC44KSArDQogICAgZ2VvbV9saW5lKGFlcyh5ID0gY3VtX3BjdCAqIG1heChuKSAvIDEwMCksIA0KICAgICAgICAgICAgICBncm91cCA9IDEsIGNvbG9yID0gbGluZV9jb2xvciwgc2l6ZSA9IDAuOCkgKw0KICAgIGdlb21fcG9pbnQoYWVzKHkgPSBjdW1fcGN0ICogbWF4KG4pIC8gMTAwKSwgDQogICAgICAgICAgICAgICBjb2xvciA9IGxpbmVfY29sb3IsIHNpemUgPSAyKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgbmFtZSA9IHlfbGFiZWwsDQogICAgICBzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAqIDEwMCAvIG1heChmcmVxJG4pLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlBvcmNlbnRhamUgYWN1bXVsYWRvICglKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKQ0KICAgICkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gdGl0dWxvLA0KICAgICAgc3VidGl0bGUgPSAiQmFycmFzOiBmcmVjdWVuY2lhIGFic29sdXRhIHwgVGV4dG86IGNvbnRlbyB5ICUgaW5kaXZpZHVhbCB8IEzDrW5lYTogJSBhY3VtdWxhZG8iLA0KICAgICAgeCA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKSArDQogICAgZXhwYW5kX2xpbWl0cyh5ID0gbWF4KGZyZXEkbikgKiAxLjE1KQ0KICANCiAgcmV0dXJuKGxpc3QoZnJlcSA9IGZyZXEsIHBsb3QgPSBwbG90KSkNCn0NCg0KIyBGdW5jacOzbiBtZWpvcmFkYSBwYXJhIGZyZWN1ZW5jaWEgcG9yIGNvbXVuYQ0KYW5hbGl6YXJfZnJlY3VlbmNpYV9jb211bmEgPC0gZnVuY3Rpb24oZGF0YSwgdmFyLCBmaWxsX2NvbG9yLCBsaW5lX2NvbG9yLCB0aXR1bG8pIHsNCiAgZnJlcV9jb211bmEgPC0gZGF0YSAlPiUNCiAgICBkaXN0aW5jdChJRF9DT01VTkEsIHt7dmFyfX0pICU+JSAgDQogICAgY291bnQoe3t2YXJ9fSwgbmFtZSA9ICJuX2NvbXVuYXMiKSAlPiUNCiAgICBhcnJhbmdlKGRlc2Mobl9jb211bmFzKSkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcGN0X2NvbXVuYXMgPSBuX2NvbXVuYXMgLyBzdW0obl9jb211bmFzKSAqIDEwMCwNCiAgICAgIGN1bV9wY3QgPSBjdW1zdW0ocGN0X2NvbXVuYXMpLA0KICAgICAgZXRpcXVldGEgPSBwYXN0ZTAobl9jb211bmFzLCAiXG4oIiwgcm91bmQocGN0X2NvbXVuYXMsIDEpLCAiJSkiKQ0KICAgICkNCiAgDQogICMgR3LDoWZpY28gY29tYmluYWRvDQogIHBsb3QgPC0gZ2dwbG90KGZyZXFfY29tdW5hLCANCiAgICAgICAgIGFlcyh4ID0gcmVvcmRlcih7e3Zhcn19LCBuX2NvbXVuYXMpLCB5ID0gbl9jb211bmFzKSkgKw0KICAgIGdlb21fY29sKGZpbGwgPSBmaWxsX2NvbG9yLCBhbHBoYSA9IDAuOCkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBldGlxdWV0YSksIA0KICAgICAgICAgICAgICBoanVzdCA9IC0wLjEsIHNpemUgPSAzLjUsIGNvbG9yID0gImJsYWNrIiwgbGluZWhlaWdodCA9IDAuOCkgKw0KICAgIGdlb21fbGluZShhZXMoeSA9IGN1bV9wY3QgKiBtYXgobl9jb211bmFzKSAvIDEwMCksDQogICAgICAgICAgICAgIGdyb3VwID0gMSwgY29sb3IgPSBsaW5lX2NvbG9yLCBzaXplID0gMC44KSArDQogICAgZ2VvbV9wb2ludChhZXMoeSA9IGN1bV9wY3QgKiBtYXgobl9jb211bmFzKSAvIDEwMCksDQogICAgICAgICAgICAgICBjb2xvciA9IGxpbmVfY29sb3IsIHNpemUgPSAyKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICAgbmFtZSA9ICJOw7ptZXJvIGRlIGNvbXVuYXMiLA0KICAgICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gKiAxMDAgLyBtYXgoZnJlcV9jb211bmEkbl9jb211bmFzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlBvcmNlbnRhamUgYWN1bXVsYWRvICglKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKQ0KICAgICkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZXhwYW5kX2xpbWl0cyh5ID0gbWF4KGZyZXFfY29tdW5hJG5fY29tdW5hcykgKiAxLjE1KSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gdGl0dWxvLA0KICAgICAgc3VidGl0bGUgPSAiQmFycmFzOiBmcmVjdWVuY2lhIGFic29sdXRhIHwgVGV4dG86IGNvbnRlbyB5ICUgZGUgY29tdW5hcyB8IEzDrW5lYTogJSBhY3VtdWxhZG8iLA0KICAgICAgeCA9IE5VTEwNCiAgICApICsNCiAgICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKQ0KICANCiAgcmV0dXJuKGxpc3QoZnJlcV9jb211bmEgPSBmcmVxX2NvbXVuYSwgcGxvdCA9IHBsb3QpKQ0KfQ0KIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLUFuw6FsaXNpcyBwYXJhIENGRy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgQ29udGVvIHkgcHJvcG9yY2lvbmVzIGdsb2JhbGVzIHBvciBUaXBvbG9naWEgQ0ZHDQoNCmNmZ19nbG9iYWxfcHJveWVjdG9zIDwtIGFuYWxpemFyX2ZyZWN1ZW5jaWEoDQogIGRmX2R1bW1pZXMsDQogIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgImRhcmtibHVlIiwgImdvbGQiLA0KICAiRnJlY3VlbmNpYSBnbG9iYWwgZGUgdGlwb2xvZ8OtYXMgQ0ZHIChQcm95ZWN0b3MpIg0KKQ0KY2ZnX2dsb2JhbF9jb211bmFzIDwtIGFuYWxpemFyX2ZyZWN1ZW5jaWFfY29tdW5hKA0KICBkZl9kdW1taWVzLA0KICBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsDQogICJkYXJrYmx1ZSIsICJnb2xkIiwNCiAgIkZyZWN1ZW5jaWEgZGUgdGlwb2xvZ8OtYXMgQ0ZHIHBvciBjb211bmEiDQopDQoNCg0KIyMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tTW9zdHJhciByZXN1bHRhZG9zLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBDb250ZW8geSBwcm9wb3JjaW9uZXMgZ2xvYmFsZXMgc29icmUgbGEgdmFyaWFibGUgb3JpZ2luYWwNCmZyZXFfY2ZnIDwtIGRmX2R1bW1pZXMgJT4lDQogIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbmFtZSA9ICJuIikgJT4lDQogIGFycmFuZ2UoZGVzYyhuKSkgJT4lDQogIG11dGF0ZSgNCiAgICBwY3QgICAgID0gbiAvIHN1bShuKSAqIDEwMCwNCiAgICBjdW1fcGN0ID0gY3Vtc3VtKHBjdCkNCiAgKQ0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1Ub3AgMTAgYmFycmFzIHNpbXBsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZnJlcV9jZmcgJT4lDQogIHNsaWNlKDE6MTApICU+JQ0KICBnZ3Bsb3QoYWVzKA0KICAgIHggPSByZW9yZGVyKENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbiksDQogICAgeSA9IG4NCiAgKSkgKw0KICAgIGdlb21fY29sKGZpbGwgPSAiZGFya2JsdWUiKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiVG9wIDEwIHRpcG9sb2fDrWFzIENGRyBtw6FzIGZyZWN1ZW50ZXMiLA0KICAgICAgeCAgICAgPSAiVGlwb2xvZ8OtYSBDRkciLA0KICAgICAgeSAgICAgPSAiTsO6bWVybyBkZSBwcm95ZWN0b3MiDQogICAgKSArDQogICAgdGhlbWVfbWluaW1hbCgpDQoNCiMjLS0tLS0tLS0tLS0tLS0tLS0tLS1HcmFmaWNvIGRlIGZyZWN1ZW5jaWFzIGRlIHRpcG9sb2fDrWFzIENGRy0tLS0tLS0tLS0tLS0tLS0tLQ0KcHJpbnQoY2ZnX2dsb2JhbF9wcm95ZWN0b3MkcGxvdCkNCg0KDQojLS0tLS0tLS1GcmVjdWVuY2lhIGFic29sdXRhIHkgcmVsYXRpdmEgZGUgY29tdW5hcyBwb3IgdGlwb2xvZ8OtYSBDRkctLS0tLS0tLS0NCmZyZXFfY2ZnX2NvbXVuYSA8LSBkZl9kdW1taWVzICU+JQ0KICBkaXN0aW5jdChJRF9DT01VTkEsIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRykgJT4lDQogIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbmFtZSA9ICJuX2NvbXVuYXMiKSAlPiUNCiAgYXJyYW5nZShkZXNjKG5fY29tdW5hcykpICU+JQ0KICBtdXRhdGUoDQogICAgcGN0X2NvbXVuYXMgPSBuX2NvbXVuYXMgLyBzdW0obl9jb211bmFzKSAqIDEwMCwNCiAgICBjdW1fcGN0ICAgICA9IGN1bXN1bShwY3RfY29tdW5hcykNCiAgKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tVG9wIDEwIGNvbXVuYXMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZnJlcV9jZmdfY29tdW5hICU+JQ0KICBzbGljZSgxOjEwKSAlPiUNCiAgZ2dwbG90KGFlcygNCiAgICB4ID0gcmVvcmRlcihDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsIG5fY29tdW5hcyksDQogICAgeSA9IG5fY29tdW5hcw0KICApKSArDQogICAgZ2VvbV9jb2woZmlsbCA9ICJkYXJrYmx1ZSIpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICJUb3AgMTAgdGlwb2xvZ8OtYXMgQ0ZHIHBvciBuw7ptZXJvIGRlIGNvbXVuYXMiLA0KICAgICAgeCAgICAgPSAiVGlwb2xvZ8OtYSBDRkciLA0KICAgICAgeSAgICAgPSAiTsO6bWVybyBkZSBjb211bmFzIg0KICAgICkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KIyMtLS0tLS0tLS0tLS0tLS0tR3JhZmljbyBkZSBmcmVjdWVuY2lhcyBkZSB0aXBvbG9nw61hcyBDRkctLS0tLS0tLS0tLS0tLS0tLS0tLQ0KcHJpbnQoY2ZnX2dsb2JhbF9jb211bmFzJHBsb3QpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojICBUQUJMQSBDT01QTEVUQSBERSBGUkVDVUVOQ0lBUyBDRkcgUE9SIFBST1lFQ1RPUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY3JlYXJfdGFibGFfY2ZnX3Byb3llY3RvcyA8LSBmdW5jdGlvbihkYXRhKSB7DQogIA0KICAjIENhbGN1bGFyIGZyZWN1ZW5jaWFzDQogIHRhYmxhX2NmZyA8LSBkYXRhICU+JQ0KICAgIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbmFtZSA9ICJuX3Byb3llY3RvcyIpICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhuX3Byb3llY3RvcykpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHBvcmNlbnRhamUgPSByb3VuZChuX3Byb3llY3RvcyAvIHN1bShuX3Byb3llY3RvcykgKiAxMDAsIDIpLA0KICAgICAgcGN0X2FjdW11bGFkbyA9IHJvdW5kKGN1bXN1bShwb3JjZW50YWplKSwgMiksDQogICAgICByYW5raW5nID0gcm93X251bWJlcigpDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAiUmFua2luZyIgPSByYW5raW5nLA0KICAgICAgIlRpcG9sb2fDrWEgQ0ZHIiA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgICAgICJOwrAgUHJveWVjdG9zIiA9IG5fcHJveWVjdG9zLA0KICAgICAgIlBvcmNlbnRhamUgKCUpIiA9IHBvcmNlbnRhamUsDQogICAgICAiJSBBY3VtdWxhZG8iID0gcGN0X2FjdW11bGFkbw0KICAgICkNCiAgDQogICMgQ3JlYXIgdGFibGEgZm9ybWF0ZWFkYSBjb24ga2FibGVFeHRyYQ0KICB0YWJsYV9maW5hbCA8LSB0YWJsYV9jZmcgJT4lDQogICAga2FibGUoDQogICAgICBjYXB0aW9uID0gIlRhYmxhIDQuMTogRGlzdHJpYnVjacOzbiBkZSBGcmVjdWVuY2lhcyBkZSBUaXBvbG9nw61hcyBDRkcgcG9yIE7Dum1lcm8gZGUgUHJveWVjdG9zIiwNCiAgICAgIGFsaWduID0gYygiYyIsICJsIiwgImMiLCAiYyIsICJjIiksDQogICAgICBmb3JtYXQgPSAiaHRtbCINCiAgICApICU+JQ0KICAgIGthYmxlX3N0eWxpbmcoDQogICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSwNCiAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICAgIHBvc2l0aW9uID0gImNlbnRlciIsDQogICAgICBmb250X3NpemUgPSAxMg0KICAgICkgJT4lDQogICAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGNvbG9yID0gIndoaXRlIiwgYmFja2dyb3VuZCA9ICIjMmMzZTUwIikgJT4lDQogICAgY29sdW1uX3NwZWMoMiwgd2lkdGggPSAiMjBlbSIpICU+JQ0KICAgIGNvbHVtbl9zcGVjKDM6NSwgd2lkdGggPSAiOGVtIikgJT4lDQogICAgcm93X3NwZWMoMTo0LCBiYWNrZ3JvdW5kID0gIiNlOGY0ZmQiKSAlPiUgICMgUmVzYWx0YXIgdG9wIDQNCiAgICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiID0gMiwgIkZyZWN1ZW5jaWFzIEFic29sdXRhcyB5IFJlbGF0aXZhcyIgPSAzKSkgJT4lDQogICAgZm9vdG5vdGUoDQogICAgICBnZW5lcmFsID0gYygNCiAgICAgICAgIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSBiYXNhZGEgZW4gZGF0b3MgZGVsIEVzdGFkbyBNw6lyaWRhIDIwMTktMjAyNSIsDQogICAgICAgICJOb3RhOiBMYXMgcHJpbWVyYXMgNCB0aXBvbG9nw61hcyBjb25jZW50cmFuIGVsIDYyLjYlIGRlIHRvZG9zIGxvcyBudWRvcyBjcsOtdGljb3MiDQogICAgICApLA0KICAgICAgZ2VuZXJhbF90aXRsZSA9ICIiLA0KICAgICAgZm9vdG5vdGVfYXNfY2h1bmsgPSBUUlVFDQogICAgKQ0KICANCiAgcmV0dXJuKGxpc3QoZGF0b3MgPSB0YWJsYV9jZmcsIHRhYmxhID0gdGFibGFfZmluYWwpKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgVEFCTEEgQ09NUExFVEEgREUgRlJFQ1VFTkNJQVMgQ0ZHIFBPUiBDT01VTkFTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjcmVhcl90YWJsYV9jZmdfY29tdW5hcyA8LSBmdW5jdGlvbihkYXRhKSB7DQogIA0KICAjIENhbGN1bGFyIGZyZWN1ZW5jaWFzIHBvciBjb211bmEgKHNpbiByZXBldGlyIGNvbXVuYXMpDQogIHRhYmxhX2NmZ19jb211bmFzIDwtIGRhdGEgJT4lDQogICAgZGlzdGluY3QoSURfQ09NVU5BLCBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcpICU+JQ0KICAgIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbmFtZSA9ICJuX2NvbXVuYXMiKSAlPiUNCiAgICBhcnJhbmdlKGRlc2Mobl9jb211bmFzKSkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcG9yY2VudGFqZSA9IHJvdW5kKG5fY29tdW5hcyAvIHN1bShuX2NvbXVuYXMpICogMTAwLCAyKSwNCiAgICAgIHBjdF9hY3VtdWxhZG8gPSByb3VuZChjdW1zdW0ocG9yY2VudGFqZSksIDIpLA0KICAgICAgcmFua2luZyA9IHJvd19udW1iZXIoKQ0KICAgICkgJT4lDQogICAgcmVuYW1lKA0KICAgICAgIlJhbmtpbmciID0gcmFua2luZywNCiAgICAgICJUaXBvbG9nw61hIENGRyIgPSBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsDQogICAgICAiTsKwIENvbXVuYXMiID0gbl9jb211bmFzLA0KICAgICAgIlBvcmNlbnRhamUgKCUpIiA9IHBvcmNlbnRhamUsDQogICAgICAiJSBBY3VtdWxhZG8iID0gcGN0X2FjdW11bGFkbw0KICAgICkNCiAgDQogICMgQ3JlYXIgdGFibGEgZm9ybWF0ZWFkYQ0KICB0YWJsYV9maW5hbCA8LSB0YWJsYV9jZmdfY29tdW5hcyAlPiUNCiAgICBrYWJsZSgNCiAgICAgIGNhcHRpb24gPSAiVGFibGEgNC4yOiBEaXN0cmlidWNpw7NuIGRlIEZyZWN1ZW5jaWFzIGRlIFRpcG9sb2fDrWFzIENGRyBwb3IgTsO6bWVybyBkZSBDb211bmFzIEFmZWN0YWRhcyIsDQogICAgICBhbGlnbiA9IGMoImMiLCAibCIsICJjIiwgImMiLCAiYyIpLA0KICAgICAgZm9ybWF0ID0gImh0bWwiDQogICAgKSAlPiUNCiAgICBrYWJsZV9zdHlsaW5nKA0KICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksDQogICAgICBmdWxsX3dpZHRoID0gRkFMU0UsDQogICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgZm9udF9zaXplID0gMTINCiAgICApICU+JQ0KICAgIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiIzJjM2U1MCIpICU+JQ0KICAgIGNvbHVtbl9zcGVjKDIsIHdpZHRoID0gIjIwZW0iKSAlPiUNCiAgICBjb2x1bW5fc3BlYygzOjUsIHdpZHRoID0gIjhlbSIpICU+JQ0KICAgIHJvd19zcGVjKDE6NCwgYmFja2dyb3VuZCA9ICIjZThmNGZkIikgJT4lICAjIFJlc2FsdGFyIHRvcCA0DQogICAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDIsICJEaXN0cmlidWNpw7NuIFRlcnJpdG9yaWFsIiA9IDMpKSAlPiUNCiAgICBmb290bm90ZSgNCiAgICAgIGdlbmVyYWwgPSBjKA0KICAgICAgICAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGJhc2FkYSBlbiBkYXRvcyBkZWwgRXN0YWRvIE3DqXJpZGEgMjAxOS0yMDI1IiwNCiAgICAgICAgIk5vdGE6IFVuYSBjb211bmEgcHVlZGUgdGVuZXIgbcO6bHRpcGxlcyB0aXBvbG9nw61hcywgcGVybyBzZSBjdWVudGEgdW5hIHNvbGEgdmV6IHBvciB0aXBvbG9nw61hIg0KICAgICAgKSwNCiAgICAgIGdlbmVyYWxfdGl0bGUgPSAiIiwNCiAgICAgIGZvb3Rub3RlX2FzX2NodW5rID0gVFJVRQ0KICAgICkNCiAgDQogIHJldHVybihsaXN0KGRhdG9zID0gdGFibGFfY2ZnX2NvbXVuYXMsIHRhYmxhID0gdGFibGFfZmluYWwpKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBUQUJMQSBDT01QQVJBVElWQSBDRkc6IFBST1lFQ1RPUyBWUyBDT01VTkFTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjcmVhcl90YWJsYV9jb21wYXJhdGl2YV9jZmcgPC0gZnVuY3Rpb24oZGF0YSkgew0KICANCiAgIyBEYXRvcyBwb3IgcHJveWVjdG9zDQogIGNmZ19wcm95ZWN0b3MgPC0gZGF0YSAlPiUNCiAgICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsIG5hbWUgPSAibl9wcm95ZWN0b3MiKSAlPiUNCiAgICBtdXRhdGUocGN0X3Byb3llY3RvcyA9IHJvdW5kKG5fcHJveWVjdG9zIC8gc3VtKG5fcHJveWVjdG9zKSAqIDEwMCwgMikpDQogIA0KICAjIERhdG9zIHBvciBjb211bmFzDQogIGNmZ19jb211bmFzIDwtIGRhdGEgJT4lDQogICAgZGlzdGluY3QoSURfQ09NVU5BLCBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcpICU+JQ0KICAgIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbmFtZSA9ICJuX2NvbXVuYXMiKSAlPiUNCiAgICBtdXRhdGUocGN0X2NvbXVuYXMgPSByb3VuZChuX2NvbXVuYXMgLyBzdW0obl9jb211bmFzKSAqIDEwMCwgMikpDQogIA0KICAjIFVuaXIgYW1iYXMgdGFibGFzDQogIHRhYmxhX2NvbXBhcmF0aXZhIDwtIGNmZ19wcm95ZWN0b3MgJT4lDQogICAgaW5uZXJfam9pbihjZmdfY29tdW5hcywgYnkgPSAiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHIikgJT4lDQogICAgYXJyYW5nZShkZXNjKG5fcHJveWVjdG9zKSkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcmFua2luZyA9IHJvd19udW1iZXIoKSwNCiAgICAgIGludGVuc2lkYWQgPSByb3VuZChuX3Byb3llY3RvcyAvIG5fY29tdW5hcywgMikgICMgUHJveWVjdG9zIHBvciBjb211bmEgcHJvbWVkaW8NCiAgICApICU+JQ0KICAgIHNlbGVjdCgNCiAgICAgIHJhbmtpbmcsDQogICAgICBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsDQogICAgICBuX3Byb3llY3RvcywgcGN0X3Byb3llY3RvcywNCiAgICAgIG5fY29tdW5hcywgcGN0X2NvbXVuYXMsDQogICAgICBpbnRlbnNpZGFkDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAiUmFuayIgPSByYW5raW5nLA0KICAgICAgIlRpcG9sb2fDrWEgQ0ZHIiA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgICAgICJOwrAgUHJveS4iID0gbl9wcm95ZWN0b3MsDQogICAgICAiJSBQcm95LiIgPSBwY3RfcHJveWVjdG9zLA0KICAgICAgIk7CsCBDb20uIiA9IG5fY29tdW5hcywNCiAgICAgICIlIENvbS4iID0gcGN0X2NvbXVuYXMsDQogICAgICAiSW50ZW5zaWRhZCIgPSBpbnRlbnNpZGFkDQogICAgKQ0KICANCiAgIyBDcmVhciB0YWJsYSBmb3JtYXRlYWRhDQogIHRhYmxhX2ZpbmFsIDwtIHRhYmxhX2NvbXBhcmF0aXZhICU+JQ0KICAgIGthYmxlKA0KICAgICAgY2FwdGlvbiA9ICJUYWJsYSA0LjM6IEFuw6FsaXNpcyBDb21wYXJhdGl2byBDRkcgLSBQcm95ZWN0b3MgdnMgQ29tdW5hcyBBZmVjdGFkYXMiLA0KICAgICAgYWxpZ24gPSBjKCJjIiwgImwiLCByZXAoImMiLCA1KSksDQogICAgICBmb3JtYXQgPSAiaHRtbCIsDQogICAgICBkaWdpdHMgPSAyDQogICAgKSAlPiUNCiAgICBrYWJsZV9zdHlsaW5nKA0KICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksDQogICAgICBmdWxsX3dpZHRoID0gRkFMU0UsDQogICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgZm9udF9zaXplID0gMTENCiAgICApICU+JQ0KICAgIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiIzJjM2U1MCIsIHdpZHRoID0gIjNlbSIpICU+JQ0KICAgIGNvbHVtbl9zcGVjKDIsIHdpZHRoID0gIjE1ZW0iKSAlPiUNCiAgICBjb2x1bW5fc3BlYygzOjcsIHdpZHRoID0gIjZlbSIpICU+JQ0KICAgIGFkZF9oZWFkZXJfYWJvdmUoYygiICIgPSAyLCAiUG9yIFByb3llY3RvcyIgPSAyLCAiUG9yIENvbXVuYXMiID0gMiwgIkluZGljYWRvciIgPSAxKSkgJT4lDQogICAgcm93X3NwZWMoMTozLCBiYWNrZ3JvdW5kID0gIiNmZmU2ZTYiKSAlPiUgICMgVG9wIDMgZW4gcm9qbyBzdWF2ZQ0KICAgIHJvd19zcGVjKDQ6NywgYmFja2dyb3VuZCA9ICIjZmZmMmU2IikgJT4lICAjIFNpZ3VpZW50ZXMgNCBlbiBuYXJhbmphIHN1YXZlDQogICAgZm9vdG5vdGUoDQogICAgICBnZW5lcmFsID0gYygNCiAgICAgICAgIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSBiYXNhZGEgZW4gZGF0b3MgZGVsIEVzdGFkbyBNw6lyaWRhIDIwMTktMjAyNSIsDQogICAgICAgICJJbnRlbnNpZGFkID0gTsKwIFByb3llY3RvcyAvIE7CsCBDb211bmFzIChwcm9tZWRpbyBkZSBwcm95ZWN0b3MgcG9yIGNvbXVuYSBwb3IgdGlwb2xvZ8OtYSkiDQogICAgICApLA0KICAgICAgZ2VuZXJhbF90aXRsZSA9ICIiLA0KICAgICAgZm9vdG5vdGVfYXNfY2h1bmsgPSBUUlVFDQogICAgKQ0KICANCiAgcmV0dXJuKGxpc3QoZGF0b3MgPSB0YWJsYV9jb21wYXJhdGl2YSwgdGFibGEgPSB0YWJsYV9maW5hbCkpDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojICBUQUJMQSBSRVNVTUVOIEVKRUNVVElWTyBDRkcgKFRPUCAxMCkNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNyZWFyX3RhYmxhX3Jlc3VtZW5fY2ZnIDwtIGZ1bmN0aW9uKGRhdGEpIHsNCiAgDQogICMgQ2FsY3VsYXIgZXN0YWTDrXN0aWNhcyByZXN1bWlkYXMNCiAgdG90YWxfcHJveWVjdG9zIDwtIG5yb3coZGF0YSkNCiAgdG90YWxfY29tdW5hcyA8LSBuX2Rpc3RpbmN0KGRhdGEkSURfQ09NVU5BKQ0KICANCiAgcmVzdW1lbl9jZmcgPC0gZGF0YSAlPiUNCiAgICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsIG5hbWUgPSAicHJveWVjdG9zIikgJT4lDQogICAgYXJyYW5nZShkZXNjKHByb3llY3RvcykpICU+JQ0KICAgIHNsaWNlKDE6MTApICU+JSAgIyBTb2xvIHRvcCAxMA0KICAgIG11dGF0ZSgNCiAgICAgIHBjdF9wcm95ZWN0b3MgPSByb3VuZChwcm95ZWN0b3MgLyB0b3RhbF9wcm95ZWN0b3MgKiAxMDAsIDEpLA0KICAgICAgcGN0X2FjdW0gPSByb3VuZChjdW1zdW0ocGN0X3Byb3llY3RvcyksIDEpDQogICAgKSAlPiUNCiAgICAjIEFncmVnYXIgZGF0b3MgZGUgY29tdW5hcw0KICAgIGxlZnRfam9pbigNCiAgICAgIGRhdGEgJT4lDQogICAgICAgIGRpc3RpbmN0KElEX0NPTVVOQSwgQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHKSAlPiUNCiAgICAgICAgY291bnQoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHLCBuYW1lID0gImNvbXVuYXMiKSwNCiAgICAgIGJ5ID0gIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRyINCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHBjdF9jb211bmFzID0gcm91bmQoY29tdW5hcyAvIHRvdGFsX2NvbXVuYXMgKiAxMDAsIDEpLA0KICAgICAgcG9zaWNpb24gPSByb3dfbnVtYmVyKCksDQogICAgICBjYXRlZ29yaWEgPSBjYXNlX3doZW4oDQogICAgICAgIHBvc2ljaW9uIDw9IDMgfiAi8J+UtCBDcsOtdGljbyIsDQogICAgICAgIHBvc2ljaW9uIDw9IDcgfiAi8J+foSBBbHRvIiwNCiAgICAgICAgVFJVRSB+ICLwn5+iIE1lZGlvIg0KICAgICAgKQ0KICAgICkgJT4lDQogICAgc2VsZWN0KA0KICAgICAgcG9zaWNpb24sIGNhdGVnb3JpYSwNCiAgICAgIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgICAgIHByb3llY3RvcywgcGN0X3Byb3llY3RvcywgcGN0X2FjdW0sDQogICAgICBjb211bmFzLCBwY3RfY29tdW5hcw0KICAgICkgJT4lDQogICAgcmVuYW1lKA0KICAgICAgIlBvcy4iID0gcG9zaWNpb24sDQogICAgICAiTml2ZWwiID0gY2F0ZWdvcmlhLA0KICAgICAgIlRpcG9sb2fDrWEgQ0ZHIiA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgICAgICJQcm95LiIgPSBwcm95ZWN0b3MsDQogICAgICAiJSIgPSBwY3RfcHJveWVjdG9zLA0KICAgICAgIiUgQWN1bS4iID0gcGN0X2FjdW0sDQogICAgICAiQ29tLiIgPSBjb211bmFzLA0KICAgICAgIiUgQ29tLiIgPSBwY3RfY29tdW5hcw0KICAgICkNCiAgDQogICMgQ3JlYXIgdGFibGEgZm9ybWF0ZWFkYQ0KICB0YWJsYV9maW5hbCA8LSByZXN1bWVuX2NmZyAlPiUNCiAgICBrYWJsZSgNCiAgICAgIGNhcHRpb24gPSAiVGFibGEgNC40OiBSZXN1bWVuIEVqZWN1dGl2byAtIFRvcCAxMCBUaXBvbG9nw61hcyBDRkcgTcOhcyBDcsOtdGljYXMiLA0KICAgICAgYWxpZ24gPSBjKCJjIiwgImMiLCAibCIsIHJlcCgiYyIsIDUpKSwNCiAgICAgIGZvcm1hdCA9ICJodG1sIg0KICAgICkgJT4lDQogICAga2FibGVfc3R5bGluZygNCiAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLA0KICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgIGZvbnRfc2l6ZSA9IDExDQogICAgKSAlPiUNCiAgICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgd2lkdGggPSAiM2VtIikgJT4lDQogICAgY29sdW1uX3NwZWMoMiwgd2lkdGggPSAiOGVtIikgJT4lDQogICAgY29sdW1uX3NwZWMoMywgd2lkdGggPSAiMTVlbSIpICU+JQ0KICAgIGNvbHVtbl9zcGVjKDQ6OCwgd2lkdGggPSAiNWVtIikgJT4lDQogICAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDMsICJBbsOhbGlzaXMgcG9yIFByb3llY3RvcyIgPSAzLCAiUG9yIENvbXVuYXMiID0gMikpICU+JQ0KICAgIGZvb3Rub3RlKA0KICAgICAgZ2VuZXJhbCA9IHBhc3RlMCgNCiAgICAgICAgIlRvdGFsIGFuYWxpemFkbzogIiwgdG90YWxfcHJveWVjdG9zLCAiIHByb3llY3RvcyBlbiAiLCB0b3RhbF9jb211bmFzLCAiIGNvbXVuYXMuICIsDQogICAgICAgICJFbCBUb3AgMTAgY29uY2VudHJhIGVsICIsIHJvdW5kKHN1bShyZXN1bWVuX2NmZyRgJWApLCAxKSwgIiUgZGUgdG9kb3MgbG9zIG51ZG9zIGNyw610aWNvcy4iDQogICAgICApLA0KICAgICAgZ2VuZXJhbF90aXRsZSA9ICJOb3RhOiIsDQogICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUNCiAgICApDQogIA0KICByZXR1cm4obGlzdChkYXRvcyA9IHJlc3VtZW5fY2ZnLCB0YWJsYSA9IHRhYmxhX2ZpbmFsKSkNCn0NCg0KIyMgR3JhZmljb3MgaW50ZXJlYWN0aXZvcyBkZSBsYXMgZnJlY3VlbmNpYXMgZGUgUGFyZXRvDQoNCiMjPT09PT09PT09PT09PT09PT09PT09PT1GcmVjdWVuY2lhIEdsb2JhbCBDRkcgLSBQcm95ZWN0b3M9PT09PT09PT09PT09PT09PT09PT09PT0jIw0KDQoNCiMgRnVuY2nDs24gQ09SUkVHSURBIHBhcmEgZ3LDoWZpY28gaW50ZXJhY3Rpdm8gZGUgUGFyZXRvIEhPUklaT05UQUwNCmNyZWFyX3BhcmV0b19ob3Jpem9udGFsX2ludGVyYWN0aXZvIDwtIGZ1bmN0aW9uKGRhdGEsIHZhcmlhYmxlLCB0aXR1bG8sIGNvbG9yX2JhcnJhcyA9ICIjMkU4NkFCIiwgY29sb3JfbGluZWEgPSAiI0U2OUYwMCIpIHsNCiAgICANCiAgICAjIENvbnZlcnRpciB2YXJpYWJsZSBhIHPDrW1ib2xvIHkgbHVlZ28gYSBub21icmUNCiAgICB2YXJfc3ltIDwtIGVuc3ltKHZhcmlhYmxlKQ0KICAgIHZhcl9uYW1lIDwtIGFzLmNoYXJhY3Rlcih2YXJfc3ltKQ0KICAgIA0KICAgICMgQ2FsY3VsYXIgZnJlY3VlbmNpYXMgdXNhbmRvIGV2YWx1YWNpw7NuIHRpZHkNCiAgICBmcmVxX2RhdGEgPC0gZGF0YSAlPiUNCiAgICAgICAgY291bnQoISF2YXJfc3ltKSAlPiUNCiAgICAgICAgYXJyYW5nZShkZXNjKG4pKSAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgcG9yY2VudGFqZSA9IG4gLyBzdW0obikgKiAxMDAsDQogICAgICAgICAgICBhY3VtdWxhZG8gPSBjdW1zdW0ocG9yY2VudGFqZSksDQogICAgICAgICAgICBldGlxdWV0YSA9IHBhc3RlMCgNCiAgICAgICAgICAgICAgICAiRnJlY3VlbmNpYTogIiwgbiwgIlxuIiwNCiAgICAgICAgICAgICAgICAiUG9yY2VudGFqZTogIiwgcm91bmQocG9yY2VudGFqZSwgMSksICIlXG4iLA0KICAgICAgICAgICAgICAgICJBY3VtdWxhZG86ICIsIHJvdW5kKGFjdW11bGFkbywgMSksICIlIg0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgICMgQ3JlYXIgdmFyaWFibGUgb3JkZW5hZGEgcGFyYSBlbCBlamUgWSAoaG9yaXpvbnRhbCkNCiAgICAgICAgICAgIHZhcmlhYmxlX29yZGVuYWRhID0gcmVvcmRlcighIXZhcl9zeW0sIG4pDQogICAgICAgICkNCiAgICANCiAgICAjIFBhcmEgcGxvdGx5IGhvcml6b250YWwsIG5lY2VzaXRhbW9zIFkgY29tbyBjYXRlZ29yw61hcyBvcmRlbmFkYXMgeSBYIGNvbW8gdmFsb3Jlcw0KICAgIGZyZXFfZGF0YSR2YXJpYWJsZV9jaGFyIDwtIGFzLmNoYXJhY3RlcihmcmVxX2RhdGEkdmFyaWFibGVfb3JkZW5hZGEpDQogICAgZnJlcV9kYXRhJHZhcmlhYmxlX2NoYXIgPC0gZmFjdG9yKGZyZXFfZGF0YSR2YXJpYWJsZV9jaGFyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gbGV2ZWxzKGZyZXFfZGF0YSR2YXJpYWJsZV9vcmRlbmFkYSkpDQogICAgDQogICAgIyBDYWxjdWxhciBlbCBtw6F4aW1vIHBhcmEgZXNjYWxhciBsYSBsw61uZWEgY29ycmVjdGFtZW50ZQ0KICAgIG1heF9mcmVjdWVuY2lhIDwtIG1heChmcmVxX2RhdGEkbikNCiAgICBlc2NhbGFfbGluZWEgPC0gbWF4X2ZyZWN1ZW5jaWEgLyAxMDANCiAgICANCiAgICAjIENyZWFyIGdyw6FmaWNvIGludGVyYWN0aXZvIEhPUklaT05UQUwNCiAgICBwbG90X2x5KGZyZXFfZGF0YSkgJT4lDQogICAgICAgIGFkZF9iYXJzKA0KICAgICAgICAgICAgeSA9IH52YXJpYWJsZV9jaGFyLCAgIyBFamUgWSBwYXJhIGxhcyBjYXRlZ29yw61hcyAoaG9yaXpvbnRhbCkNCiAgICAgICAgICAgIHggPSB+biwgICAgICAgICAgICAgICMgRWplIFggcGFyYSBsb3MgdmFsb3JlcyAoaG9yaXpvbnRhbCkNCiAgICAgICAgICAgIG5hbWUgPSAiRnJlY3VlbmNpYSIsDQogICAgICAgICAgICBvcmllbnRhdGlvbiA9ICdoJywgICAjIMKhSU1QT1JUQU5URTogZ3LDoWZpY28gaG9yaXpvbnRhbCENCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoDQogICAgICAgICAgICAgICAgY29sb3IgPSBjb2xvcl9iYXJyYXMsDQogICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzFhNTI3NicsIHdpZHRoID0gMSkNCiAgICAgICAgICAgICksDQogICAgICAgICAgICB0ZXh0ID0gfmV0aXF1ZXRhLA0KICAgICAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgICAgICAgICAgdGV4dHBvc2l0aW9uID0gIm5vbmUiDQogICAgICAgICkgJT4lDQogICAgICAgIGFkZF90cmFjZSgNCiAgICAgICAgICAgIHkgPSB+dmFyaWFibGVfY2hhciwNCiAgICAgICAgICAgIHggPSB+YWN1bXVsYWRvICogZXNjYWxhX2xpbmVhLCAgIyBFc2NhbGFyIGxhIGzDrW5lYSBhbCBtaXNtbyByYW5nbyBxdWUgbGFzIGJhcnJhcw0KICAgICAgICAgICAgbmFtZSA9ICJQb3JjZW50YWplIEFjdW11bGFkbyIsDQogICAgICAgICAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgICAgICAgICAgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywNCiAgICAgICAgICAgIGxpbmUgPSBsaXN0KA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY29sb3JfbGluZWEsIA0KICAgICAgICAgICAgICAgIHdpZHRoID0gMywNCiAgICAgICAgICAgICAgICBkYXNoID0gJ3NvbGlkJw0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoDQogICAgICAgICAgICAgICAgY29sb3IgPSBjb2xvcl9saW5lYSwNCiAgICAgICAgICAgICAgICBzaXplID0gNiwNCiAgICAgICAgICAgICAgICBzeW1ib2wgPSAnY2lyY2xlJw0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIHlheGlzID0gInkiLA0KICAgICAgICAgICAgeGF4aXMgPSAieCIsDQogICAgICAgICAgICBob3ZlcmluZm8gPSAieCt0ZXh0IiwNCiAgICAgICAgICAgIHRleHQgPSB+cGFzdGUoIkFjdW11bGFkbzogIiwgcm91bmQoYWN1bXVsYWRvLCAxKSwgIiUiKQ0KICAgICAgICApICU+JQ0KICAgICAgICBsYXlvdXQoDQogICAgICAgICAgICB0aXRsZSA9IGxpc3QoDQogICAgICAgICAgICAgICAgdGV4dCA9IHRpdHVsbywNCiAgICAgICAgICAgICAgICB4ID0gMC4wNSwNCiAgICAgICAgICAgICAgICBmb250ID0gbGlzdChzaXplID0gMTYsIGNvbG9yID0gIiMyYzNlNTAiKQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIHlheGlzID0gbGlzdCgNCiAgICAgICAgICAgICAgICB0aXRsZSA9ICIiLA0KICAgICAgICAgICAgICAgIHNob3dncmlkID0gRkFMU0UsDQogICAgICAgICAgICAgICAgdGlja2ZvbnQgPSBsaXN0KHNpemUgPSAxMSkNCiAgICAgICAgICAgICksDQogICAgICAgICAgICB4YXhpcyA9IGxpc3QoDQogICAgICAgICAgICAgICAgdGl0bGUgPSAiRnJlY3VlbmNpYSBkZSBQcm95ZWN0b3MiLA0KICAgICAgICAgICAgICAgIHNob3dncmlkID0gVFJVRSwNCiAgICAgICAgICAgICAgICBncmlkY29sb3IgPSAiI2YwZjBmMCIsDQogICAgICAgICAgICAgICAgc2lkZSA9ICJib3R0b20iDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgc2hvd2xlZ2VuZCA9IFRSVUUsDQogICAgICAgICAgICBsZWdlbmQgPSBsaXN0KA0KICAgICAgICAgICAgICAgIHggPSAwLjAyLCANCiAgICAgICAgICAgICAgICB5ID0gMC45OCwNCiAgICAgICAgICAgICAgICBiZ2NvbG9yID0gInJnYmEoMjU1LDI1NSwyNTUsMC44KSIsDQogICAgICAgICAgICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDEyKQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDE1MCwgciA9IDUwLCBiID0gODAsIHQgPSA2MCksICAjIE1hcmdlbiBpenF1aWVyZG8gbWF5b3IgcGFyYSBldGlxdWV0YXMgbGFyZ2FzDQogICAgICAgICAgICBob3ZlcmxhYmVsID0gbGlzdCgNCiAgICAgICAgICAgICAgICBiZ2NvbG9yID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgICBib3JkZXJjb2xvciA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDEyKQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgICMgRWplIHNlY3VuZGFyaW8gcGFyYSBlbCBwb3JjZW50YWplIChwYXJ0ZSBzdXBlcmlvcikNCiAgICAgICAgICAgIHhheGlzMiA9IGxpc3QoDQogICAgICAgICAgICAgICAgdGl0bGUgPSAiUG9yY2VudGFqZSBBY3VtdWxhZG8gKCUpIiwNCiAgICAgICAgICAgICAgICBvdmVybGF5aW5nID0gIngiLA0KICAgICAgICAgICAgICAgIHNpZGUgPSAidG9wIiwNCiAgICAgICAgICAgICAgICByYW5nZSA9IGMoMCwgMTAwKSwNCiAgICAgICAgICAgICAgICBzaG93Z3JpZCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIHRpY2tmb250ID0gbGlzdChjb2xvciA9IGNvbG9yX2xpbmVhKQ0KICAgICAgICAgICAgKQ0KICAgICAgICApICU+JQ0KICAgICAgICBjb25maWcoDQogICAgICAgICAgICBkaXNwbGF5TW9kZUJhciA9IFRSVUUsDQogICAgICAgICAgICBtb2RlQmFyQnV0dG9uc1RvUmVtb3ZlID0gYygicGFuMmQiLCAibGFzc28yZCIsICJzZWxlY3QyZCIpLA0KICAgICAgICAgICAgZGlzcGxheWxvZ28gPSBGQUxTRQ0KICAgICAgICApDQp9DQoNCiMgR3LDoWZpY28gaW50ZXJhY3Rpdm8gcGFyYSBDRkcgcG9yIHByb3llY3RvcyAtIFZFUlNJw5NOIEhPUklaT05UQUwgQ09SUkVHSURBDQpjcmVhcl9wYXJldG9faG9yaXpvbnRhbF9pbnRlcmFjdGl2bygNCiAgICBkZl9kdW1taWVzLA0KICAgIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywNCiAgICAiRGlzdHJpYnVjacOzbiBkZSBUaXBvbG9nw61hcyBDRkcgLSBQYXJldG8gcG9yIE7Dum1lcm8gZGUgUHJveWVjdG9zIiwNCiAgICAiIzM0OThkYiIsICIjZTc0YzNjIg0KKQ0KDQoNCiMjPT09PT09PT09PT09PT09PT09PT09PT1GcmVjdWVuY2lhIEdsb2JhbCBDRkcgLSBDb211bmFzPT09PT09PT09PT09PT09PT09PT09PT09IyMNCg0KIyBGdW5jacOzbiBwYXJhIFBhcmV0byBwb3IgY29tdW5hcyAoSE9SSVpPTlRBTCkNCmNyZWFyX3BhcmV0b19jb211bmFzX2ludGVyYWN0aXZvIDwtIGZ1bmN0aW9uKGRhdGEsIHZhcmlhYmxlLCB0aXR1bG8sIGNvbG9yX2JhcnJhcyA9ICIjMmMzZTUwIiwgY29sb3JfbGluZWEgPSAiI2YzOWMxMiIpIHsNCiAgICANCiAgICAjIENvbnZlcnRpciB2YXJpYWJsZSBhIHPDrW1ib2xvDQogICAgdmFyX3N5bSA8LSBlbnN5bSh2YXJpYWJsZSkNCiAgICANCiAgICAjIENhbGN1bGFyIGZyZWN1ZW5jaWFzIHBvciBjb211bmEgKHNpbiByZXBldGlyIGNvbXVuYXMpDQogICAgZnJlcV9kYXRhIDwtIGRhdGEgJT4lDQogICAgICAgIGRpc3RpbmN0KElEX0NPTVVOQSwgISF2YXJfc3ltKSAlPiUgIA0KICAgICAgICBjb3VudCghIXZhcl9zeW0sIG5hbWUgPSAibl9jb211bmFzIikgJT4lDQogICAgICAgIGFycmFuZ2UoZGVzYyhuX2NvbXVuYXMpKSAlPiUNCiAgICAgICAgbXV0YXRlKA0KICAgICAgICAgICAgcG9yY2VudGFqZSA9IG5fY29tdW5hcyAvIHN1bShuX2NvbXVuYXMpICogMTAwLA0KICAgICAgICAgICAgYWN1bXVsYWRvID0gY3Vtc3VtKHBvcmNlbnRhamUpLA0KICAgICAgICAgICAgZXRpcXVldGEgPSBwYXN0ZTAoDQogICAgICAgICAgICAgICAgIkNvbXVuYXM6ICIsIG5fY29tdW5hcywgIlxuIiwNCiAgICAgICAgICAgICAgICAiUG9yY2VudGFqZTogIiwgcm91bmQocG9yY2VudGFqZSwgMSksICIlXG4iLA0KICAgICAgICAgICAgICAgICJBY3VtdWxhZG86ICIsIHJvdW5kKGFjdW11bGFkbywgMSksICIlIg0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgICMgQ3JlYXIgdmFyaWFibGUgb3JkZW5hZGEgcGFyYSBlbCBlamUgWSAoaG9yaXpvbnRhbCkNCiAgICAgICAgICAgIHZhcmlhYmxlX29yZGVuYWRhID0gcmVvcmRlcighIXZhcl9zeW0sIG5fY29tdW5hcykNCiAgICAgICAgKQ0KICAgIA0KICAgICMgUHJlcGFyYXIgZGF0b3MgcGFyYSBwbG90bHkgaG9yaXpvbnRhbA0KICAgIGZyZXFfZGF0YSR2YXJpYWJsZV9jaGFyIDwtIGFzLmNoYXJhY3RlcihmcmVxX2RhdGEkdmFyaWFibGVfb3JkZW5hZGEpDQogICAgZnJlcV9kYXRhJHZhcmlhYmxlX2NoYXIgPC0gZmFjdG9yKGZyZXFfZGF0YSR2YXJpYWJsZV9jaGFyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gbGV2ZWxzKGZyZXFfZGF0YSR2YXJpYWJsZV9vcmRlbmFkYSkpDQogICAgDQogICAgIyBDYWxjdWxhciBlbCBtw6F4aW1vIHBhcmEgZXNjYWxhciBsYSBsw61uZWEgY29ycmVjdGFtZW50ZQ0KICAgIG1heF9jb211bmFzIDwtIG1heChmcmVxX2RhdGEkbl9jb211bmFzKQ0KICAgIGVzY2FsYV9saW5lYSA8LSBtYXhfY29tdW5hcyAvIDEwMA0KICAgIA0KICAgICMgQ3JlYXIgZ3LDoWZpY28gaW50ZXJhY3Rpdm8gSE9SSVpPTlRBTA0KICAgIHBsb3RfbHkoZnJlcV9kYXRhKSAlPiUNCiAgICAgICAgYWRkX2JhcnMoDQogICAgICAgICAgICB5ID0gfnZhcmlhYmxlX2NoYXIsDQogICAgICAgICAgICB4ID0gfm5fY29tdW5hcywNCiAgICAgICAgICAgIG5hbWUgPSAiTsO6bWVybyBkZSBDb211bmFzIiwNCiAgICAgICAgICAgIG9yaWVudGF0aW9uID0gJ2gnLA0KICAgICAgICAgICAgbWFya2VyID0gbGlzdCgNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNvbG9yX2JhcnJhcywNCiAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjMWMyODMzJywgd2lkdGggPSAxKQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIHRleHQgPSB+ZXRpcXVldGEsDQogICAgICAgICAgICBob3ZlcmluZm8gPSAidGV4dCIsDQogICAgICAgICAgICB0ZXh0cG9zaXRpb24gPSAibm9uZSINCiAgICAgICAgKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKA0KICAgICAgICAgICAgeSA9IH52YXJpYWJsZV9jaGFyLA0KICAgICAgICAgICAgeCA9IH5hY3VtdWxhZG8gKiBlc2NhbGFfbGluZWEsDQogICAgICAgICAgICBuYW1lID0gIlBvcmNlbnRhamUgQWN1bXVsYWRvIiwNCiAgICAgICAgICAgIHR5cGUgPSAnc2NhdHRlcicsDQogICAgICAgICAgICBtb2RlID0gJ2xpbmVzK21hcmtlcnMnLA0KICAgICAgICAgICAgbGluZSA9IGxpc3QoDQogICAgICAgICAgICAgICAgY29sb3IgPSBjb2xvcl9saW5lYSwgDQogICAgICAgICAgICAgICAgd2lkdGggPSAzLA0KICAgICAgICAgICAgICAgIGRhc2ggPSAnc29saWQnDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgbWFya2VyID0gbGlzdCgNCiAgICAgICAgICAgICAgICBjb2xvciA9IGNvbG9yX2xpbmVhLA0KICAgICAgICAgICAgICAgIHNpemUgPSA2LA0KICAgICAgICAgICAgICAgIHN5bWJvbCA9ICdjaXJjbGUnDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgaG92ZXJpbmZvID0gIngrdGV4dCIsDQogICAgICAgICAgICB0ZXh0ID0gfnBhc3RlKCJBY3VtdWxhZG86ICIsIHJvdW5kKGFjdW11bGFkbywgMSksICIlIikNCiAgICAgICAgKSAlPiUNCiAgICAgICAgbGF5b3V0KA0KICAgICAgICAgICAgdGl0bGUgPSBsaXN0KA0KICAgICAgICAgICAgICAgIHRleHQgPSB0aXR1bG8sDQogICAgICAgICAgICAgICAgeCA9IDAuMDUsDQogICAgICAgICAgICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDE2LCBjb2xvciA9ICIjMmMzZTUwIikNCiAgICAgICAgICAgICksDQogICAgICAgICAgICB5YXhpcyA9IGxpc3QoDQogICAgICAgICAgICAgICAgdGl0bGUgPSAiIiwNCiAgICAgICAgICAgICAgICBzaG93Z3JpZCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIHRpY2tmb250ID0gbGlzdChzaXplID0gMTEpDQogICAgICAgICAgICApLA0KICAgICAgICAgICAgeGF4aXMgPSBsaXN0KA0KICAgICAgICAgICAgICAgIHRpdGxlID0gIk7Dum1lcm8gZGUgQ29tdW5hcyBBZmVjdGFkYXMiLA0KICAgICAgICAgICAgICAgIHNob3dncmlkID0gVFJVRSwNCiAgICAgICAgICAgICAgICBncmlkY29sb3IgPSAiI2YwZjBmMCINCiAgICAgICAgICAgICksDQogICAgICAgICAgICBzaG93bGVnZW5kID0gVFJVRSwNCiAgICAgICAgICAgIGxlZ2VuZCA9IGxpc3QoDQogICAgICAgICAgICAgICAgeCA9IDAuMDIsIA0KICAgICAgICAgICAgICAgIHkgPSAwLjk4LA0KICAgICAgICAgICAgICAgIGJnY29sb3IgPSAicmdiYSgyNTUsMjU1LDI1NSwwLjgpIg0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDE1MCwgciA9IDUwLCBiID0gODAsIHQgPSA2MCksDQogICAgICAgICAgICBob3ZlcmxhYmVsID0gbGlzdCgNCiAgICAgICAgICAgICAgICBiZ2NvbG9yID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgICBib3JkZXJjb2xvciA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDEyKQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIHhheGlzMiA9IGxpc3QoDQogICAgICAgICAgICAgICAgdGl0bGUgPSAiUG9yY2VudGFqZSBBY3VtdWxhZG8gKCUpIiwNCiAgICAgICAgICAgICAgICBvdmVybGF5aW5nID0gIngiLA0KICAgICAgICAgICAgICAgIHNpZGUgPSAidG9wIiwNCiAgICAgICAgICAgICAgICByYW5nZSA9IGMoMCwgMTAwKSwNCiAgICAgICAgICAgICAgICBzaG93Z3JpZCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIHRpY2tmb250ID0gbGlzdChjb2xvciA9IGNvbG9yX2xpbmVhKQ0KICAgICAgICAgICAgKQ0KICAgICAgICApICU+JQ0KICAgICAgICBjb25maWcoDQogICAgICAgICAgICBkaXNwbGF5TW9kZUJhciA9IFRSVUUsDQogICAgICAgICAgICBtb2RlQmFyQnV0dG9uc1RvUmVtb3ZlID0gYygicGFuMmQiLCAibGFzc28yZCIsICJzZWxlY3QyZCIpLA0KICAgICAgICAgICAgZGlzcGxheWxvZ28gPSBGQUxTRQ0KICAgICAgICApDQp9DQoNCiMgR3LDoWZpY28gaW50ZXJhY3Rpdm8gcGFyYSBDRkcgcG9yIGNvbXVuYXMNCmNyZWFyX3BhcmV0b19jb211bmFzX2ludGVyYWN0aXZvKA0KICAgIGRmX2R1bW1pZXMsDQogICAgQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHLA0KICAgICJEaXN0cmlidWNpw7NuIGRlIFRpcG9sb2fDrWFzIENGRyAtIFBhcmV0byBwb3IgTsO6bWVybyBkZSBDb211bmFzIEFmZWN0YWRhcyIsDQogICAgIiMyYzNlNTAiLCAiI2YzOWMxMiINCikNCg0KYGBgDQoNCiMjICoqQW7DoWxpc2lzIGRlIFRpcG9sb2fDrWFzIENGRzogVGFibGFzIERlc2NyaXB0aXZhcyoqDQoNCkVuIGVzdGEgc2VjY2nDs24gcHJlc2VudGFtb3MgZWwgYW7DoWxpc2lzIGRldGFsbGFkbyBkZSBsYXMgdGlwb2xvZ8OtYXMgQ0ZHIG1lZGlhbnRlIHRhYmxhcyBkZXNjcmlwdGl2YXMgcXVlIHBlcm1pdGVuIHZpc3VhbGl6YXIgbGEgZGlzdHJpYnVjacOzbiwgZnJlY3VlbmNpYSBlIGltcGFjdG8gdGVycml0b3JpYWwgZGUgbG9zIG51ZG9zIGNyw610aWNvcyBpZGVudGlmaWNhZG9zLg0KDQpFc3RlIHJldmVsYSB1bmEgZGlzdHJpYnVjacOzbiBhbHRhbWVudGUgY29uY2VudHJhZGEgZGUgbG9zIG51ZG9zIGNyw610aWNvcywgZG9uZGUgTWFuZWpvIEludGVncmFsIGRlbCBBZ3VhIGVtZXJnZSBpbmVxdcOtdm9jYW1lbnRlIGNvbW8gZWwgcHJvYmxlbWEgbcOhcyBjb23Dum4gZGVsIEVzdGFkbyBNw6lyaWRhLiBDb24gNTQgcHJveWVjdG9zIHJlcHJlc2VudGFuZG8gZWwgMjcsMjclIGRlbCB0b3RhbCwgZXN0YSB0aXBvbG9nw61hIHN1cGVyYSBwb3IgdW4gbWFyZ2VuIGNvbnNpZGVyYWJsZSBhIHRvZGFzIGxhcyBkZW3DoXMgY2F0ZWdvcsOtYXMsIGVzdGFibGVjaWVuZG8gdW5hIGJyZWNoYSBzaWduaWZpY2F0aXZhIGRlIDEyIHB1bnRvcyBwb3JjZW50dWFsZXMgY29uIHJlc3BlY3RvIGEgVmlhbGlkYWQsIHF1ZSBvY3VwYSBlbCBzZWd1bmRvIGx1Z2FyIGNvbiAzMCBwcm95ZWN0b3MgKDE1LDE1JSkuDQoNCkVsIGFuw6FsaXNpcyBkZWwgcG9yY2VudGFqZSBhY3VtdWxhZG8gZGVtdWVzdHJhIGxhIGFwbGljYWNpw7NuIHByw6FjdGljYSBkZWwgcHJpbmNpcGlvIGRlIFBhcmV0byBlbiBsYSBwcm9ibGVtw6F0aWNhIGVzdGF0YWw6DQoNCuKAoiBMYXMgcHJpbWVyYXMgNCB0aXBvbG9nw61hcyAoTWFuZWpvIEludGVncmFsIGRlbCBBZ3VhLCBWaWFsaWRhZCwgVml2aWVuZGEgeSBFbGVjdHJpY2lkYWQpIGNvbmNlbnRyYW4gZWwgNjIsNjMlIGRlIHRvZG9zIGxvcyBudWRvcyBjcsOtdGljb3MNCg0K4oCiIExhcyBwcmltZXJhcyA3IHRpcG9sb2fDrWFzIGFsY2FuemFuIGVsIDgwLDgxJSBkZWwgdG90YWwsIGNvbmZpcm1hbmRvIHF1ZSBhcHJveGltYWRhbWVudGUgZWwgODAlIGRlIGxvcyBwcm9ibGVtYXMgc2UgY29uY2VudHJhIGVuIG1lbm9zIGRlbCA1MCUgZGUgbGFzIGNhdGVnb3LDrWFzLiBFc3RhIGNvbmNlbnRyYWNpw7NuIGluZGljYSBxdWUgdW5hIGVzdHJhdGVnaWEgZGUgaW50ZXJ2ZW5jacOzbiBmb2NhbGl6YWRhIGVuIGVzdGFzIMOhcmVhcyBwcmluY2lwYWxlcyBwb2Ryw61hIGF0ZW5kZXIgbGEgbWF5b3LDrWEgZGUgbG9zIHByb2JsZW1hcyBpZGVudGlmaWNhZG9zIGNvbiB1bmEgZWZpY2llbmNpYSBjb25zaWRlcmFibGUgZW4gZWwgdXNvIGRlIHJlY3Vyc29zIHDDumJsaWNvcy4NCg0KTGEgZGlzdHJpYnVjacOzbiBwZXJtaXRlIGVzdGFibGVjZXIgdHJlcyBuaXZlbGVzIGRlIGNyaXRpY2lkYWQgY2xhcmFtZW50ZSBkaWZlcmVuY2lhZG9zOiBOaXZlbCBDcsOtdGljbyBBbHRvIChQb3NpY2lvbmVzIDEtNCk6IE1hbmVqbyBJbnRlZ3JhbCBkZWwgQWd1YSwgVmlhbGlkYWQsIFZpdmllbmRhIHkgRWxlY3RyaWNpZGFkIHJlcHJlc2VudGFuIGxvcyBzZXJ2aWNpb3MgYsOhc2ljb3MgZnVuZGFtZW50YWxlcyBkZWwgZXN0YWRvLCBjb24gZnJlY3VlbmNpYXMgcXVlIHZhbiBkZXNkZSA1NCBoYXN0YSAxOSBwcm95ZWN0b3MuDQoNCk5pdmVsIENyw610aWNvIE1lZGlvIChQb3NpY2lvbmVzIDUtNyk6IFNhbHVkLCBJbmZyYWVzdHJ1Y3R1cmEgeSBBbWJpZW50ZSBjb25maWd1cmFuIHVuIHNlZ3VuZG8gZ3J1cG8gZGUgcHJvYmxlbWFzIHNpZ25pZmljYXRpdm9zLCBjb24gZnJlY3VlbmNpYXMgZW50cmUgMTQgeSAxMCBwcm95ZWN0b3MuDQoNCk5pdmVsIENyw610aWNvIEJham8gKFBvc2ljaW9uZXMgOC0xNik6IExhcyBudWV2ZSB0aXBvbG9nw61hcyByZXN0YW50ZXMgcHJlc2VudGFuIGZyZWN1ZW5jaWFzIG1lbm9yZXMgYSAxMCBwcm95ZWN0b3MgY2FkYSB1bmEsIHJlcHJlc2VudGFuZG8gcHJvYmxlbWFzIGltcG9ydGFudGVzLCBwZXJvIGRlIG1lbm9yIGVzY2FsYSByZWxhdGl2YS4NCg0KIyMjICoqVGFibGEgZGUgRGlzdHJpYnVjacOzbiBkZSBGcmVjdWVuY2lhcyBkZSBUaXBvbG9nw61hcyBDRkcgcG9yIE7Dum1lcm8gZGUgUHJveWVjdG9zKioNCg0KYGBge3IgdGFibGFfNC4xLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBHZW5lcmFyIHRhYmxhIGRlIHByb3llY3Rvcw0KdGFibGFfcHJveWVjdG9zIDwtIGNyZWFyX3RhYmxhX2NmZ19wcm95ZWN0b3MoZGZfZHVtbWllcykNCnRhYmxhX3Byb3llY3RvcyR0YWJsYQ0KYGBgDQoNCipOb3RhOiBMYSB0YWJsYSBtdWVzdHJhIGxhIGRpc3RyaWJ1Y2nDs24gYWJzb2x1dGEgeSByZWxhdGl2YSBkZSBsYXMgdGlwb2xvZ8OtYXMgQ0ZHIHNlZ8O6biBlbCBuw7ptZXJvIGRlIHByb3llY3RvcyBhc29jaWFkb3MuKg0KDQojIyMgKipUYWJsYSBkZSBEaXN0cmlidWNpw7NuIGRlIEZyZWN1ZW5jaWFzIGRlIFRpcG9sb2fDrWFzIENGRyBwb3IgTsO6bWVybyBkZSBDb211bmFzIEFmZWN0YWRhcyoqDQoNCmBgYHtyIHRhYmxhXzQuMiwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgR2VuZXJhciB0YWJsYSBkZSBjb211bmFzDQp0YWJsYV9jb211bmFzIDwtIGNyZWFyX3RhYmxhX2NmZ19jb211bmFzKGRmX2R1bW1pZXMpDQp0YWJsYV9jb211bmFzJHRhYmxhDQpgYGANCg0KKk5vdGE6IEVzdGEgdGFibGEgcmVwcmVzZW50YSBsYSBkaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsIGRlIGxhcyB0aXBvbG9nw61hcywgY29udGFiaWxpemFuZG8gY3XDoW50YXMgY29tdW5hcyBlc3TDoW4gYWZlY3RhZGFzIHBvciBjYWRhIHRpcG8gZGUgbnVkbyBjcsOtdGljby4qDQoNCiMjIyAqKlRhYmxhIGRlIEFuw6FsaXNpcyBDb21wYXJhdGl2byBDRkcgLSBQcm95ZWN0b3MgdnMgQ29tdW5hcyBBZmVjdGFkYXMqKg0KDQpgYGB7ciB0YWJsYV80LjMsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEdlbmVyYXIgdGFibGEgY29tcGFyYXRpdmENCnRhYmxhX2NvbXBhcmF0aXZhIDwtIGNyZWFyX3RhYmxhX2NvbXBhcmF0aXZhX2NmZyhkZl9kdW1taWVzKQ0KdGFibGFfY29tcGFyYXRpdmEkdGFibGENCmBgYA0KDQoqTm90YTogRWwgaW5kaWNhZG9yIGRlIGludGVuc2lkYWQgKHByb3llY3Rvcy9jb211bmEpIHBlcm1pdGUgaWRlbnRpZmljYXIgdGlwb2xvZ8OtYXMgY29uIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIHByb2JsZW1hcyBwb3IgdGVycml0b3Jpby4qDQoNCiMjIyAqKlRhYmxhIGRlIFJlc3VtZW4gRWplY3V0aXZvIC0gVG9wIDEwIFRpcG9sb2fDrWFzIENGRyBNw6FzIENyw610aWNhcyoqDQoNCmBgYHtyIHRhYmxhXzQuNCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgR2VuZXJhciB0YWJsYSByZXN1bWVuIGVqZWN1dGl2bw0KdGFibGFfcmVzdW1lbiA8LSBjcmVhcl90YWJsYV9yZXN1bWVuX2NmZyhkZl9kdW1taWVzKQ0KdGFibGFfcmVzdW1lbiR0YWJsYQ0KYGBgDQoNCipOb3RhOiBDbGFzaWZpY2FjacOzbiBwb3Igbml2ZWwgZGUgY3JpdGljaWRhZCBiYXNhZG8gZW4gbGEgZnJlY3VlbmNpYSBkZSBhcGFyaWNpw7NuIHkgZGlzdHJpYnVjacOzbiB0ZXJyaXRvcmlhbC4qDQoNCiMjICoqRnJlY3VlbmNpYXMgZGUgR29iZXJuYWNpw7NuKioNCg0KU2Ugb2JzZXJ2YSB1bmEgY2xhcmEgZGlzdHJpYnVjacOzbiBkZSBQYXJldG8sIGRvbmRlIGxhcyBtaXNtYXMgY3VhdHJvIGNhdGVnb3LDrWFzIHByaW5jaXBhbGVzLCBsYSBjYXJ0ZXJhIGRlIHByb3llY3RvcyBkZSBsYSBHb2Jlcm5hY2nDs24gZXN0w6EgZG9taW5hZGEgcG9yIHVuYSBjbGFyYSBwcmlvcml6YWNpw7NuIGRlIGxvcyBzZXJ2aWNpb3MgYsOhc2ljb3MuIExhcyBjdWF0cm8gcHJpbWVyYXMgY2F0ZWdvcsOtYXMgKEFndWEgUG90YWJsZSDigJMgKioxNCwxNCUqKiwgVml2aWVuZGEg4oCTICoqMTEsNjIlKiosIEVsZWN0cmljaWRhZCDigJMgKio5LDYwJSoqLCBWaWFsaWRhZCDigJMgKio5LDA5JSoqKSBjb25jZW50cmFuIDQ0LDQ1JSBkZSB0b2RvcyBsb3MgcHJveWVjdG9zLiBFc3RvIGluZGljYSBxdWUgbGEgZXN0cmF0ZWdpYSBpbnN0aXR1Y2lvbmFsIHNlIGNlbnRyYSBlbiBhdGVuZGVyIGxvcyBkw6lmaWNpdHMgbcOhcyBlc2VuY2lhbGVzIHBhcmEgbGEgY2FsaWRhZCBkZSB2aWRhIHkgZWwgZGVzYXJyb2xsbzogYWNjZXNvIGFsIGFndWEsIHZpdmllbmRhIGRpZ25hLCBlbmVyZ8OtYSB5IGNvbmVjdGl2aWRhZC4NCg0KVW4gc2VndW5kbyBncnVwbyBkZSBjYXRlZ29yw61hcyByZWNpYmUgdW5hIGF0ZW5jacOzbiBzaWduaWZpY2F0aXZhLCBhdW5xdWUgbWVub3IuICJFcXVpcGFtaWVudG8gU2FsdWQiICg3LDA3JSksICJBZ3VhIFJlc2lkdWFsIiAoNiw1NyUpLCAiRHJlbmFqZXMiICg2LDU3JSkgeSAiRXF1aXBhbWllbnRvIEVkdWNhdGl2byIgKDYsMDYlKSByZXByZXNlbnRhbiB1biAyNiwyNyUgYWRpY2lvbmFsIGRlIGxvcyBwcm95ZWN0b3MuIExhIGzDrW5lYSBkZSBwb3JjZW50YWplIGFjdW11bGFkbyBtdWVzdHJhIHF1ZSBzZSBuZWNlc2l0YW4gbGFzIHByaW1lcmFzIDggY2F0ZWdvcsOtYXMgcGFyYSBhbGNhbnphciBhcHJveGltYWRhbWVudGUgZWwgNzAlIGRlIGxvcyBwcm95ZWN0b3MuIExhcyAxMyBjYXRlZ29yw61hcyByZXN0YW50ZXMgY29uc3RpdHV5ZW4gdW5hICJsYXJnYSBjb2xhIiBkZSBwcm9ibGVtw6F0aWNhcyBxdWUsIHNpIGJpZW4gc29uIGNyw610aWNhcyBwYXJhIGxhcyBjb211bmlkYWRlcyBxdWUgbGFzIHBhZGVjZW4sIHJlcHJlc2VudGFuIHVuYSBwb3JjacOzbiBtZW5vciBkZSBsYSBjYXJ0ZXJhIGdsb2JhbCBkZSBsYSBHb2Jlcm5hY2nDs24uDQoNCkxhIGRpc3RyaWJ1Y2nDs24gc2lndWUgdW4gcHJpbmNpcGlvIGRlIFBhcmV0bywgZG9uZGUgdW5hIG1pbm9yw61hIGRlIGNhdGVnb3LDrWFzIGNvbmNlbnRyYSBsYSBtYXlvcsOtYSBkZSBsb3MgZXNmdWVyem9zIGluc3RpdHVjaW9uYWxlcy4NCg0KYGBge3IsIGZyZWN1ZW5jaWEgZ2xvYmFsIEdvYmVybmFjaW9ufQ0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1SZXN1bWVuIEdvYmVybmFjacOzbiBwb3IgQ29tdW5hLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyMgQW7DoWxpc2lzIHBhcmEgR29iZXJuYWNpw7NuIC0tLS0NCiMgQ29udGVvIHkgcHJvcG9yY2lvbmVzIGdsb2JhbGVzIHBvciBUaXBvbG9naWEgZGUgR29iZXJuYWNpw7NuDQpmcmVxX2dvYiA8LSBkZl9kdW1taWVzICU+JQ0KICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLCBuYW1lID0gIm4iKSAlPiUNCiAgYXJyYW5nZShkZXNjKG4pKSAlPiUNCiAgbXV0YXRlKHBjdCA9IG4gLyBzdW0obikgKiAxMDApDQoNCg0KIyAgR3LDoWZpY28gZGUgYmFycmFzIChUb3AgMTApIGRlIGdvYmVybmFjacOzbiBwb3IgcHJveWVjdG9zDQpmcmVxX2dvYiAlPiUNCiAgc2xpY2UoMToxMCkgJT4lDQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTiwgbiksDQogICAgICAgICAgICAgeSA9IG4pKSArDQogICAgZ2VvbV9jb2woZmlsbCA9ICJkYXJrcmVkIikgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIlRvcCAxMCBjYXRlZ29yw61hcyBkZSBHb2Jlcm5hY2nDs24gbcOhcyBmcmVjdWVudGVzIiwNCiAgICAgIHggICAgID0gIkNhdGVnb3LDrWEgZGUgR29iZXJuYWNpw7NuIiwNCiAgICAgIHkgICAgID0gIk7Dum1lcm8gZGUgcHJveWVjdG9zIg0KICAgICkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KDQojIEZyZWN1ZW5jaWEgYWJzb2x1dGEgeSByZWxhdGl2YSBwb3IgY29tdW5hDQpmcmVxX2dvYl9jb211bmEgPC0gZGZfZHVtbWllcyAlPiUNCiAgZGlzdGluY3QoSURfQ09NVU5BLCBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OKSAlPiUgIA0KICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLCBuYW1lID0gIm5fY29tdW5hcyIpICU+JQ0KICBhcnJhbmdlKGRlc2Mobl9jb211bmFzKSkgJT4lDQogIG11dGF0ZSgNCiAgICBwY3RfY29tdW5hcyA9IG5fY29tdW5hcyAvIHN1bShuX2NvbXVuYXMpICogMTAwLA0KICAgIGN1bV9wY3QgICAgID0gY3Vtc3VtKHBjdF9jb211bmFzKQ0KICApDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1HcsOhZmljbyBkZSB0b3AgMTAgcG9yIGNvbXVuYS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZnJlcV9nb2JfY29tdW5hICU+JQ0KICBzbGljZSgxOjEwKSAlPiUNCiAgZ2dwbG90KGFlcygNCiAgICB4ID0gcmVvcmRlcihDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLCBuX2NvbXVuYXMpLA0KICAgIHkgPSBuX2NvbXVuYXMNCiAgKSkgKw0KICBnZW9tX2NvbChmaWxsID0gImRhcmtyZWQiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVG9wIDEwIGNhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbiBwb3IgbsO6bWVybyBkZSBjb211bmFzIiwNCiAgICB4ICAgICA9ICJDYXRlZ29yw61hIGRlIEdvYmVybmFjacOzbiIsDQogICAgeSAgICAgPSAiTsO6bWVybyBkZSBjb211bmFzIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tR2xvYmFsIC0gUHJveWVjdG9zLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZ29iX2dsb2JhbF9wcm95ZWN0b3MgPC0gYW5hbGl6YXJfZnJlY3VlbmNpYSgNCiAgZGZfcmF3LA0KICBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLA0KICAiZGFya3JlZCIsICJnb2xkIiwNCiAgIkZyZWN1ZW5jaWEgZ2xvYmFsIGRlIGNhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbiAoUHJveWVjdG9zKSIsDQogICJwcm95ZWN0b3MiDQopDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLUdsb2JhbCAtIENvbXVuYXMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZ29iX2dsb2JhbF9jb211bmFzIDwtIGFuYWxpemFyX2ZyZWN1ZW5jaWFfY29tdW5hKA0KICBkZl9yYXcsDQogIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sDQogICJkYXJrcmVkIiwgImdvbGQiLA0KICAiRnJlY3VlbmNpYSBkZSBjYXRlZ29yw61hcyBkZSBHb2Jlcm5hY2nDs24gcG9yIGNvbXVuYSINCikNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS1HcmFmaWNvIGRlIGZyZWN1ZW5jaWFzIGRlIGNhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbi0tLS0tLS0tLS0tLS0NCnByaW50KGdvYl9nbG9iYWxfcHJveWVjdG9zJHBsb3QpDQoNCiMtLS0tR3JhZmljbyBGcmVjdWVuY2lhIGFic29sdXRhIHkgcmVsYXRpdmEgZGUgY29tdW5hcyBwb3IgY2F0ZWdvcsOtYSBkZSBHb2Jlcm5hY2nDs24tLS0tDQpwcmludChnb2JfZ2xvYmFsX2NvbXVuYXMkcGxvdCkNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIFRBQkxBIENPTVBMRVRBIERFIEZSRUNVRU5DSUFTIEdPQkVSTkFDScOTTiBQT1IgUFJPWUVDVE9TDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KY3JlYXJfdGFibGFfZ29iX3Byb3llY3RvcyA8LSBmdW5jdGlvbihkYXRhKSB7DQogIA0KICAjIENhbGN1bGFyIGZyZWN1ZW5jaWFzDQogIHRhYmxhX2dvYiA8LSBkYXRhICU+JQ0KICAgIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sIG5hbWUgPSAibl9wcm95ZWN0b3MiKSAlPiUNCiAgICBhcnJhbmdlKGRlc2Mobl9wcm95ZWN0b3MpKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwb3JjZW50YWplID0gcm91bmQobl9wcm95ZWN0b3MgLyBzdW0obl9wcm95ZWN0b3MpICogMTAwLCAyKSwNCiAgICAgIHBjdF9hY3VtdWxhZG8gPSByb3VuZChjdW1zdW0ocG9yY2VudGFqZSksIDIpLA0KICAgICAgcmFua2luZyA9IHJvd19udW1iZXIoKQ0KICAgICkgJT4lDQogICAgcmVuYW1lKA0KICAgICAgIlJhbmtpbmciID0gcmFua2luZywNCiAgICAgICJDYXRlZ29yw61hIEdvYmVybmFjacOzbiIgPSBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLA0KICAgICAgIk7CsCBQcm95ZWN0b3MiID0gbl9wcm95ZWN0b3MsDQogICAgICAiUG9yY2VudGFqZSAoJSkiID0gcG9yY2VudGFqZSwNCiAgICAgICIlIEFjdW11bGFkbyIgPSBwY3RfYWN1bXVsYWRvDQogICAgKQ0KICANCiAgIyBDcmVhciB0YWJsYSBmb3JtYXRlYWRhIGNvbiBrYWJsZUV4dHJhDQogIHRhYmxhX2ZpbmFsIDwtIHRhYmxhX2dvYiAlPiUNCiAgICBrYWJsZSgNCiAgICAgIGNhcHRpb24gPSAiVGFibGEgNS4xOiBEaXN0cmlidWNpw7NuIGRlIEZyZWN1ZW5jaWFzIGRlIENhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbiBwb3IgTsO6bWVybyBkZSBQcm95ZWN0b3MiLA0KICAgICAgYWxpZ24gPSBjKCJjIiwgImwiLCAiYyIsICJjIiwgImMiKSwNCiAgICAgIGZvcm1hdCA9ICJodG1sIg0KICAgICkgJT4lDQogICAga2FibGVfc3R5bGluZygNCiAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLA0KICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgIGZvbnRfc2l6ZSA9IDEyDQogICAgKSAlPiUNCiAgICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiM4QjAwMDAiKSAlPiUNCiAgICBjb2x1bW5fc3BlYygyLCB3aWR0aCA9ICIyMGVtIikgJT4lDQogICAgY29sdW1uX3NwZWMoMzo1LCB3aWR0aCA9ICI4ZW0iKSAlPiUNCiAgICByb3dfc3BlYygxOjQsIGJhY2tncm91bmQgPSAiI2ZmZWJlZSIpICU+JSAgIyBSZXNhbHRhciB0b3AgNA0KICAgIGFkZF9oZWFkZXJfYWJvdmUoYygiICIgPSAyLCAiRnJlY3VlbmNpYXMgQWJzb2x1dGFzIHkgUmVsYXRpdmFzIiA9IDMpKSAlPiUNCiAgICBmb290bm90ZSgNCiAgICAgIGdlbmVyYWwgPSBjKA0KICAgICAgICAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGJhc2FkYSBlbiBkYXRvcyBkZWwgRXN0YWRvIE3DqXJpZGEgMjAxOS0yMDI1IiwNCiAgICAgICAgIk5vdGE6IExhcyBwcmltZXJhcyA0IGNhdGVnb3LDrWFzIGNvbmNlbnRyYW4gZWwgNTEuNSUgZGUgdG9kb3MgbG9zIHByb3llY3RvcyINCiAgICAgICksDQogICAgICBnZW5lcmFsX3RpdGxlID0gIiIsDQogICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUNCiAgICApDQogIA0KICByZXR1cm4obGlzdChkYXRvcyA9IHRhYmxhX2dvYiwgdGFibGEgPSB0YWJsYV9maW5hbCkpDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojICBUQUJMQSBDT01QTEVUQSBERSBGUkVDVUVOQ0lBUyBHT0JFUk5BQ0nDk04gUE9SIENPTVVOQVMNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpjcmVhcl90YWJsYV9nb2JfY29tdW5hcyA8LSBmdW5jdGlvbihkYXRhKSB7DQogIA0KICAjIENhbGN1bGFyIGZyZWN1ZW5jaWFzIHBvciBjb211bmEgKHNpbiByZXBldGlyIGNvbXVuYXMpDQogIHRhYmxhX2dvYl9jb211bmFzIDwtIGRhdGEgJT4lDQogICAgZGlzdGluY3QoSURfQ09NVU5BLCBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OKSAlPiUNCiAgICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLCBuYW1lID0gIm5fY29tdW5hcyIpICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhuX2NvbXVuYXMpKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwb3JjZW50YWplID0gcm91bmQobl9jb211bmFzIC8gc3VtKG5fY29tdW5hcykgKiAxMDAsIDIpLA0KICAgICAgcGN0X2FjdW11bGFkbyA9IHJvdW5kKGN1bXN1bShwb3JjZW50YWplKSwgMiksDQogICAgICByYW5raW5nID0gcm93X251bWJlcigpDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAiUmFua2luZyIgPSByYW5raW5nLA0KICAgICAgIkNhdGVnb3LDrWEgR29iZXJuYWNpw7NuIiA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sDQogICAgICAiTsKwIENvbXVuYXMiID0gbl9jb211bmFzLA0KICAgICAgIlBvcmNlbnRhamUgKCUpIiA9IHBvcmNlbnRhamUsDQogICAgICAiJSBBY3VtdWxhZG8iID0gcGN0X2FjdW11bGFkbw0KICAgICkNCiAgDQogICMgQ3JlYXIgdGFibGEgZm9ybWF0ZWFkYQ0KICB0YWJsYV9maW5hbCA8LSB0YWJsYV9nb2JfY29tdW5hcyAlPiUNCiAgICBrYWJsZSgNCiAgICAgIGNhcHRpb24gPSAiVGFibGEgNS4yOiBEaXN0cmlidWNpw7NuIGRlIEZyZWN1ZW5jaWFzIGRlIENhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbiBwb3IgTsO6bWVybyBkZSBDb211bmFzIEFmZWN0YWRhcyIsDQogICAgICBhbGlnbiA9IGMoImMiLCAibCIsICJjIiwgImMiLCAiYyIpLA0KICAgICAgZm9ybWF0ID0gImh0bWwiDQogICAgKSAlPiUNCiAgICBrYWJsZV9zdHlsaW5nKA0KICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksDQogICAgICBmdWxsX3dpZHRoID0gRkFMU0UsDQogICAgICBwb3NpdGlvbiA9ICJjZW50ZXIiLA0KICAgICAgZm9udF9zaXplID0gMTINCiAgICApICU+JQ0KICAgIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiIzhCMDAwMCIpICU+JQ0KICAgIGNvbHVtbl9zcGVjKDIsIHdpZHRoID0gIjIwZW0iKSAlPiUNCiAgICBjb2x1bW5fc3BlYygzOjUsIHdpZHRoID0gIjhlbSIpICU+JQ0KICAgIHJvd19zcGVjKDE6NCwgYmFja2dyb3VuZCA9ICIjZmZlYmVlIikgJT4lICAjIFJlc2FsdGFyIHRvcCA0DQogICAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDIsICJEaXN0cmlidWNpw7NuIFRlcnJpdG9yaWFsIiA9IDMpKSAlPiUNCiAgICBmb290bm90ZSgNCiAgICAgIGdlbmVyYWwgPSBjKA0KICAgICAgICAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGJhc2FkYSBlbiBkYXRvcyBkZWwgRXN0YWRvIE3DqXJpZGEgMjAxOS0yMDI1IiwNCiAgICAgICAgIk5vdGE6IFVuYSBjb211bmEgcHVlZGUgdGVuZXIgbcO6bHRpcGxlcyBjYXRlZ29yw61hcywgcGVybyBzZSBjdWVudGEgdW5hIHNvbGEgdmV6IHBvciBjYXRlZ29yw61hIg0KICAgICAgKSwNCiAgICAgIGdlbmVyYWxfdGl0bGUgPSAiIiwNCiAgICAgIGZvb3Rub3RlX2FzX2NodW5rID0gVFJVRQ0KICAgICkNCiAgDQogIHJldHVybihsaXN0KGRhdG9zID0gdGFibGFfZ29iX2NvbXVuYXMsIHRhYmxhID0gdGFibGFfZmluYWwpKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBUQUJMQSBDT01QQVJBVElWQSBHT0JFUk5BQ0nDk046IFBST1lFQ1RPUyBWUyBDT01VTkFTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KY3JlYXJfdGFibGFfY29tcGFyYXRpdmFfZ29iIDwtIGZ1bmN0aW9uKGRhdGEpIHsNCiAgDQogICMgRGF0b3MgcG9yIHByb3llY3Rvcw0KICBnb2JfcHJveWVjdG9zIDwtIGRhdGEgJT4lDQogICAgY291bnQoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTiwgbmFtZSA9ICJuX3Byb3llY3RvcyIpICU+JQ0KICAgIG11dGF0ZShwY3RfcHJveWVjdG9zID0gcm91bmQobl9wcm95ZWN0b3MgLyBzdW0obl9wcm95ZWN0b3MpICogMTAwLCAyKSkNCiAgDQogICMgRGF0b3MgcG9yIGNvbXVuYXMNCiAgZ29iX2NvbXVuYXMgPC0gZGF0YSAlPiUNCiAgICBkaXN0aW5jdChJRF9DT01VTkEsIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04pICU+JQ0KICAgIGNvdW50KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sIG5hbWUgPSAibl9jb211bmFzIikgJT4lDQogICAgbXV0YXRlKHBjdF9jb211bmFzID0gcm91bmQobl9jb211bmFzIC8gc3VtKG5fY29tdW5hcykgKiAxMDAsIDIpKQ0KICANCiAgIyBVbmlyIGFtYmFzIHRhYmxhcw0KICB0YWJsYV9jb21wYXJhdGl2YSA8LSBnb2JfcHJveWVjdG9zICU+JQ0KICAgIGlubmVyX2pvaW4oZ29iX2NvbXVuYXMsIGJ5ID0gIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04iKSAlPiUNCiAgICBhcnJhbmdlKGRlc2Mobl9wcm95ZWN0b3MpKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICByYW5raW5nID0gcm93X251bWJlcigpLA0KICAgICAgaW50ZW5zaWRhZCA9IHJvdW5kKG5fcHJveWVjdG9zIC8gbl9jb211bmFzLCAyKSAgIyBQcm95ZWN0b3MgcG9yIGNvbXVuYSBwcm9tZWRpbw0KICAgICkgJT4lDQogICAgc2VsZWN0KA0KICAgICAgcmFua2luZywNCiAgICAgIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sDQogICAgICBuX3Byb3llY3RvcywgcGN0X3Byb3llY3RvcywNCiAgICAgIG5fY29tdW5hcywgcGN0X2NvbXVuYXMsDQogICAgICBpbnRlbnNpZGFkDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAiUmFuayIgPSByYW5raW5nLA0KICAgICAgIkNhdGVnb3LDrWEgR29iZXJuYWNpw7NuIiA9IENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04sDQogICAgICAiTsKwIFByb3kuIiA9IG5fcHJveWVjdG9zLA0KICAgICAgIiUgUHJveS4iID0gcGN0X3Byb3llY3RvcywNCiAgICAgICJOwrAgQ29tLiIgPSBuX2NvbXVuYXMsDQogICAgICAiJSBDb20uIiA9IHBjdF9jb211bmFzLA0KICAgICAgIkludGVuc2lkYWQiID0gaW50ZW5zaWRhZA0KICAgICkNCiAgDQogICMgQ3JlYXIgdGFibGEgZm9ybWF0ZWFkYQ0KICB0YWJsYV9maW5hbCA8LSB0YWJsYV9jb21wYXJhdGl2YSAlPiUNCiAgICBrYWJsZSgNCiAgICAgIGNhcHRpb24gPSAiVGFibGEgNS4zOiBBbsOhbGlzaXMgQ29tcGFyYXRpdm8gR29iZXJuYWNpw7NuIC0gUHJveWVjdG9zIHZzIENvbXVuYXMgQWZlY3RhZGFzIiwNCiAgICAgIGFsaWduID0gYygiYyIsICJsIiwgcmVwKCJjIiwgNSkpLA0KICAgICAgZm9ybWF0ID0gImh0bWwiLA0KICAgICAgZGlnaXRzID0gMg0KICAgICkgJT4lDQogICAga2FibGVfc3R5bGluZygNCiAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLA0KICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgIGZvbnRfc2l6ZSA9IDExDQogICAgKSAlPiUNCiAgICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiM4QjAwMDAiLCB3aWR0aCA9ICIzZW0iKSAlPiUNCiAgICBjb2x1bW5fc3BlYygyLCB3aWR0aCA9ICIxNWVtIikgJT4lDQogICAgY29sdW1uX3NwZWMoMzo3LCB3aWR0aCA9ICI2ZW0iKSAlPiUNCiAgICBhZGRfaGVhZGVyX2Fib3ZlKGMoIiAiID0gMiwgIlBvciBQcm95ZWN0b3MiID0gMiwgIlBvciBDb211bmFzIiA9IDIsICJJbmRpY2Fkb3IiID0gMSkpICU+JQ0KICAgIHJvd19zcGVjKDE6MywgYmFja2dyb3VuZCA9ICIjZmZjZGQyIikgJT4lICAjIFRvcCAzIGVuIHJvam8gc3VhdmUNCiAgICByb3dfc3BlYyg0OjcsIGJhY2tncm91bmQgPSAiI2ZmZWNiMyIpICU+JSAgIyBTaWd1aWVudGVzIDQgZW4gYW1hcmlsbG8gc3VhdmUNCiAgICBmb290bm90ZSgNCiAgICAgIGdlbmVyYWwgPSBjKA0KICAgICAgICAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGJhc2FkYSBlbiBkYXRvcyBkZWwgRXN0YWRvIE3DqXJpZGEgMjAxOS0yMDI1IiwNCiAgICAgICAgIkludGVuc2lkYWQgPSBOwrAgUHJveWVjdG9zIC8gTsKwIENvbXVuYXMgKHByb21lZGlvIGRlIHByb3llY3RvcyBwb3IgY29tdW5hIHBvciBjYXRlZ29yw61hKSINCiAgICAgICksDQogICAgICBnZW5lcmFsX3RpdGxlID0gIiIsDQogICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUNCiAgICApDQogIA0KICByZXR1cm4obGlzdChkYXRvcyA9IHRhYmxhX2NvbXBhcmF0aXZhLCB0YWJsYSA9IHRhYmxhX2ZpbmFsKSkNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIFRBQkxBIFJFU1VNRU4gRUpFQ1VUSVZPIEdPQkVSTkFDScOTTiAoVE9QIDEwKQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCmNyZWFyX3RhYmxhX3Jlc3VtZW5fZ29iIDwtIGZ1bmN0aW9uKGRhdGEpIHsNCiAgDQogICMgQ2FsY3VsYXIgZXN0YWTDrXN0aWNhcyByZXN1bWlkYXMNCiAgdG90YWxfcHJveWVjdG9zIDwtIG5yb3coZGF0YSkNCiAgdG90YWxfY29tdW5hcyA8LSBuX2Rpc3RpbmN0KGRhdGEkSURfQ09NVU5BKQ0KICANCiAgcmVzdW1lbl9nb2IgPC0gZGF0YSAlPiUNCiAgICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLCBuYW1lID0gInByb3llY3RvcyIpICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhwcm95ZWN0b3MpKSAlPiUNCiAgICBzbGljZSgxOjEwKSAlPiUgICMgU29sbyB0b3AgMTANCiAgICBtdXRhdGUoDQogICAgICBwY3RfcHJveWVjdG9zID0gcm91bmQocHJveWVjdG9zIC8gdG90YWxfcHJveWVjdG9zICogMTAwLCAxKSwNCiAgICAgIHBjdF9hY3VtID0gcm91bmQoY3Vtc3VtKHBjdF9wcm95ZWN0b3MpLCAxKQ0KICAgICkgJT4lDQogICAgIyBBZ3JlZ2FyIGRhdG9zIGRlIGNvbXVuYXMNCiAgICBsZWZ0X2pvaW4oDQogICAgICBkYXRhICU+JQ0KICAgICAgICBkaXN0aW5jdChJRF9DT01VTkEsIENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04pICU+JQ0KICAgICAgICBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLCBuYW1lID0gImNvbXVuYXMiKSwNCiAgICAgIGJ5ID0gIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04iDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwY3RfY29tdW5hcyA9IHJvdW5kKGNvbXVuYXMgLyB0b3RhbF9jb211bmFzICogMTAwLCAxKSwNCiAgICAgIHBvc2ljaW9uID0gcm93X251bWJlcigpLA0KICAgICAgY2F0ZWdvcmlhID0gY2FzZV93aGVuKA0KICAgICAgICBwb3NpY2lvbiA8PSAzIH4gIvCflLQgQ3LDrXRpY28iLA0KICAgICAgICBwb3NpY2lvbiA8PSA3IH4gIvCfn6EgQWx0byIsDQogICAgICAgIFRSVUUgfiAi8J+foiBNZWRpbyINCiAgICAgICkNCiAgICApICU+JQ0KICAgIHNlbGVjdCgNCiAgICAgIHBvc2ljaW9uLCBjYXRlZ29yaWEsDQogICAgICBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLA0KICAgICAgcHJveWVjdG9zLCBwY3RfcHJveWVjdG9zLCBwY3RfYWN1bSwNCiAgICAgIGNvbXVuYXMsIHBjdF9jb211bmFzDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAiUG9zLiIgPSBwb3NpY2lvbiwNCiAgICAgICJOaXZlbCIgPSBjYXRlZ29yaWEsDQogICAgICAiQ2F0ZWdvcsOtYSBHb2Jlcm5hY2nDs24iID0gQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTiwNCiAgICAgICJQcm95LiIgPSBwcm95ZWN0b3MsDQogICAgICAiJSIgPSBwY3RfcHJveWVjdG9zLA0KICAgICAgIiUgQWN1bS4iID0gcGN0X2FjdW0sDQogICAgICAiQ29tLiIgPSBjb211bmFzLA0KICAgICAgIiUgQ29tLiIgPSBwY3RfY29tdW5hcw0KICAgICkNCiAgDQogICMgQ3JlYXIgdGFibGEgZm9ybWF0ZWFkYQ0KICB0YWJsYV9maW5hbCA8LSByZXN1bWVuX2dvYiAlPiUNCiAgICBrYWJsZSgNCiAgICAgIGNhcHRpb24gPSAiVGFibGEgNS40OiBSZXN1bWVuIEVqZWN1dGl2byAtIFRvcCAxMCBDYXRlZ29yw61hcyBkZSBHb2Jlcm5hY2nDs24gTcOhcyBDcsOtdGljYXMiLA0KICAgICAgYWxpZ24gPSBjKCJjIiwgImMiLCAibCIsIHJlcCgiYyIsIDUpKSwNCiAgICAgIGZvcm1hdCA9ICJodG1sIg0KICAgICkgJT4lDQogICAga2FibGVfc3R5bGluZygNCiAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpLA0KICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgcG9zaXRpb24gPSAiY2VudGVyIiwNCiAgICAgIGZvbnRfc2l6ZSA9IDExDQogICAgKSAlPiUNCiAgICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgd2lkdGggPSAiM2VtIikgJT4lDQogICAgY29sdW1uX3NwZWMoMiwgd2lkdGggPSAiOGVtIikgJT4lDQogICAgY29sdW1uX3NwZWMoMywgd2lkdGggPSAiMTVlbSIpICU+JQ0KICAgIGNvbHVtbl9zcGVjKDQ6OCwgd2lkdGggPSAiNWVtIikgJT4lDQogICAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDMsICJBbsOhbGlzaXMgcG9yIFByb3llY3RvcyIgPSAzLCAiUG9yIENvbXVuYXMiID0gMikpICU+JQ0KICAgIGZvb3Rub3RlKA0KICAgICAgZ2VuZXJhbCA9IHBhc3RlMCgNCiAgICAgICAgIlRvdGFsIGFuYWxpemFkbzogIiwgdG90YWxfcHJveWVjdG9zLCAiIHByb3llY3RvcyBlbiAiLCB0b3RhbF9jb211bmFzLCAiIGNvbXVuYXMuICIsDQogICAgICAgICJFbCBUb3AgMTAgY29uY2VudHJhIGVsICIsIHJvdW5kKHN1bShyZXN1bWVuX2dvYiRgJWApLCAxKSwgIiUgZGUgdG9kb3MgbG9zIHByb3llY3Rvcy4iDQogICAgICApLA0KICAgICAgZ2VuZXJhbF90aXRsZSA9ICJOb3RhOiIsDQogICAgICBmb290bm90ZV9hc19jaHVuayA9IFRSVUUNCiAgICApDQogIA0KICByZXR1cm4obGlzdChkYXRvcyA9IHJlc3VtZW5fZ29iLCB0YWJsYSA9IHRhYmxhX2ZpbmFsKSkNCn0NCiMjPT09PT09PT09PT09PT09PT09PT09PT0gRnJlY3VlbmNpYSBHbG9iYWwgR29iZXJuYWNpw7NuIC0gUHJveWVjdG9zID09PT09PT09PT09PT09PT09PT09PT09PSMjDQoNCiMgR3LDoWZpY28gaW50ZXJhY3Rpdm8gZGUgUGFyZXRvIEhPUklaT05UQUwgcGFyYSBHb2Jlcm5hY2nDs24gLSBQcm95ZWN0b3MNCmNyZWFyX3BhcmV0b19ob3Jpem9udGFsX2ludGVyYWN0aXZvKA0KICAgIGRmX2R1bW1pZXMsDQogICAgQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTiwNCiAgICAiRGlzdHJpYnVjacOzbiBkZSBUaXBvbG9nw61hcyBkZSBHb2Jlcm5hY2nDs24gLSBQYXJldG8gcG9yIE7Dum1lcm8gZGUgUHJveWVjdG9zIiwNCiAgICAiIzE2YTA4NSIsICIjZDM1NDAwIiAgICMgQ29sb3JlcyBwZXJzb25hbGl6YWRvcyAodmVyZGUvcm9qbyBxdWVtYWRvKQ0KKQ0KDQoNCiMjPT09PT09PT09PT09PT09PT09PT09PT0gRnJlY3VlbmNpYSBHbG9iYWwgR29iZXJuYWNpw7NuIC0gQ29tdW5hcyA9PT09PT09PT09PT09PT09PT09PT09PT0jIw0KDQojIEdyw6FmaWNvIGludGVyYWN0aXZvIGRlIFBhcmV0byBIT1JJWk9OVEFMIHBhcmEgR29iZXJuYWNpw7NuIC0gQ29tdW5hcw0KY3JlYXJfcGFyZXRvX2NvbXVuYXNfaW50ZXJhY3Rpdm8oDQogICAgZGZfZHVtbWllcywNCiAgICBDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OLA0KICAgICJEaXN0cmlidWNpw7NuIGRlIFRpcG9sb2fDrWFzIGRlIEdvYmVybmFjacOzbiAtIFBhcmV0byBwb3IgTsO6bWVybyBkZSBDb211bmFzIEFmZWN0YWRhcyIsDQogICAgIiMzNDQ5NWUiLCAiI2YxYzQwZiIgICAjIENvbG9yZXMgcGVyc29uYWxpemFkb3MgKGdyaXMgb3NjdXJvL2FtYXJpbGxvKQ0KKQ0KDQpgYGANCg0KIyMgKipBbsOhbGlzaXMgZGUgQ2F0ZWdvcsOtYXMgZGUgR29iZXJuYWNpw7NuOiBUYWJsYXMgRGVzY3JpcHRpdmFzKioNCg0KRW4gZXN0YSBzZWNjacOzbiBwcmVzZW50YW1vcyBlbCBhbsOhbGlzaXMgZGV0YWxsYWRvIGRlIGxhcyBjYXRlZ29yw61hcyBkZSBnb2Jlcm5hY2nDs24gbWVkaWFudGUgdGFibGFzIGRlc2NyaXB0aXZhcyBxdWUgcGVybWl0ZW4gdmlzdWFsaXphciBsYSBkaXN0cmlidWNpw7NuLCBmcmVjdWVuY2lhIGUgaW1wYWN0byB0ZXJyaXRvcmlhbCBkZSBsb3MgbnVkb3MgY3LDrXRpY29zIGlkZW50aWZpY2Fkb3MuDQoNCkxhcyB0YWJsYXMgcmV2ZWxhbiB1bmEgZGlzdHJpYnVjacOzbiBkZSBwcm9ibGVtYXMgbcOhcyBkaXZlcnNpZmljYWRhIHF1ZSBlbiBlbCBhbsOhbGlzaXMgQ0ZHLCBwZXJvIGNvbiB1bmEgY2xhcmEgY29uY2VudHJhY2nDs24gZW4gbGFzIHByaW1lcmFzIHBvc2ljaW9uZXMuIEFHVUEgUE9UQUJMRSBlbWVyZ2UgY29tbyBsYSBjYXRlZ29yw61hIG3DoXMgY3LDrXRpY2EsIGNvbiAyOCBwcm95ZWN0b3MgcXVlIHJlcHJlc2VudGFuIGVsIDE0LDE0JSBkZWwgdG90YWwsIGNvbnNvbGlkYW5kbyBsYSBwcm9ibGVtw6F0aWNhIGjDrWRyaWNhIGNvbW8gcHJpb3JpZGFkIGFic29sdXRhIGVuIGxhIGdlc3Rpw7NuIGd1YmVybmFtZW50YWwuDQoNCkxhIGRpc3RyaWJ1Y2nDs24gc2lndWUgdW4gcGF0csOzbiBkZSBQYXJldG8gbW9kaWZpY2FkbywgZG9uZGUgbGFzIHByaW1lcmFzIDQgY2F0ZWdvcsOtYXMgKEFHVUEgUE9UQUJMRSwgVklWSUVOREEsIEVMRUNUUklDSURBRCB5IFZJQUxJREFEKSBjb25jZW50cmFuIGVsIDQ0LDQ1JSBkZSB0b2RvcyBsb3MgcHJveWVjdG9zLCBsYXMgb3RyYXMgcHJpbWVyYXMgOCBjYXRlZ29yw61hcyBhbGNhbnphbiBlbCA3MCw3MiUgZGVsIHRvdGFsLCBjb25maXJtYW5kbyBxdWUgZWwgNzAlIGRlIGxvcyBwcm95ZWN0b3Mgc2UgZW5mb2NhIGVuIHJlc29sdmVyIGVsIDM4JSBkZSBsYXMgY2F0ZWdvcsOtYXMgKDggZGUgMjEpLg0KDQpFc3RhIGRpc3RyaWJ1Y2nDs24gcGVybWl0ZSBlc3RhYmxlY2VyIHRyZXMgbml2ZWxlcyBkZSBjcml0aWNpZGFkIGNsYXJhbWVudGUgZGlmZXJlbmNpYWRvczoNCg0KTml2ZWwgQ3LDrXRpY28gQWx0byAoUG9zaWNpb25lcyAxLTQpOg0KDQrigKIgQUdVQSBQT1RBQkxFICgyOCBwcm95ZWN0b3MsIDE0LjE0JSkgDQoNCuKAoiBWSVZJRU5EQSAoMjMgcHJveWVjdG9zLCAxMS42MiUpDQoNCuKAoiBFTEVDVFJJQ0lEQUQgKDE5IHByb3llY3RvcywgOS42MCUpDQoNCuKAoiBWSUFMSURBRCAoMTggcHJveWVjdG9zLCA5LjA5JSkNCg0KTml2ZWwgQ3LDrXRpY28gTWVkaW8gKFBvc2ljaW9uZXMgNS04KToNCg0K4oCiIEVRVUlQQU1JRU5UTyBTQUxVRCAoMTQgcHJveWVjdG9zLCA3LjA3JSkgDQoNCuKAoiBBR1VBIFJFU0lEVUFMICgxMyBwcm95ZWN0b3MsIDYuNTclKSANCg0K4oCiIERSRU5BSkVTICgxMyBwcm95ZWN0b3MsIDYuNTclKSANCg0K4oCiIEVRVUlQQU1JRU5UTyBFRFVDQVRJVk8gKDEyIHByb3llY3RvcywgNi4wNiUpDQoNCk5pdmVsIENyw610aWNvIEJham8gKFBvc2ljaW9uZXMgOS0yMSk6DQoNCkxhcyB0cmVjZSBjYXRlZ29yw61hcyByZXN0YW50ZXMgcHJlc2VudGFuIGZyZWN1ZW5jaWFzIG1lbm9yZXMgYSAxMCBwcm95ZWN0b3MgY2FkYSB1bmEuDQoNCm5vIGRlIGxvcyBoYWxsYXpnb3MgY2xhdmVzIGVzIGxhIGNvbnNpc3RlbmNpYSBlbiBlbCByYW5raW5nIHkgdmFsaWRhY2nDs24gZGUgbGEgcHJpb3JpemFjacOzbiwgZWwgb3JkZW4gZGUgbGFzIGNhdGVnb3LDrWFzIHByaW5jaXBhbGVzIGVzIG5vdGFibGVtZW50ZSBjb25zaXN0ZW50ZSBjb24gZWwgYW7DoWxpc2lzIHBvciBuw7ptZXJvcyBkZSBwcm95ZWN0b3MsIGFob3JhIGxvcyByZXN1bHRhZG9zIHBvciBuw7ptZXJvIGRlIGNvbXVuYXMgZXMgY29uc2lzdGVudGUsIHlhIHF1ZSBlbCBBZ3VhIFBvdGFibGUgKCoqMTMsNjElKiopLCBWaXZpZW5kYSAoKioxMSw1MiUqKiksIEVsZWN0cmljaWRhZCAoOSw0MiUqKikgeSBWaWFsaWRhZCAoKio4LDkwJVwqXCopIHZ1ZWx2ZW4gYSBvY3VwYXIgbG9zIGN1YXRybyBwcmltZXJvcyBsdWdhcmVzLiBFc3RhIGNvbnNpc3RlbmNpYSBlcyB1biBoYWxsYXpnbyB5YSBxdWUgZGVtdWVzdHJhIHF1ZSBsb3MgcHJvYmxlbWFzIGVuIGxvcyBxdWUgbGEgR29iZXJuYWNpw7NuIG3DoXMgc2UgZW5mb2NhIChtYXlvciBuw7ptZXJvIGRlIHByb3llY3Rvcykgc29uIHByZWNpc2FtZW50ZSBsb3MgcXVlIGVzdMOhbiBtw6FzIGdlbmVyYWxpemFkb3MgZW4gZWwgdGVycml0b3JpbyAoYWZlY3RhbiBhIG3DoXMgY29tdW5hcykuIFZhbGlkYSBxdWUgbGEgcHJpb3JpemFjacOzbiBpbnN0aXR1Y2lvbmFsIGVzIGFjZXJ0YWRhIHkgZXN0w6EgYWxpbmVhZGEgY29uIGxhIHJlYWxpZGFkIGdlb2dyw6FmaWNhIGRlIGxhcyBjYXJlbmNpYXMuDQoNCiMjICoqQW7DoWxpc2lzIGRlIENhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbjogVGFibGFzIERlc2NyaXB0aXZhcyoqDQoNCkRlc2RlIGxhIHBlcnNwZWN0aXZhIGRlIGxhIEdvYmVybmFjacOzbiwgZWwgcHJpbmNpcGlvIGRlIFBhcmV0byBzZSBtYW50aWVuZSwgcGVybyBjb24gdW5hIGRpc3RyaWJ1Y2nDs24gbGlnZXJhbWVudGUgbcOhcyBkaXZlcnNpZmljYWRhLiBMYXMgcHJpbWVyYXMgNCBjYXRlZ29yw61hcyAoQWd1YSBQb3RhYmxlLCBWaXZpZW5kYSwgRWxlY3RyaWNpZGFkLCBWaWFsaWRhZCksIHF1ZSBjb25zdGl0dXllbiBlbCAxOSUgZGVsIHRvdGFsICg0IGRlIDIxKSwgYWNhcGFyYW4gZWwgNDQsNDUlIGRlIGxvcyBwcm95ZWN0b3MgaW5zdGl0dWNpb25hbGVzLiBMYSByZWdsYSBkZWwgODAvMjAgc2UgY3VtcGxlIGFsIGNvbnNpZGVyYXIgcXVlIGxhcyBwcmltZXJhcyA4IGNhdGVnb3LDrWFzICgzOCUgZGVsIHRvdGFsKSBleHBsaWNhbiBlbCA3MCw3MiUgZGUgbGEgY2FydGVyYSBkZSBwcm95ZWN0b3MgZ3ViZXJuYW1lbnRhbGVzLg0KDQojIyMgKipUYWJsYSBkZSBEaXN0cmlidWNpw7NuIGRlIEZyZWN1ZW5jaWFzIGRlIENhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbiBwb3IgTsO6bWVybyBkZSBQcm95ZWN0b3MqKg0KDQpgYGB7ciB0YWJsYV81LjEsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEdlbmVyYXIgdGFibGEgZGUgcHJveWVjdG9zIHBhcmEgR29iZXJuYWNpw7NuDQp0YWJsYV9nb2JfcHJveWVjdG9zIDwtIGNyZWFyX3RhYmxhX2dvYl9wcm95ZWN0b3MoZGZfZHVtbWllcykNCnRhYmxhX2dvYl9wcm95ZWN0b3MkdGFibGENCmBgYA0KDQoqTm90YTogTGEgdGFibGEgbXVlc3RyYSBsYSBkaXN0cmlidWNpw7NuIGFic29sdXRhIHkgcmVsYXRpdmEgZGUgbGFzIGNhdGVnb3LDrWFzIGRlIGdvYmVybmFjacOzbiBzZWfDum4gZWwgbsO6bWVybyBkZSBwcm95ZWN0b3MgYXNvY2lhZG9zLioNCg0KIyMjICoqVGFibGEgZGUgRGlzdHJpYnVjacOzbiBkZSBGcmVjdWVuY2lhcyBkZSBDYXRlZ29yw61hcyBkZSBHb2Jlcm5hY2nDs24gcG9yIE7Dum1lcm8gZGUgQ29tdW5hcyBBZmVjdGFkYXMqKg0KDQpgYGB7ciB0YWJsYV81LjIsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEdlbmVyYXIgdGFibGEgZGUgY29tdW5hcyBwYXJhIEdvYmVybmFjacOzbg0KdGFibGFfZ29iX2NvbXVuYXMgPC0gY3JlYXJfdGFibGFfZ29iX2NvbXVuYXMoZGZfZHVtbWllcykNCnRhYmxhX2dvYl9jb211bmFzJHRhYmxhDQpgYGANCg0KKk5vdGE6IEVzdGEgdGFibGEgcmVwcmVzZW50YSBsYSBkaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsIGRlIGxhcyBjYXRlZ29yw61hcyBkZSBnb2Jlcm5hY2nDs24sIGNvbnRhYmlsaXphbmRvIGN1w6FudGFzIGNvbXVuYXMgZXN0w6FuIGFmZWN0YWRhcyBwb3IgY2FkYSB0aXBvIGRlIG51ZG8gY3LDrXRpY28uKg0KDQojIyMgKipUYWJsYSBkZSBBbsOhbGlzaXMgQ29tcGFyYXRpdm8gR29iZXJuYWNpw7NuIC0gUHJveWVjdG9zIHZzIENvbXVuYXMgQWZlY3RhZGFzKioNCg0KYGBge3IgdGFibGFfNS4zLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBHZW5lcmFyIHRhYmxhIGNvbXBhcmF0aXZhIHBhcmEgR29iZXJuYWNpw7NuDQp0YWJsYV9nb2JfY29tcGFyYXRpdmEgPC0gY3JlYXJfdGFibGFfY29tcGFyYXRpdmFfZ29iKGRmX2R1bW1pZXMpDQp0YWJsYV9nb2JfY29tcGFyYXRpdmEkdGFibGENCmBgYA0KDQoqTm90YTogRWwgaW5kaWNhZG9yIGRlIGludGVuc2lkYWQgKHByb3llY3Rvcy9jb211bmEpIHBlcm1pdGUgaWRlbnRpZmljYXIgY2F0ZWdvcsOtYXMgY29uIG1heW9yIGNvbmNlbnRyYWNpw7NuIGRlIHByb2JsZW1hcyBwb3IgdGVycml0b3Jpby4qDQoNCiMjIyAqKlRhYmxhIGRlIFJlc3VtZW4gRWplY3V0aXZvIC0gVG9wIDEwIENhdGVnb3LDrWFzIGRlIEdvYmVybmFjacOzbiBNw6FzIENyw610aWNhcyoqDQoNCmBgYHtyIHRhYmxhXzUuNCwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgR2VuZXJhciB0YWJsYSByZXN1bWVuIGVqZWN1dGl2byBwYXJhIEdvYmVybmFjacOzbg0KdGFibGFfZ29iX3Jlc3VtZW4gPC0gY3JlYXJfdGFibGFfcmVzdW1lbl9nb2IoZGZfZHVtbWllcykNCnRhYmxhX2dvYl9yZXN1bWVuJHRhYmxhDQpgYGANCg0KKk5vdGE6IENsYXNpZmljYWNpw7NuIHBvciBuaXZlbCBkZSBjcml0aWNpZGFkIGJhc2FkbyBlbiBsYSBmcmVjdWVuY2lhIGRlIGFwYXJpY2nDs24geSBkaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsLioNCg0KIyMgKirDjW5kaWNlIFNoYW5ub24geSBQaWVsb3UgcG9yIENvbXVuYXMgeSBUaXBvbG9nw61hIENGRyB5IGRlIEdvYmVybmFjacOzbioqDQoNCkVsIMOtbmRpY2UgZGUgU2hhbm5vbiBzZSB1dGlsaXphIGNvbW8gdW5hIGhlcnJhbWllbnRhIGN1YW50aXRhdGl2YSBwYXJhIG1lZGlyIGxhIGRpdmVyc2lkYWQgZGUgdGlwb2xvZ8OtYXMgZGUgY29uZmxpY3RvIHkgbGEgZGl2ZXJzaWRhZCBpbnN0aXR1Y2lvbmFsIChnb2Jlcm5hY2nDs24pLCBjdWFudGlmaWNhIGxhIGRpdmVyc2lkYWQgZGUgY2F0ZWdvcsOtYXMgZW4gdW5hIGNvbXVuaWRhZCBjb25zaWRlcmFuZG8gdGFudG8gbGEgcmlxdWV6YSAobsO6bWVybyBkZSBjYXRlZ29yw61hcykgY29tbyBsYSB1bmlmb3JtaWRhZCBlbiBzdSBkaXN0cmlidWNpw7NuIGludm9sdWNyYWRhcyBlbiBsb3MgcHJveWVjdG9zIGFuYWxpemFkb3MuDQoNCiQkDQpIXlxwcmltZSA9IC0gXHN1bV97aT0xfV57U30gcF9pIFxsbihwX2kpDQokJA0KDQpMZXllbmRhOg0KDQpFeHBsaWNhY2nDs24gcsOhcGlkYSBkZSBsb3Mgc8OtbWJvbG9zOg0KDQrwnZC74oaSIMONbmRpY2UgZGUgU2hhbm5vbi4NCg0K8J2RhiDihpIgTsO6bWVybyB0b3RhbCBkZSBjYXRlZ29yw61hcyAobyB0aXBvbG9nw61hcyBkZSBudWRvcyBjcsOtdGljb3MpLg0KDQrwnZGd8J2RliDihpIgUHJvcG9yY2nDs24gZGUgbGEgY2F0ZWdvcsOtYQ0KDQppIHJlc3BlY3RvIGFsIHRvdGFsLg0KDQpTZSB1dGlsaXphIGxvcyDDrW5kaWNlcyBkZSBTaGFubm9uIHkgUGllbG91IGNvbW8gaGVycmFtaWVudGFzIHBhcmE6DQoNCjEuICBNZWRpciBsYSBkaXZlcnNpZGFkIGRlIHByb2JsZW3DoXRpY2FzIChDRkcpIHkgYWN0b3JlcyAoR29iZXJuYWNpw7NuKSBlbiBjb211bmFzIG1lcmlkZcOxYXMuDQoNCjIuICBJbnRlcnByZXRhciBzdSBzaWduaWZpY2FkbyBtZWRpYW50ZSBlbCBtYXJjbyBkZSBoaXDDs3Rlc2lzIChUYWJsYSBkZSBIaXDDs3Rlc2lzIDEpLCBxdWUgY29udHJhc3RhIGVzY2VuYXJpb3MgZGUgY2FwYWNpZGFkIHZzLiBkaXNmdW5jacOzbi4NCg0KMy4gIERpc2XDsWFyIHBvbMOtdGljYXMgZGlmZXJlbmNpYWRhcyBzZWfDum4gZWwgcGVyZmlsIGRlIGNhZGEgY29tdW5hIChjb29yZGluYWNpw7NuIGludGVyaW5zdGl0dWNpb25hbCBwYXJhIEgnIGFsdG8sIGFzZXNvcsOtYSB0w6ljbmljYSBwYXJhIEgnIGJham8gY29uIGJhamEgSicpLg0KDQpQYXJhIGFib3JkYXIgZGUgbWFuZXJhIGVmZWN0aWNhIGVsIGluZGljZSBTaGFubm9uLVBpZW9sb3UsIG5vcyB2YW1vcyBhIHBsYW50ZWFyIHVuYXMgaGlwb3Rlc2lzOg0KDQoqKlZhbG9yIGRlIFNoYW5ub24gQUxUTyAoSCcgXD4gMS41KSoqDQoNCi0gICBMYXMgY29tdW5pZGFkZXMgdGllbmVuIGNhcGFjaWRhZCBkZSBkaWFnbsOzc3RpY28geSBvcmdhbml6YWNpw7NuLCBlc3RvIGVzIHVuYSBjb211bmEgY29uIHZpc2nDs24gaW50ZWdyYWwsIGNhcGF6IGRlIG1hcGVhciBjb21wbGV0YW1lbnRlIHN1cyBwcm9ibGVtw6F0aWNhcy4gLQ0KDQotICAgRXhpc3RlIHPDrW50b21hcyBkZSBBYmFuZG9ubyBJbnN0aXR1Y2lvbmFsLCByZWZsZWphIGNhcmVuY2lhcyBnZW5lcmFsaXphZGFzLiBMYSBjb211bmEgZG9jdW1lbnRhIHRvZG8gcG9yIGRlc2VzcGVyYWNpw7NuLiBQcm95ZWN0b3MgcmVwZXRpdGl2b3MgcXVlIG5vIHNlIHJlc3VlbHZlbi4gQmFqYSB0YXNhIGRlIGN1bG1pbmFjacOzbi5Qb2Ryw61hIHN1YmVzdGltYXJzZSB1bmEgZ2VudWluYSBjYXBhY2lkYWQgb3JnYW5pemF0aXZhLg0KDQoqKlZhbG9yIGRlIFNoYW5ub24gQkFKTyAoSCcgXDwgMS4wKSoqDQoNCi0gICBUaWVuZW4gdW5hIEZvY2FsaXphY2nDs24gRXN0cmF0w6lnaWNhLCBMYXMgY29tdW5hcyBwcmlvcml6YSBkZSBtYW5lcmEgcHJhZ23DoXRpY2EgbG9zIHByb2JsZW1hcyBtw6FzIGNyw610aWNvcyB5IHZpYWJsZXMuIFByb2JsZW1hcyBjbGFyYW1lbnRlIGlkZW50aWZpY2Fkb3MgY29tbyBwcmltb3JkaWFsZXMuIE1heW9yZXMgdGFzYXMgZGUgw6l4aXRvLiBQdWVkZSBpZ25vcmFyIHByb2JsZW3DoXRpY2FzICJtZW5vcmVzIi4NCg0KLSAgIERlc2NvbmV4acOzbiBlIEludmlhYmlsaWRhZCwgbGFzIGNvbXVuYXMgcGVyc2lndWUgc29sdWNpb25lcyBtb251bWVudGFsZXMgZSBpbnZpYWJsZXMuIFByb3llY3RvcyBkZSBlc2NhbGEgbmFjaW9uYWwvZXN0YWRhbC4gUGVyc2lzdGVuY2lhIGRlbCBtaXNtbyBwcm9ibGVtYSBzaW4gZXZvbHVjacOzbi4gQmFqYSBlZmVjdGl2aWRhZC4NCg0KYGBge3IsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD0xMiwgb3V0LndpZHRoPSIxMDAlIn0NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KDQpjb25mbGljdF9wcmVmZXIoInNlbGVjdCIsICJkcGx5ciIpDQpjb25mbGljdF9wcmVmZXIoImZpbHRlciIsICJkcGx5ciIpDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tQ3JlYXIgbWFwZW8gw7puaWNvIGRlIElEX0NPTVVOQSBhIENPTVVOQS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpjb21tdW5lX21hcCA8LSBkZl9yYXcgJT4lDQogIGRpc3RpbmN0KElEX0NPTVVOQSwgQ09NVU5BKSAlPiUNCiAgbXV0YXRlKENPTVVOQSA9IHN0cl90cmltKENPTVVOQSkpICAjIExpbXBpYXIgZXNwYWNpb3MgZXh0cmFzDQoNCiMjIERldGVjdGFyIGRpbsOhbWljYW1lbnRlIGxhcyBjb2x1bW5hcyBkdW1teQ0KY2ZnX2NvbHMgPC0gZ3JlcCgiXkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGR18iLCANCiAgICAgICAgICAgICAgICAgbmFtZXMoZGZfZHVtbWllcyksIHZhbHVlID0gVFJVRSkNCmdvYl9jb2xzIDwtIGdyZXAoIl5DTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OXyIsIA0KICAgICAgICAgICAgICAgICBuYW1lcyhkZl9kdW1taWVzKSwgdmFsdWUgPSBUUlVFKQ0KDQojIyBDYWxjdWxhciBkaXZlcnNpZGFkIHBhcmEgbGFzIFRpcG9sb2fDrWEgQ0ZHIGNvbiBub21icmVzIGRlIGNvbXVuYXMNCmRpdl9jZmcgPC0gZGZfZHVtbWllcyAlPiUNCiAgZ3JvdXBfYnkoSURfQ09NVU5BKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG5fcHJveWVjdG9zID0gbigpLA0KICAgIGFjcm9zcyhhbGxfb2YoY2ZnX2NvbHMpLCBzdW0sIG5hLnJtID0gVFJVRSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICAjIEFncmVnYXIgbm9tYnJlcyBkZSBjb211bmFzDQogIGxlZnRfam9pbihjb21tdW5lX21hcCwgYnkgPSAiSURfQ09NVU5BIikgJT4lDQogICMgQ2FsY3VsYXIgw61uZGljZXMgZGUgZGl2ZXJzaWRhZA0KICB7DQogICAgY250cyA8LSBzZWxlY3QoLiwgYWxsX29mKGNmZ19jb2xzKSkNCiAgICB0aWIgPC0gc2VsZWN0KC4sIElEX0NPTVVOQSwgQ09NVU5BLCBuX3Byb3llY3RvcykNCiAgICBIIDwtIHZlZ2FuOjpkaXZlcnNpdHkoY250cywgaW5kZXggPSAic2hhbm5vbiIpDQogICAgcmljaGVzc2UgPC0gcm93U3VtcyhjbnRzID4gMCkNCiAgICBKIDwtIGlmZWxzZShyaWNoZXNzZSA+IDAsIEggLyBsb2cocmljaGVzc2UpLCBOQV9yZWFsXykNCiAgICBiaW5kX2NvbHModGliLCBIX3NoYW5ub24gPSBILCBwaWVsb3UgPSBKKQ0KICB9DQoNCiMgQ3JlYXIgY29sdW1uYSBjb21iaW5hZGEgcGFyYSBtb3N0cmFyIGVuIHRhYmxhcw0KZGl2X2NmZyA8LSBkaXZfY2ZnICU+JQ0KICBtdXRhdGUoQ09NVU5BX0lEX05PTUJSRSA9IHBhc3RlKElEX0NPTVVOQSwgIi0iLCBDT01VTkEpKQ0KDQojIFRhYmxhOiBUb3AgMTAgY29tdW5hcyBtw6FzIGRpdmVyc2FzIChjb24gSUQgeSBub21icmUpDQp0b3AxMF9jZmcgPC0gZGl2X2NmZyAlPiUNCiAgYXJyYW5nZShkZXNjKEhfc2hhbm5vbikpICU+JQ0KICBzbGljZSgxOjEwKSAlPiUNCiAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIEhfc2hhbm5vbiwgcGllbG91LCBuX3Byb3llY3RvcykNCg0KIyBUYWJsYTogVG9wIDEwIGNvbXVuYXMgbWVub3MgZGl2ZXJzYXMgKGNvbiBJRCB5IG5vbWJyZSkNCmJvdHRvbTEwX2NmZyA8LSBkaXZfY2ZnICU+JQ0KICBhcnJhbmdlKEhfc2hhbm5vbikgJT4lDQogIHNsaWNlKDE6MTApICU+JQ0KICBzZWxlY3QoQ09NVU5BX0lEX05PTUJSRSwgSF9zaGFubm9uLCBwaWVsb3UsIG5fcHJveWVjdG9zKQ0KDQojIE1vc3RyYXIgdGFibGFzIGVuIGZvcm1hdG8ga2FibGUgcGFyYSBUaXBvbG9nw61hIENGRw0KY2F0KCJcblxuKioxMCBjb211bmFzIGNvbiBtYXlvciBkaXZlcnNpZGFkIChTaGFubm9uX0NGRykqKlxuIikNCmtuaXRyOjprYWJsZSh0b3AxMF9jZmcsIA0KICAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIkNvbXVuYSAoSUQgLSBOb21icmUpIiwgIkhfQ0ZHIChTaGFubm9uKSIsICJKX0NGRyAoUGllbG91KSIsICJOwrAgUHJveWVjdG9zIiksDQogICAgICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICAgICBjYXB0aW9uID0gIlRvcCAxMCBjb211bmFzIGNvbiBtYXlvciDDrW5kaWNlIGRlIFNoYW5ub24gcGFyYSBDRkciKQ0KDQpjYXQoIlxuXG4qKjEwIGNvbXVuYXMgY29uIG1lbm9yIGRpdmVyc2lkYWQgKFNoYW5ub25fQ0ZHKSoqXG4iKQ0Ka25pdHI6OmthYmxlKGJvdHRvbTEwX2NmZywNCiAgICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJDb211bmEgKElEIC0gTm9tYnJlKSIsICJIX0NGRyAoU2hhbm5vbikiLCAiSl9DRkcgKFBpZWxvdSkiLCAiTsKwIFByb3llY3RvcyIpLA0KICAgICAgICAgICAgIGRpZ2l0cyA9IDMsDQogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgMTAgY29tdW5hcyBjb24gbWVub3Igw61uZGljZSBkZSBTaGFubm9uIHBhcmEgQ0ZHIikNCg0KIyMgUHJlcGFyYXIgZGF0b3MgcGFyYSBncsOhZmljbyBjb25zb2xpZGFkbyBwYXJhIENGRw0KdGFibGFfZXh0cmVtb3NfY2ZnIDwtIGJpbmRfcm93cygNCiAgdG9wMTBfY2ZnICAlPiUgbXV0YXRlKHRpcG8gPSAiVG9wIDEwIOKGkSIpICU+JSByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSksDQogIGJvdHRvbTEwX2NmZyAlPiUgbXV0YXRlKHRpcG8gPSAiVG9wIDEwIOKGkyIpICU+JSByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSkNCikgJT4lDQogICMgQ3JlYXIgZXRpcXVldGEgb3JkZW5hZGEgcG9yIEhfc2hhbm5vbg0KICBtdXRhdGUoQ09NVU5BX09SRCA9IHJlb3JkZXIoQ09NVU5BLCBIX3NoYW5ub24pKQ0KDQojLS0tLS0tLS0tLS0tLS0tR3LDoWZpY286IFNoYW5ub24gKGJhcnJhcykgKyBQaWVsb3UgKGzDrW5lYSkgcGFyYSBDRkctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jDQptYXhIIDwtIG1heCh0YWJsYV9leHRyZW1vc19jZmckSF9zaGFubm9uKQ0KDQojIEFqdXN0YXIgZWwgZ3LDoWZpY28gY29uIGRpbWVuc2lvbmVzIGVzcGVjw61maWNhcw0KY2ZnX3Bsb3QgPC0gZ2dwbG90KHRhYmxhX2V4dHJlbW9zX2NmZywgYWVzKHggPSBDT01VTkFfT1JELCB5ID0gSF9zaGFubm9uLCBmaWxsID0gdGlwbykpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gcGllbG91ICogbWF4SCwgZ3JvdXAgPSAxKSwgDQogICAgICAgICAgICBjb2xvciA9ICIjRTY5RjAwIiwgc2l6ZSA9IDEuMCwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBnZW9tX3BvaW50KGFlcyh5ID0gcGllbG91ICogbWF4SCksIA0KICAgICAgICAgICAgIGNvbG9yID0gIiNENTVFMDAiLCBzaXplID0gMi41LCBzaGFwZSA9IDE4KSArDQogICMgRXRpcXVldGFzIGRlIFBpZWxvdSBkZXNwbGF6YWRhcyBhIGxhIGRlcmVjaGENCiAgZ2VvbV90ZXh0KGFlcyh5ID0gcGllbG91ICogbWF4SCwgbGFiZWwgPSBzcHJpbnRmKCJKPSUuMmYiLCBwaWVsb3UpKSwNCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMywgc2l6ZSA9IDIuNSwgY29sb3IgPSAiI0Q1NUUwMCIpICsgICMgQWp1c3RhZG8gaGp1c3QNCg0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNywgYWxwaGEgPSAwLjkpICsNCiAgZ2VvbV90ZXh0KGFlcyh5ID0gSF9zaGFubm9uLCBsYWJlbCA9IHNwcmludGYoIiUuMmYgKCUuMWYpIiwgSF9zaGFubm9uLCBleHAoSF9zaGFubm9uKSkpLA0KICAgICAgICAgICAgaGp1c3QgPSAxLjEsIHNpemUgPSAyLjgsIGNvbG9yID0gIndoaXRlIiwgZm9udGZhY2UgPSAiYm9sZCIpICsgICMgVGFtYcOxbyBhanVzdGFkbw0KICBmYWNldF93cmFwKH4gdGlwbywgc2NhbGVzID0gImZyZWVfeSIsIG5jb2wgPSAxKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBuYW1lID0gIsONbmRpY2UgZGUgU2hhbm5vbiAoSCkiLA0KICAgIGxpbWl0cyA9IGMoMCwgbWF4SCAqIDEuMTUpLCANCiAgICBzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIG1heEgsIG5hbWUgPSAiw41uZGljZSBkZSBQaWVsb3UgKEopIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpDQogICkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUb3AgMTAg4oaRIiA9ICIjNTZCNEU5IiwgIlRvcCAxMCDihpMiID0gIiNDQzc5QTciKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpdmVyc2lkYWQgZGUgVGlwb2xvZ8OtYXMgQ0ZHIHBvciBDb211bmEiLA0KICAgIHN1YnRpdGxlID0gIlRvcCAxMCBjb211bmFzIGNvbiBtYXlvciB5IG1lbm9yIGRpdmVyc2lkYWQgfCBCYXJyYXM6IFNoYW5ub24gKEgpIHwgTMOtbmVhOiBQaWVsb3UgKEopIiwNCiAgICB4ID0gIkNvbXVuYSAoSUQgLSBOb21icmUpIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSBkYXRvcyBkZSBwcm95ZWN0b3MgQUNBIC0gV2lsbGlhbSBHdXRpZXJyZXoiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0LCBoanVzdCA9IDAuNSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImdyYXk0MCIsIGhqdXN0ID0gMC41KSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHIgPSAxMCkpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDEwKSksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAgIyBSZWR1Y2lyIHRhbWHDsW8gdGV4dG8gZWplIFkNCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTEpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigxLCAyLCAxLCAxLCAiY20iKSAgIyBBdW1lbnRhciBtYXJnZW4gZGVyZWNobw0KICApDQoNCiMgR3VhcmRhciBjb24gZGltZW5zaW9uZXMgZXNwZWPDrWZpY2FzDQpnZ3NhdmUoImNmZ19kaXZlcnNpdHlfcGxvdC5wbmciLCBjZmdfcGxvdCwgd2lkdGggPSAxNCwgaGVpZ2h0ID0gMTAsIGRwaSA9IDMwMCkNCnByaW50KGNmZ19wbG90KQ0KDQojIyBDYWxjdWxhciBkaXZlcnNpZGFkIHBhcmEgVGlwb2xvZ8OtYSBkZSBHb2Jlcm5hY2nDs24gY29uIG5vbWJyZXMNCmRpdl9nb2IgPC0gZGZfZHVtbWllcyAlPiUNCiAgZ3JvdXBfYnkoSURfQ09NVU5BKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG5fcHJveWVjdG9zID0gbigpLA0KICAgIGFjcm9zcyhhbGxfb2YoZ29iX2NvbHMpLCBzdW0sIG5hLnJtID0gVFJVRSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICAjIEFncmVnYXIgbm9tYnJlcyBkZSBjb211bmFzDQogIGxlZnRfam9pbihjb21tdW5lX21hcCwgYnkgPSAiSURfQ09NVU5BIikgJT4lDQogICMgQ2FsY3VsYXIgw61uZGljZXMgZGUgZGl2ZXJzaWRhZA0KICB7DQogICAgY250cyA8LSBzZWxlY3QoLiwgYWxsX29mKGdvYl9jb2xzKSkNCiAgICB0aWIgPC0gc2VsZWN0KC4sIElEX0NPTVVOQSwgQ09NVU5BLCBuX3Byb3llY3RvcykNCiAgICBIIDwtIHZlZ2FuOjpkaXZlcnNpdHkoY250cywgaW5kZXggPSAic2hhbm5vbiIpDQogICAgcmljaGVzc2UgPC0gcm93U3VtcyhjbnRzID4gMCkNCiAgICBKIDwtIGlmZWxzZShyaWNoZXNzZSA+IDAsIEggLyBsb2cocmljaGVzc2UpLCBOQV9yZWFsXykNCiAgICBiaW5kX2NvbHModGliLCBIX3NoYW5ub24gPSBILCBwaWVsb3UgPSBKKQ0KICB9DQoNCiMgQ3JlYXIgY29sdW1uYSBjb21iaW5hZGEgcGFyYSBtb3N0cmFyIGVuIHRhYmxhcw0KZGl2X2dvYiA8LSBkaXZfZ29iICU+JQ0KICBtdXRhdGUoQ09NVU5BX0lEX05PTUJSRSA9IHBhc3RlKElEX0NPTVVOQSwgIi0iLCBDT01VTkEpKQ0KDQojIyBNb3N0cmFyIHRhYmxhcyBjb24gbm9tYnJlcw0KdG9wMTBfZ29iIDwtIGRpdl9nb2IgJT4lIA0KICBhcnJhbmdlKGRlc2MoSF9zaGFubm9uKSkgJT4lIA0KICBzbGljZSgxOjEwKSAlPiUNCiAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIG5fcHJveWVjdG9zLCBIX3NoYW5ub24sIHBpZWxvdSkNCg0KYm90dG9tMTBfZ29iIDwtIGRpdl9nb2IgJT4lIA0KICBhcnJhbmdlKEhfc2hhbm5vbikgJT4lIA0KICBzbGljZSgxOjEwKSAlPiUNCiAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIG5fcHJveWVjdG9zLCBIX3NoYW5ub24sIHBpZWxvdSkNCg0KY2F0KCJcblxuKipUb3AgMTAgY29tdW5hcyBjb24gbWF5b3IgZGl2ZXJzaWRhZCAoU2hhbm5vbikgZGUgR29iZXJuYWNpw7NuKipcbiIpDQprbml0cjo6a2FibGUodG9wMTBfZ29iLA0KICAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIkNvbXVuYSAoSUQgLSBOb21icmUpIiwgIk7CsCBQcm95ZWN0b3MiLCAiSF9HT0IgKFNoYW5ub24pIiwgIkpfR09CIChQaWVsb3UpIiksDQogICAgICAgICAgICAgZGlnaXRzID0gMywgDQogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgMTAgY29tdW5hcyBjb24gbWF5b3Igw61uZGljZSBkZSBTaGFubm9uIHBhcmEgR29iZXJuYWNpw7NuIikNCg0KY2F0KCJcblxuKipUb3AgMTAgY29tdW5hcyBjb24gbWVub3IgZGl2ZXJzaWRhZCAoU2hhbm5vbikgZGUgR29iZXJuYWNpw7NuKipcbiIpDQprbml0cjo6a2FibGUoYm90dG9tMTBfZ29iLA0KICAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIkNvbXVuYSAoSUQgLSBOb21icmUpIiwgIk7CsCBQcm95ZWN0b3MiLCAiSF9HT0IgKFNoYW5ub24pIiwgIkpfR09CIChQaWVsb3UpIiksDQogICAgICAgICAgICAgZGlnaXRzID0gMywgDQogICAgICAgICAgICAgY2FwdGlvbiA9ICJUb3AgMTAgY29tdW5hcyBjb24gbWVub3Igw61uZGljZSBkZSBTaGFubm9uIHBhcmEgR29iZXJuYWNpw7NuIikNCg0KIyMgUHJlcGFyYXIgZGF0b3MgcGFyYSBncsOhZmljbyBkZSBHb2Jlcm5hY2nDs24NCnRhYmxhX2V4dHJlbW9zX2dvYiA8LSBiaW5kX3Jvd3MoDQogIHRvcDEwX2dvYiAlPiUgbXV0YXRlKHRpcG8gPSAiVG9wIDEwIOKGkSIpICU+JSByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSksDQogIGJvdHRvbTEwX2dvYiAlPiUgbXV0YXRlKHRpcG8gPSAiVG9wIDEwIOKGkyIpICU+JSByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSkNCikgJT4lDQogICMgQ3JlYXIgZXRpcXVldGEgb3JkZW5hZGEgcG9yIEhfc2hhbm5vbg0KICBtdXRhdGUoQ09NVU5BX09SRCA9IHJlb3JkZXIoQ09NVU5BLCBIX3NoYW5ub24pKQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tR3LDoWZpY2EgZGUgdGlwb2xvZ8OtYSBkZSBnb2Jlcm5hY2nDs24tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMNCm1heEhfZ29iIDwtIG1heCh0YWJsYV9leHRyZW1vc19nb2IkSF9zaGFubm9uKQ0KDQpnb2JfcGxvdCA8LSBnZ3Bsb3QodGFibGFfZXh0cmVtb3NfZ29iLCBhZXMoeCA9IENPTVVOQV9PUkQsIHkgPSBIX3NoYW5ub24sIGZpbGwgPSB0aXBvKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBwaWVsb3UgKiBtYXhIX2dvYiwgZ3JvdXAgPSAxKSwgDQogICAgICAgICAgICBjb2xvciA9ICIjRTY5RjAwIiwgc2l6ZSA9IDEuMCwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBnZW9tX3BvaW50KGFlcyh5ID0gcGllbG91ICogbWF4SF9nb2IpLCANCiAgICAgICAgICAgICBjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDIuNSwgc2hhcGUgPSAxOCkgKw0KICAjIEV0aXF1ZXRhcyBkZSBQaWVsb3UgZGVzcGxhemFkYXMgYSBsYSBkZXJlY2hhDQogIGdlb21fdGV4dChhZXMoeSA9IHBpZWxvdSAqIG1heEhfZ29iLCBsYWJlbCA9IHNwcmludGYoIko9JS4yZiIsIHBpZWxvdSkpLA0KICAgICAgICAgICAgaGp1c3QgPSAtMC4yLCBzaXplID0gMi41LCBjb2xvciA9ICIjRDU1RTAwIikgKw0KICAjIEx1ZWdvIGRpYnVqYXIgbGFzIGJhcnJhcyBkZSBTaGFubm9uDQogIGdlb21fY29sKHdpZHRoID0gMC43LCBhbHBoYSA9IDAuOSkgKw0KICBnZW9tX3RleHQoYWVzKHkgPSBIX3NoYW5ub24sIGxhYmVsID0gc3ByaW50ZigiJS4yZiAoJS4xZikiLCBIX3NoYW5ub24sIGV4cChIX3NoYW5ub24pKSksDQogICAgICAgICAgICBoanVzdCA9IDEuMSwgc2l6ZSA9IDIuOCwgY29sb3IgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBmYWNldF93cmFwKH4gdGlwbywgc2NhbGVzID0gImZyZWVfeSIsIG5jb2wgPSAxKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBuYW1lID0gIsONbmRpY2UgZGUgU2hhbm5vbiAoSCkiLA0KICAgIGxpbWl0cyA9IGMoMCwgbWF4SF9nb2IgKiAxLjE1KSwNCiAgICBzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIG1heEhfZ29iLCBuYW1lID0gIsONbmRpY2UgZGUgUGllbG91IChKKSIsDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKQ0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVG9wIDEwIOKGkSIgPSAiIzU2QjRFOSIsICJUb3AgMTAg4oaTIiA9ICIjQ0M3OUE3IikpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXZlcnNpZGFkIEluc3RpdHVjaW9uYWwgKEdvYmVybmFjacOzbikgcG9yIENvbXVuYSIsDQogICAgc3VidGl0bGUgPSAiVG9wIDEwIGNvbXVuYXMgY29uIG1heW9yIHkgbWVub3IgZGl2ZXJzaWRhZCB8IEJhcnJhczogU2hhbm5vbiAoSCkgfCBMw61uZWE6IFBpZWxvdSAoSikiLA0KICAgIHggPSAiQ29tdW5hIChJRCAtIE5vbWJyZSkiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGRhdG9zIGRlIHByb3llY3RvcyBBQ0EgLSBXaWxsaWFtIEd1dGllcnJleiINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTQsIGhqdXN0ID0gMC41KSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiZ3JheTQwIiwgaGp1c3QgPSAwLjUpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4ociA9IDEwKSksDQogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMTApKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksICAjIFJlZHVjaXIgdGFtYcOxbyB0ZXh0byBlamUgWQ0KICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDEsIDIsIDEsIDEsICJjbSIpICAjIEF1bWVudGFyIG1hcmdlbiBkZXJlY2hvDQogICkNCg0KIyBHdWFyZGFyIGNvbiBkaW1lbnNpb25lcyBlc3BlY8OtZmljYXMNCmdnc2F2ZSgiZ29iX2RpdmVyc2l0eV9wbG90LnBuZyIsIGdvYl9wbG90LCB3aWR0aCA9IDE0LCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KcHJpbnQoZ29iX3Bsb3QpDQoNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgQ0ZHOiBncsOhZmljbyBjb24gdG9vbHRpcHMgeSBhanVzdGUgcGFyYSBQaWVsb3UNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQptYXhIIDwtIG1heCh0YWJsYV9leHRyZW1vc19jZmckSF9zaGFubm9uLCBuYS5ybSA9IFRSVUUpDQoNCmNmZ19wbG90MiA8LSBnZ3Bsb3QodGFibGFfZXh0cmVtb3NfY2ZnLCANCiAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBDT01VTkFfT1JELCANCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBIX3NoYW5ub24sDQogICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gdGlwbykpICsNCiAgIyBCQVJSQVMgY29uIHRvb2x0aXAgKHRleHQpDQogIGdlb21fY29sKGFlcyh0ZXh0ID0gcGFzdGUwKA0KICAgICAgICAgICAgICAgICAgICAiQ29tdW5hOiAiLCBDT01VTkEsICJcbiIsDQogICAgICAgICAgICAgICAgICAgICJIID0gIiwgc3ByaW50ZigiJS4yZiIsIEhfc2hhbm5vbiksIA0KICAgICAgICAgICAgICAgICAgICAiIChleHA9Iiwgc3ByaW50ZigiJS4xZiIsIGV4cChIX3NoYW5ub24pKSwgIilcbiIsDQogICAgICAgICAgICAgICAgICAgICJKID0gIiwgc3ByaW50ZigiJS4yZiIsIHBpZWxvdSksICJcbiIsDQogICAgICAgICAgICAgICAgICAgICJOID0gIiwgbl9wcm95ZWN0b3MNCiAgICAgICAgICAgICAgICApKSwNCiAgICAgICAgICAgd2lkdGggPSAwLjcsIGFscGhhID0gMC45NSkgKw0KICAjIExJTkVBIHkgUFVOVE9TIGRlIFBpZWxvdSAoZXNjYWxhZG9zKQ0KICBnZW9tX2xpbmUoYWVzKHkgPSBwaWVsb3UgKiBtYXhILCBncm91cCA9IDEpLCANCiAgICAgICAgICAgIGNvbG9yID0gIiNFNjlGMDAiLCBzaXplID0gMS4wLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGdlb21fcG9pbnQoYWVzKHkgPSBwaWVsb3UgKiBtYXhILA0KICAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUwKCJDb211bmE6ICIsIENPTVVOQSwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSiA9ICIsIHNwcmludGYoIiUuMmYiLCBwaWVsb3UpLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIID0gIiwgc3ByaW50ZigiJS4yZiIsIEhfc2hhbm5vbikpKSwNCiAgICAgICAgICAgICBjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgpICsNCiAgDQogICMgRXRpcXVldGFzIGRlIFBpZWxvdTogY29sb2NhZGFzIGxpZ2VyYW1lbnRlIGhhY2lhIGxhIGRlcmVjaGEgKGhqdXN0IG5lZ2F0aXZvKQ0KICBnZW9tX3RleHQoYWVzKHkgPSBwaWVsb3UgKiBtYXhILCBsYWJlbCA9IHNwcmludGYoIko9JS4yZiIsIHBpZWxvdSkpLA0KICAgICAgICAgICAgaGp1c3QgPSAtMC4wOCwgc2l6ZSA9IDIuOCwgY29sb3IgPSAiI0Q1NUUwMCIpICsNCiAgIyBFdGlxdWV0YXMgZGVudHJvIGRlIGxhcyBiYXJyYXMgKEggeSBleHAoSCkpDQogIGdlb21fdGV4dChhZXMoeSA9IEhfc2hhbm5vbiwgDQogICAgICAgICAgICAgICAgbGFiZWwgPSBzcHJpbnRmKCIlLjJmICglLjFmKSIsIEhfc2hhbm5vbiwgZXhwKEhfc2hhbm5vbikpKSwNCiAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDIuOSwgY29sb3IgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBmYWNldF93cmFwKH4gdGlwbywgc2NhbGVzID0gImZyZWVfeSIsIG5jb2wgPSAxKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cygNCiAgICBuYW1lID0gIsONbmRpY2UgZGUgU2hhbm5vbiAoSCkiLA0KICAgIGxpbWl0cyA9IGMoMCwgbWF4SCAqIDEuMzApLCAgICMgYXVtZW50YXIgcGFyYSBkYXIgZXNwYWNpbyBhIFBpZWxvdQ0KICAgIHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gbWF4SCwgbmFtZSA9ICLDjW5kaWNlIGRlIFBpZWxvdSAoSikiLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4wMSkpDQogICkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUb3AgMTAg4oaRIiA9ICIjNTZCNEU5IiwgIlRvcCAxMCDihpMiID0gIiNDQzc5QTciKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpdmVyc2lkYWQgZGUgVGlwb2xvZ8OtYXMgQ0ZHIHBvciBDb211bmEiLA0KICAgIHN1YnRpdGxlID0gIlRvcCAxMCBjb211bmFzIGNvbiBtYXlvciB5IG1lbm9yIGRpdmVyc2lkYWQgfCBCYXJyYXM6IFNoYW5ub24gKEgpIHwgTMOtbmVhOiBQaWVsb3UgKEopIiwNCiAgICB4ID0gIkNvbXVuYSAoSUQgLSBOb21icmUpIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSBkYXRvcyBkZSBwcm95ZWN0b3MgQUNBIC0gV2lsbGlhbSBHdXRpZXJyZXoiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDExKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0LCBoanVzdCA9IDAuNSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImdyYXk0MCIsIGhqdXN0ID0gMC41KSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDExKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDEyLCByID0gMTIwLCBiID0gMTIsIGwgPSAxODApLCAgIyBtYXJnZW4gZGVyZWNobyBncmFuZGUNCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSwNCiAgICBwYW5lbC5jbGlwID0gIm9mZiIgICAgIyA8LS0gcGVybWl0ZSBxdWUgdGV4dG9zIGZ1ZXJhIGRlbCBwYW5lbCBubyBzZSBjb3J0ZW4gKGdncGxvdDIgPj0zLjQpDQogICkNCg0KIyBHdWFyZGFyIG9wY2lvbmFsIChzaSBxdWllcmVzIGxhIGltYWdlbiBlc3TDoXRpY2EpDQpnZ3NhdmUoImNmZ19kaXZlcnNpdHlfcGxvdF9hZGoucG5nIiwgY2ZnX3Bsb3QyLCB3aWR0aCA9IDE0LCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBHT0I6IGdyw6FmaWNvIGNvbiB0b29sdGlwcyB5IGFqdXN0ZSBwYXJhIFBpZWxvdQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCm1heEhfZ29iIDwtIG1heCh0YWJsYV9leHRyZW1vc19nb2IkSF9zaGFubm9uLCBuYS5ybSA9IFRSVUUpDQoNCmdvYl9wbG90MiA8LSBnZ3Bsb3QodGFibGFfZXh0cmVtb3NfZ29iLCBhZXMoeCA9IENPTVVOQV9PUkQsIHkgPSBIX3NoYW5ub24sIGZpbGwgPSB0aXBvKSkgKw0KICBnZW9tX2NvbChhZXModGV4dCA9IHBhc3RlMCgNCiAgICAgICAgICAgICAgICAgICAgIkNvbXVuYTogIiwgQ09NVU5BLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAiSCA9ICIsIHNwcmludGYoIiUuMmYiLCBIX3NoYW5ub24pLCANCiAgICAgICAgICAgICAgICAgICAgIiAoZXhwPSIsIHNwcmludGYoIiUuMWYiLCBleHAoSF9zaGFubm9uKSksICIpXG4iLA0KICAgICAgICAgICAgICAgICAgICAiSiA9ICIsIHNwcmludGYoIiUuMmYiLCBwaWVsb3UpLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAiTiA9ICIsIG5fcHJveWVjdG9zDQogICAgICAgICAgICAgICAgKSksDQogICAgICAgICAgIHdpZHRoID0gMC43LCBhbHBoYSA9IDAuOTUpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gcGllbG91ICogbWF4SF9nb2IsIGdyb3VwID0gMSksIA0KICAgICAgICAgICAgY29sb3IgPSAiI0U2OUYwMCIsIHNpemUgPSAxLjAsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgZ2VvbV9wb2ludChhZXMoeSA9IHBpZWxvdSAqIG1heEhfZ29iLA0KICAgICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUwKCJDb211bmE6ICIsIENPTVVOQSwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSiA9ICIsIHNwcmludGYoIiUuMmYiLCBwaWVsb3UpLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIID0gIiwgc3ByaW50ZigiJS4yZiIsIEhfc2hhbm5vbikpKSwNCiAgICAgICAgICAgICBjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgpICsNCiAgZ2VvbV90ZXh0KGFlcyh5ID0gcGllbG91ICogbWF4SF9nb2IsIGxhYmVsID0gc3ByaW50ZigiSj0lLjJmIiwgcGllbG91KSksDQogICAgICAgICAgICBoanVzdCA9IC0wLjA4LCBzaXplID0gMi44LCBjb2xvciA9ICIjRDU1RTAwIikgKw0KICBnZW9tX3RleHQoYWVzKHkgPSBIX3NoYW5ub24sIGxhYmVsID0gc3ByaW50ZigiJS4yZiAoJS4xZikiLCBIX3NoYW5ub24sIGV4cChIX3NoYW5ub24pKSksDQogICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSAyLjksIGNvbG9yID0gIndoaXRlIiwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgZmFjZXRfd3JhcCh+IHRpcG8sIHNjYWxlcyA9ICJmcmVlX3kiLCBuY29sID0gMSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbmFtZSA9ICLDjW5kaWNlIGRlIFNoYW5ub24gKEgpIiwNCiAgICBsaW1pdHMgPSBjKDAsIG1heEhfZ29iICogMS4zMCksDQogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyBtYXhIX2dvYiwgbmFtZSA9ICLDjW5kaWNlIGRlIFBpZWxvdSAoSikiLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4wMSkpDQogICkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUb3AgMTAg4oaRIiA9ICIjNTZCNEU5IiwgIlRvcCAxMCDihpMiID0gIiNDQzc5QTciKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpdmVyc2lkYWQgSW5zdGl0dWNpb25hbCAoR29iZXJuYWNpw7NuKSBwb3IgQ29tdW5hIiwNCiAgICBzdWJ0aXRsZSA9ICJUb3AgMTAgY29tdW5hcyBjb24gbWF5b3IgeSBtZW5vciBkaXZlcnNpZGFkIHwgQmFycmFzOiBTaGFubm9uIChIKSB8IEzDrW5lYTogUGllbG91IChKKSIsDQogICAgeCA9ICJDb211bmEgKElEIC0gTm9tYnJlKSIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVsYWJvcmFjacOzbiBwcm9waWEgZGF0b3MgZGUgcHJveWVjdG9zIEFDQSAtIFdpbGxpYW0gR3V0aWVycmV6Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMSkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCwgaGp1c3QgPSAwLjUpLA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5NDAiLCBoanVzdCA9IDAuNSksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHQgPSAxMiwgciA9IDEyMCwgYiA9IDEyLCBsID0gMTgwKSwNCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSwNCiAgICBwYW5lbC5jbGlwID0gIm9mZiINCiAgKQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBDb252ZXJ0aXIgYSBwbG90bHkgY29uIGRpbWVuc2lvbmVzIGZpamFzIHkgbW9zdHJhcg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnBsb3RseV9maXhfc2l6ZSA8LSBmdW5jdGlvbihnZ29iaiwgd2lkdGggPSAxNjAwLCBoZWlnaHQgPSA4MDAsIG1hcmdpbiA9IGxpc3QobCA9IDE4MCwgciA9IDEyMCwgYiA9IDEwMCwgdCA9IDkwKSkgew0KICBwIDwtIGdncGxvdGx5KGdnb2JqLCB0b29sdGlwID0gInRleHQiKQ0KICBwIDwtIHAgJT4lIGxheW91dChhdXRvc2l6ZSA9IEZBTFNFLCB3aWR0aCA9IHdpZHRoLCBoZWlnaHQgPSBoZWlnaHQsIG1hcmdpbiA9IG1hcmdpbikNCiAgIyBBdW1lbnRhciBib3RvbmVzIMO6dGlsZXMNCiAgcCA8LSBwICU+JSBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICBtb2RlQmFyQnV0dG9uc1RvQWRkID0gbGlzdCgidG9JbWFnZSIsICJ6b29tMmQiLCAicmVzZXRTY2FsZTJkIikpDQogIHJldHVybihwKQ0KfQ0KDQpjZmdfcGxvdGx5IDwtIHBsb3RseV9maXhfc2l6ZShjZmdfcGxvdDIsIHdpZHRoID0gMTYwMCwgaGVpZ2h0ID0gODAwKQ0KZ29iX3Bsb3RseSA8LSBwbG90bHlfZml4X3NpemUoZ29iX3Bsb3QyLCB3aWR0aCA9IDE2MDAsIGhlaWdodCA9IDgwMCkNCg0KIyBSZW5kZXIgKGVuIFIgTWFya2Rvd24gc2UgbW9zdHJhcsOhbiBsb3MgZG9zIGVuIG9yZGVuKQ0KY2ZnX3Bsb3RseQ0KaHRtbHRvb2xzOjp0YWdMaXN0KGh0bWx0b29sczo6dGFncyRicigpLCBodG1sdG9vbHM6OnRhZ3MkYnIoKSkNCmdvYl9wbG90bHkNCg0KDQojIz09PT09PT09PT09PT09PT1UYWJsYSBpbnRlcnByZXRhdGl2YSBkZWwgaW5kaWNlIFNoYW5ub249PT09PT09PT09PT09PT09PT09PT09PT09PT09IyMNCnRibCA8LSB0aWJibGU6OnRpYmJsZSgNCiAgQ29tdW5hID0gYygNCiAgICAiMTQxMjEyIC0gQ29tdW5hIFByw7NjZXIgSm9zw6kgRsOpbGl4IFJpYmFzIiwNCiAgICAiMTQxNzAxIC0gQ29tdW5hIFNvY2lvcHJvZHVjdGl2YSBBbHRvIGRlIGxhIENhcmJvbmVyYSIsDQogICAgIjE0MTIwMyAtIENvbXVuYSBlbiBDb25zdHJ1Y2Npw7NuIExhcyBIZXJvw61uYXMgZGUgTcOpcmlkYSIsDQogICAgIjE0MjAwNiAtIENvbXVuYSBTYW4gSnVhbiBkZSBsb3MgTGliZXJ0YWRvcmVzIiwNCiAgICAiMTQwMTAxIC0gQ29tdW5hIFVuacOzbiBkZSBDaMOhdmV6Ig0KICApLA0KICBIX0NGRyA9IGMoMS44MzEsIDEuNzkyLCAxLjYwOSwgMC44NjgsIDAuNjM3KSwNCiAgZV9DRkcgPSByb3VuZChleHAoYygxLjgzMSwgMS43OTIsIDEuNjA5LCAwLjg2OCwgMC42MzcpKSwgMiksDQogIEhfR09CID0gYygyLjE5NywgMS41NjEsIDEuNjA5LCAxLjU2MSwgMC42MzcpLA0KICBlX0dPQiA9IHJvdW5kKGV4cChjKDIuMTk3LCAxLjU2MSwgMS42MDksIDEuNTYxLCAwLjYzNykpLCAyKSwNCiAgSW50ZXJwcmV0YWNpb24gPSBjKA0KICAgICJBbHRhIGNvbXBsZWppZGFkOiDiiYg2IHRpcG9sb2fDrWFzIHkg4omIOSBpbnN0aXR1Y2lvbmVzIGVmZWN0aXZhcyDihpIgY29vcmQuIG11bHRpc2VjdG9yaWFsIHJlcXVlcmlkYS4iLA0KICAgICJEaXZlcnNhIHkgZXF1aWxpYnJhZGE6IOKJiDYgdGlwb2xvZ8OtYXMgeSDiiYg0Ljc3IGluc3RpdHVjaW9uZXMg4oaSIHByaW9yaXphciBnb2Jlcm5hbnphIGNvbXBhcnRpZGEuIiwNCiAgICAiUGVyZmlsIG11bHRpZnVuY2lvbmFsOiDiiYg1IHRpcG9sb2fDrWFzIGUgaW5zdGl0dWNpb25lcyBlZmVjdGl2YXMg4oaSIGludGVydmVuY2lvbmVzIGludGVncmFkYXMuIiwNCiAgICAiQ29uY2VudHJhY2nDs24gbW9kZXJhZGEgKOKJiDIuMzggdGlwb2xvZ8OtYXMpIHBlcm8gcmVkIGluc3RpdHVjaW9uYWwgYW1wbGlhICjiiYg0Ljc3KSDihpIgcmV2aXNhciBkdXBsaWNpZGFkZXMuIiwNCiAgICAiRnVlcnRlIGZvY2FsaXphY2nDs246IOKJiDEuODkgdGlwb2xvZ8OtYXMgZSBpbnN0aXR1Y2lvbmVzIOKGkiBpbnRlcnZlbmNpb25lcyBmb2NhbGVzIGRlIGFsdG8gaW1wYWN0by4iDQogICksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQprbml0cjo6a2FibGUoDQogIHRibCwNCiAgY2FwdGlvbiA9ICJSZXN1bWVuOiBIJyB5IE7Dum1lcm8gZWZlY3Rpdm8gKGVee0gnfSkg4oCUIENGRyB2cyBHb2Jlcm5hY2nDs24gKDUgY29tdW5hcykiLA0KICBkaWdpdHMgPSAyLA0KICBhbGlnbiA9IGMoImwiLCAiciIsICJyIiwgInIiLCAiciIsICJsIikNCikgJT4lDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSkNCg0KYGBgDQoNCiMjICoqSW50ZXJwcmV0YWNpw7NuICBkZWwgw41uZGljZSBkZSBTaGFubm9uIChI4oCyKSB5IFBpZWxvdSAoSikqKg0KDQpFbCBhbsOhbGlzaXMgZGUgZGl2ZXJzaWRhZCAow41uZGljZSBkZSBTaGFubm9uLCBI4oCyKSB5IGRlIGVxdWl0YXRpdmlkYWQgKMONbmRpY2UgZGUgUGllbG91LCBKKSBwZXJtaXRlIGNhcmFjdGVyaXphciBkZSBmb3JtYSBjb21wYWN0YSBjw7NtbyBjYWRhIGNvbXVuYSBkaXN0cmlidXllIHN1cyBudWRvcyBjcsOtdGljb3MgeSBxdcOpIGltcGxpY2FjaW9uZXMgcHLDoWN0aWNhcyB0aWVuZSBlc2EgZGlzdHJpYnVjacOzbiBwYXJhIGxhIHBsYW5pZmljYWNpw7NuIHkgZWplY3VjacOzbiBkZSBwcm95ZWN0b3MuDQoNCi1WZWFtb3MgZXN0ZSBlamVtcGxvIGxhICoqQ29tdW5hcyBjb24gSOKAsiBhbHRvIChlai4gMS44MyDigJQgMS42MCk6KiogY29tbyAqMTQxMjEyIC0gQ29tdW5hIFByw7NjZXIgSm9zw6kgRsOpbGl4IFJpYmFzKiAoSOKAsj0xLjgzMSwgSj0wLjk0MSwgbj05KSBvICoxNDE3MDEgLSBBbHRvIGRlIGxhIENhcmJvbmVyYSogKEjigLI9MS43OTIsIEo9MS4wMDAsIG49NiksIG11ZXN0cmFuICoqYWx0YSBkaXZlcnNpZGFkIHRlbcOhdGljYSoqIHkgdW5hIGRpc3RyaWJ1Y2nDs24gcmVsYXRpdmFtZW50ZSBlcXVpbGlicmFkYSAoSiBjZXJjYW5vIGEgMSkNCg0KUHVlZGVuIHJlcHJlc2VudGFyIChhKSAqKmNhcGFjaWRhZCBkaWFnbsOzc3RpY2EgZ2VudWluYSoqLCBsYSBjb211bmEgaWRlbnRpZmljYSBtw7psdGlwbGVzIHByb2JsZW3DoXRpY2FzIHJlbGV2YW50ZXMgbyAoYikgKiphY3VtdWxhY2nDs24gZGUgY2FyZW5jaWFzKiogKGFiYW5kb25vIGluc3RpdHVjaW9uYWwpLiBQYXJhIGRlY2lkaXIgZW50cmUgKGEpIHkgKGIpIGNvbnZpZW5lIGNydXphciBI4oCyIGNvbiBpbmRpY2Fkb3JlcyBkZSBlamVjdWNpw7NuIChSYXRpbyBBQ0EpIHkgbGEgaW50ZW5zaWRhZCBkZSBwcm95ZWN0b3MsIGFkZW3DoXMgZGUgZW50cmV2aXN0YXMgZW4gZGlyZWN0YW1lbnRlIGxhcyBjb211bmFzLCB1bmEgZWxlbWVudG8gaW1wb3J0YW50ZSBubyBoZWNobyBlbiBlc3RlIHRyYWJham8uDQoNCi0gICBBaG9yYSBjb24gbGFzICoqQ29tdW5hcyBjb24gSOKAsiBiYWpvIChjb21vIHBvciBlamVtcGxvcyBkZSAwLjYzIOKAlCAwLjg3KToqKiBjb21vIHZhcmlhcyBlbnRyYWRhcyBjb21vICoxNDAxMDEtQy1VUkItMjAxOC0xMS0wMDE4IC0gMTEuIENPTVVOQSBVTknDk04gREUgQ0jDgVZFWiogZGVsIHRvcCBtZW5vciAoSOKAsiDiiYggMC42MzcsIEog4omIIDAuOTE4KSwgcmV2ZWxhbiAqKmZvY2FsaXphY2nDs24gdGVtw6F0aWNhKiosIHVuYSBncmFuIGNhbnRpZGFkIGRlIGNvbXVuYXMgdGllbmVuIGVzdGEgZm9jYWxpemFjacOzbi4NCg0KUHVlZGUgdHJhdGFyc2UgZGUgKGEpICoqcHJpb3JpemFjacOzbiBlc3RyYXTDqWdpY2EqKiwgY29uY2VudHJhY2nDs24gZW4gcHJvYmxlbWFzIHZpYWJsZXMgeSBtYXlvciBwcm9iYWJpbGlkYWQgZGUgY3VsbWluYWNpw7NuIG8gKGIpICoqZGVzY29uZXhpw7NuL2ludmlhYmlsaWRhZCoqLCBjdWFuZG8gbGEgYmFqYSBkaXZlcnNpZGFkIHJlc3BvbmRlIGEgcHJveWVjdG9zIG1vbnVtZW50YWxlcyBvIGEgbGEgcmVwZXRpY2nDs24gZGUgdW4gbWlzbW8gcHJvYmxlbWEgc2luIGF2YW5jZSByZWFsLg0KDQpOdWV2YW1lbnRlLCBlbCBjcnVjZSBjb24gdGFzYXMgZGUgY3VsbWluYWNpw7NuIHkgbGEgZXNjYWxhIGRlIGxvcyBwcm95ZWN0b3MgcGVybWl0ZSBkaXN0aW5ndWlyIGVzdG9zIGVzY2VuYXJpb3MuDQoNCi0gICAqKlVzbyBwcsOhY3RpY286KiogcHJvcG9uZW1vcyB1c2FyIHJlZ2xhcyBzaW1wbGVzIHBhcmEgZGlhZ27Ds3N0aWNvIHLDoXBpZG86DQoNCiAgICAxLiAgKipI4oCyIGFsdG8gKyBKIGFsdG8gKyBSYXRpbyBBQ0EgYmFqbyoqIOKGkiBzZcOxYWwgZGUgKmFjdW11bGFjacOzbi9hYmFuZG9ubyogKHJlcXVpZXJlIGF0ZW5jacOzbiBpbnN0aXR1Y2lvbmFsIHkgcmV2aXNpw7NuIGRlIGFjdG9yZXMgcmVzcG9uc2FibGVzKS4NCg0KICAgIDIuICAqKkjigLIgYWx0byArIFJhdGlvIEFDQSBhbHRvKiog4oaSICpnZXN0acOzbiBpbnRlZ3JhbCBlZmVjdGl2YSogKHByaW9yaXphciBlc2NhbGFtaWVudG8gZGUgYnVlbmFzIHByw6FjdGljYXMpLg0KDQogICAgMy4gICoqSOKAsiBiYWpvICsgUmF0aW8gQUNBIGFsdG8qKiDihpIgKmZvY2FsaXphY2nDs24gZXN0cmF0w6lnaWNhIGVmZWN0aXZhKiAobW9kZWxvIHJlcGxpY2FibGUpLg0KDQogICAgNC4gICoqSOKAsiBiYWpvICsgUmF0aW8gQUNBIGJham8qKiDihpIgKnJpZXNnbyBkZSBpbnZpYWJpbGlkYWQqIChyZWZvcm11bGFyIGFsY2FuY2UgeSBhY3RvciByZXNwb25zYWJsZSkuDQoNCiAgICBFbiBzw61udGVzaXM6IEjigLIgeSBKIHNvbiBpbmRpY2Fkb3JlcyBzaW50w6l0aWNvcyB5IMO6dGlsZXMgcGFyYSBjbGFzaWZpY2FyIGNvbXVuYXMgcsOhcGlkYW1lbnRlOyBzdSB2YWxvciByZWFsIHBhcmEgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGFwYXJlY2UgY3VhbmRvIHNlIGNvbWJpbmFuIGNvbiBtw6l0cmljYXMgZGUgZWplY3VjacOzbiAoUmF0aW8gQUNBKSB5IGNvbiBsYSByZXZpc2nDs24gY3VhbGl0YXRpdmEgaW4gc2l0dS4NCg0KTGEgdGFibGEgbXVlc3RyYSBI4oCyIChTaGFubm9uKSB5IHN1IGNvbnZlcnNpw7NuIGEgbsO6bWVybyBlZmVjdGl2byAkZV57SCd9JCBwYXJhIGxhcyBkaW1lbnNpb25lcyBDRkcgKHRpcG9sb2fDrWFzKSB5IEdvYmVybmFjacOzbiAoYWN0b3JlcykuDQoNClZhbG9yZXMgYWx0b3MgZGUgJGVee0gnfSQgaW5kaWNhbiB1bmEgKiptYXlvciBjYXJnYSBkZSBjb29yZGluYWNpw7NuKiogeSBjb21wbGVqaWRhZCBvcGVyYXRpdmEgKGVqLiBDb211bmEgUHLDs2NlciBKb3PDqSBGw6lsaXggUmliYXM6IOKJiDYgdGlwb2xvZ8OtYXMgeSDiiYg5IGluc3RpdHVjaW9uZXMgZWZlY3RpdmFzKSwgcG9yIGxvIHF1ZSByZXF1aWVyZW4gbWVjYW5pc21vcyBkZSBnb2Jlcm5hbnphIGludGVncmFkb3MuIFZhbG9yZXMgYmFqb3Mgc2XDsWFsYW4gKipmb2NhbGl6YWNpw7NuIHRlbcOhdGljYSoqIHkgcGVybWl0ZW4gaW50ZXJ2ZW5jaW9uZXMgbcOhcyBkaXJlY3RhcyB5IHJlcGxpY2FibGVzIChlai4gVW5pw7NuIGRlIENow6F2ZXo6IOKJiDEuOSB0aXBvbG9nw61hcykuDQoNCkVuIHByw6FjdGljYSwgcHJpb3JpemFyIHJlY3Vyc29zIGRvbmRlICRlXntIJ30kIGVzIGFsdG8geSByZXBsaWNhciBtb2RlbG9zIGRlIGdlc3Rpw7NuIGVuIGNvbXVuYXMgY29uICRlXntIJ30kIG1vZGVyYWRvL8OzcHRpbW8gbWF4aW1pemEgZWZpY2llbmNpYS4NCg0KDQojIyAqKkluZGljZSBTaGFubm9uIGRlIHJhdGlvIGRlIHByb3llY3RvIHBvciB0aXBvbG9nw61hcyoqDQoNCkxhIGFwbGljYWNpw7NuIGRlbCDDrW5kaWNlIGRlIFNoYW5ub24gYSBsYSB2YXJpYWJsZSBSYXRpbyBBQ0EgUHJveWVjdG8gQ3VsbWluYWRvIHBlcm1pdGUgZXZhbHVhciBsYSBkaXZlcnNpZGFkIGRlIHJlc3VsdGFkb3MgbyBlc3RhZG9zIGRlIGN1bG1pbmFjacOzbiBkZSBsb3MgcHJveWVjdG9zIGRlbnRybyBkZSBjYWRhIGNvbXVuYS4gQSBkaWZlcmVuY2lhIGRlIGxvcyBhbsOhbGlzaXMgYW50ZXJpb3JlcyBxdWUgbWVkw61hbiBsYSB2YXJpZWRhZCBkZSBwcm9ibGVtYXMgbyBhY3RvcmVzLCBlc3RlIMOtbmRpY2UgY3VhbnRpZmljYSBhcXXDrSBsYSBoZXRlcm9nZW5laWRhZCBlbiBsYSBlZmVjdGl2aWRhZC4NCg0KQ29tbyBzZSBoYWNlIGVuIGVsIHByaW1lciBhbsOhbGlzaXMgZGUgU2hhbm5vbiwgbm9zIHBsYW50ZWFtb3MgbGFzIHNpZ3VpZW50ZSBoaXDDs3Rlc2lzOg0KDQoqKlZhbG9yIGRlIFNoYW5ub24gQUxUTyAoSCcgXD4gMSwwKSoqDQoNCi0gICBHZXN0acOzbiBSZWFsaXN0YSB5IFRyYW5zcGFyZW50ZSwgTGEgY29tdW5hIGRvY3VtZW50YSBkZSBtYW5lcmEgaG9uZXN0YSB1biBwYW5vcmFtYSBtaXh0byBkZSDDqXhpdG9zLCBwcm95ZWN0b3MgZW4gY3Vyc28geSBmcmFjYXNvcy4gTGEgZGl2ZXJzaWRhZCByZWZsZWphIHVuYSBnZXN0acOzbiBhY3RpdmEgZGUgbcO6bHRpcGxlcyAibWljcm8gZGVtYW5kYXMiIGNvbiByZXN1bHRhZG9zIHZhcmlhYmxlcy4gTsO6bWVybyBtb2RlcmFkby1hbHRvIGRlIHByb3llY3Rvcy4NCg0KLSAgIEZyYWdtZW50YWNpw7NuIGUgSW5jb25zaXN0ZW5jaWEsIExhIGRpdmVyc2lkYWQgZGUgcmVzdWx0YWRvcyBlcyBzw61udG9tYSBkZSB1bmEgZWplY3VjacOzbiBlcnLDoXRpY2EsIGRvbmRlIGVsIMOpeGl0byBkZXBlbmRlIGRlIGZhY3RvcmVzIHZvbMOhdGlsZXMgKGFjdG9yIGluc3RpdHVjaW9uYWwgZXNwZWPDrWZpY28sIHJlY3Vyc29zIGludGVybWl0ZW50ZXMpLCBubyBkZSB1bmEgZXN0cmF0ZWdpYSBjb2hlcmVudGUuIC0gQmFqYSBlZmVjdGl2aWRhZCBwcm9tZWRpbyBhIHBlc2FyIGRlIGxhIGRpdmVyc2lkYWQuIFBvZHLDrWEgc3ViZXN0aW1hcnNlIGVsIGVzZnVlcnpvIGRlIGdlc3Rpb25hciByZWFsaWRhZGVzIGNvbXBsZWphcy4NCg0KKipWYWxvciBkZWwgU2hhbm5vbiBCQUpPIChIJyBcPCAwKSoqDQoNCi0gICBFZmVjdGl2aWRhZCBIb21vZ8OpbmVhIHkgUHJlZGVjaWJsZSwgVG9kb3MgbG9zIHByb3llY3RvcyBkZSBsYSBjb211bmEgY29tcGFydGVuIHVuIG1pc21vIGVzdGFkbyBkZSBhbHRvIMOpeGl0byAoIkFMVEEiKSwgbG8gcXVlIGluZGljYSB1bmEgZ2VzdGnDs24gZXhjZXBjaW9uYWxtZW50ZSBlZmljYXogeSBjb25zaXN0ZW50ZS4gTsO6bWVybyB2aWFibGUgZGUgcHJveWVjdG9zLg0KDQotICAgRmFsbGEgRXN0cnVjdHVyYWwgeSBEZXNjb25leGnDs24sIFRvZG9zIGxvcyBwcm95ZWN0b3MgZGUgbGEgY29tdW5hIGVzdMOhbiBlc3RhbmNhZG9zIGVuIHVuIG1pc21vIGVzdGFkbyBkZSBiYWphIGVmZWN0aXZpZGFkICgiTVVZIEJBSkEiLyJCQUpBIikuIFJldmVsYSB1bmEgZGVzY29uZXhpw7NuIHRvdGFsIGVudHJlIGxhIHBsYW5pZmljYWNpw7NuIHkgbGEgZWplY3VjacOzbiwgbyBsYSBpbnNpc3RlbmNpYSBlbiBtYWNyb3Byb3llY3RvcyBpbnZpYWJsZXMuIFByb3llY3RvcyBhbWJpY2lvc29zIG8gcmVwZXRpdGl2b3MuIExhIGNvbXVuaWRhZCBwb2Ryw61hIHBlcmNpYmlybG8gY29tbyBhYmFuZG9ubyBpbnN0aXR1Y2lvbmFsLg0KDQpgYGB7ciwgZmlnLndpZHRoPTE2LCBmaWcuaGVpZ2h0PTEyLCBvdXQud2lkdGg9IjEwMCUifQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KDQogICAgICAgIGNvbmZsaWN0X3ByZWZlcigic2VsZWN0IiwgImRwbHlyIikNCiAgICAgICAgY29uZmxpY3RfcHJlZmVyKCJmaWx0ZXIiLCAiZHBseXIiKQ0KDQogICAgICAgICMjICoqSW5kaWNlIFNoYW5ub24gZGUgcmF0aW8gZGUgcHJveWVjdG8gcG9yIHRpcG9sb2fDrWFzKioNCg0KICAgICAgICAjIEZpbHRyYXIgeSBwcmVwYXJhciBkYXRvcyBwYXJhIFJhdGlvDQogICAgICAgIGRmX3JhdGlvX2NsZWFuIDwtIGRmX3JhdyAlPiUgDQogICAgICAgICAgZmlsdGVyKCFpcy5uYShSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPKSkgJT4lICANCiAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPID0gZmFjdG9yKA0KICAgICAgICAgICAgICBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPLA0KICAgICAgICAgICAgICBsZXZlbHMgPSAxOjQsDQogICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1VWSBCQUpBIiwgIkJBSkEiLCAiTUVESUEiLCAiQUxUQSIpDQogICAgICAgICAgICApDQogICAgICAgICAgKQ0KDQogICAgICAgICMgQ3JlYXIgZGF0b3Mgd2lkZSBwYXJhIGRpdmVyc2lkYWQNCiAgICAgICAgZGZfcmF0aW9fd2lkZSA8LSBkZl9yYXRpb19jbGVhbiAlPiUNCiAgICAgICAgICBncm91cF9ieShJRF9DT01VTkEsIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8pICU+JQ0KICAgICAgICAgIHN1bW1hcmlzZShuID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUNCiAgICAgICAgICBjb21wbGV0ZShJRF9DT01VTkEsIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIGZpbGwgPSBsaXN0KG4gPSAwKSkgJT4lDQogICAgICAgICAgcGl2b3Rfd2lkZXIoDQogICAgICAgICAgICBuYW1lc19mcm9tID0gUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETywgDQogICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG4sIA0KICAgICAgICAgICAgbmFtZXNfcHJlZml4ID0gInJhdGlvXyINCiAgICAgICAgICApDQoNCiAgICAgICAgIyBBc2VndXJhciBxdWUgdG9kYXMgbGFzIGNvbHVtbmFzIGRlIHJhdGlvIGV4aXN0YW4NCiAgICAgICAgcmF0aW9fY29scyA8LSBjKCJyYXRpb19NVVkgQkFKQSIsICJyYXRpb19CQUpBIiwgInJhdGlvX01FRElBIiwgInJhdGlvX0FMVEEiKQ0KICAgICAgICBmb3IgKGNvbCBpbiByYXRpb19jb2xzKSB7DQogICAgICAgICAgaWYgKCFjb2wgJWluJSBuYW1lcyhkZl9yYXRpb193aWRlKSkgew0KICAgICAgICAgICAgZGZfcmF0aW9fd2lkZVtbY29sXV0gPC0gMA0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgICMgQ2FsY3VsYXIgZGl2ZXJzaWRhZCBwYXJhIFJhdGlvDQogICAgICAgIGRpdl9yYXRpbyA8LSBkZl9yYXRpb193aWRlICU+JQ0KICAgICAgICAgIGxlZnRfam9pbihjb21tdW5lX21hcCwgYnkgPSAiSURfQ09NVU5BIikgJT4lDQogICAgICAgICAgbXV0YXRlKG5fcHJveWVjdG9zX3JhdGlvID0gcm93U3VtcyhzZWxlY3QoLiwgYWxsX29mKHJhdGlvX2NvbHMpKSkpICU+JQ0KICAgICAgICAgIHsNCiAgICAgICAgICAgIGNudHMgPC0gc2VsZWN0KC4sIGFsbF9vZihyYXRpb19jb2xzKSkNCiAgICAgICAgICAgIHRpYiA8LSBzZWxlY3QoLiwgSURfQ09NVU5BLCBDT01VTkEsIG5fcHJveWVjdG9zX3JhdGlvKQ0KICAgICAgICAgICAgSCA8LSB2ZWdhbjo6ZGl2ZXJzaXR5KGNudHMsIGluZGV4ID0gInNoYW5ub24iKQ0KICAgICAgICAgICAgcmljaGVzc2UgPC0gcm93U3VtcyhjbnRzID4gMCkNCiAgICAgICAgICAgIEogPC0gaWZlbHNlKHJpY2hlc3NlID4gMCwgSCAvIGxvZyhyaWNoZXNzZSksIE5BX3JlYWxfKQ0KICAgICAgICAgICAgYmluZF9jb2xzKHRpYiwgSF9zaGFubm9uID0gSCwgcGllbG91ID0gSikNCiAgICAgICAgICB9ICU+JQ0KICAgICAgICAgIG11dGF0ZShDT01VTkFfSURfTk9NQlJFID0gcGFzdGUoSURfQ09NVU5BLCAiLSIsIENPTVVOQSkpDQoNCiAgICAgICAgIyBDcmVhciB0b3AgeSBib3R0b20gMTANCiAgICAgICAgdG9wMTBfcmF0aW8gPC0gZGl2X3JhdGlvICU+JQ0KICAgICAgICAgIGFycmFuZ2UoZGVzYyhIX3NoYW5ub24pKSAlPiUNCiAgICAgICAgICBzbGljZSgxOjEwKSAlPiUNCiAgICAgICAgICBzZWxlY3QoQ09NVU5BX0lEX05PTUJSRSwgbl9wcm95ZWN0b3NfcmF0aW8sIEhfc2hhbm5vbiwgcGllbG91KQ0KDQogICAgICAgIGJvdHRvbTEwX3JhdGlvIDwtIGRpdl9yYXRpbyAlPiUNCiAgICAgICAgICBhcnJhbmdlKEhfc2hhbm5vbikgJT4lDQogICAgICAgICAgc2xpY2UoMToxMCkgJT4lDQogICAgICAgICAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIG5fcHJveWVjdG9zX3JhdGlvLCBIX3NoYW5ub24sIHBpZWxvdSkNCg0KICAgICAgICAjIFByZXBhcmFyIGRhdG9zIHBhcmEgZ3LDoWZpY28NCiAgICAgICAgdGFibGFfZXh0cmVtb3NfcmF0aW8gPC0gYmluZF9yb3dzKA0KICAgICAgICAgIHRvcDEwX3JhdGlvICU+JSANCiAgICAgICAgICAgIG11dGF0ZSh0aXBvID0gIk1heW9yIGRpdmVyc2lkYWQgKFRvcCAxMCkiKSAlPiUgDQogICAgICAgICAgICByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSksDQogICAgICAgICAgYm90dG9tMTBfcmF0aW8gJT4lIA0KICAgICAgICAgICAgbXV0YXRlKHRpcG8gPSAiTWVub3IgZGl2ZXJzaWRhZCAoQm90dG9tIDEwKSIpICU+JSANCiAgICAgICAgICAgIHJlbmFtZShDT01VTkEgPSBDT01VTkFfSURfTk9NQlJFKQ0KICAgICAgICApICU+JQ0KICAgICAgICAgIG11dGF0ZSgNCiAgICAgICAgICAgIGV0aXF1ZXRhX0ggPSBzcHJpbnRmKCJIOiAlLjJmIiwgSF9zaGFubm9uKSwNCiAgICAgICAgICAgIGV0aXF1ZXRhX0ogPSBzcHJpbnRmKCJKOiAlLjJmIiwgcGllbG91KQ0KICAgICAgICAgICkNCiAgICAgICAgIyMgVGFibGEgY29tcGxldGEgKFRvZGFzIGxhcyBjb211bmFzKQ0KICAgICAgICBkaXZfcmF0aW9fY29tcGxldG8gPC0gZGl2X3JhdGlvICU+JQ0KICAgICAgICAgIHNlbGVjdChDT01VTkFfSURfTk9NQlJFLCBuX3Byb3llY3Rvc19yYXRpbywgSF9zaGFubm9uLCBwaWVsb3UpICU+JQ0KICAgICAgICAgIGFycmFuZ2UoZGVzYyhIX3NoYW5ub24pKSAlPiUNCiAgICAgICAgICBtdXRhdGUoDQogICAgICAgICAgICBIX3NoYW5ub24gPSByb3VuZChIX3NoYW5ub24sIDMpLA0KICAgICAgICAgICAgcGllbG91ID0gcm91bmQocGllbG91LCAzKSwNCiAgICAgICAgICAgICMgSW50ZXJwcmV0YWNpw7NuIHLDoXBpZGENCiAgICAgICAgICAgIEludGVycHJldGFjaW9uID0gY2FzZV93aGVuKA0KICAgICAgICAgICAgICBIX3NoYW5ub24gPCAwLjUgfiAiQmFqYSBkaXZlcnNpZGFkIiwNCiAgICAgICAgICAgICAgSF9zaGFubm9uID49IDAuNSAmIEhfc2hhbm5vbiA8IDEuMCB+ICJEaXZlcnNpZGFkIG1lZGlhIiwNCiAgICAgICAgICAgICAgSF9zaGFubm9uID49IDEuMCB+ICJBbHRhIGRpdmVyc2lkYWQiDQogICAgICAgICAgICApDQogICAgICAgICAgKQ0KDQogICAgICAgICMgTW9zdHJhciB0YWJsYSBjb21wbGV0YSBvcmRlbmFkYSBwb3IgZGl2ZXJzaWRhZA0KICAgICAgICBjYXQoIlxuXG4qKkRpdmVyc2lkYWQgZGUgUmF0aW8gQUNBIGVuIHRvZGFzIGxhcyBjb211bmFzKipcbiIpDQogICAgICAgIGtuaXRyOjprYWJsZSgNCiAgICAgICAgICBkaXZfcmF0aW9fY29tcGxldG8sDQogICAgICAgICAgY29sLm5hbWVzID0gYygiQ29tdW5hIChJRCAtIE5vbWJyZSkiLCAiUHJveWVjdG9zIiwgIkggKFNoYW5ub24pIiwgIkogKFBpZWxvdSkiLCAiSW50ZXJwcmV0YWNpw7NuIiksDQogICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICBjYXB0aW9uID0gIkRpdmVyc2lkYWQgZGUgZXN0YWRvcyBkZSBjdWxtaW5hY2nDs24gZW4gdG9kYXMgbGFzIGNvbXVuYXMiDQogICAgICAgICkNCg0KICAgICAgICAjIFByZXBhcmFyIGRhdG9zIHBhcmEgZ3LDoWZpY28gKHNpbiBjcmVhciBldGlxdWV0YXMgcHJlLWRlZmluaWRhcykNCiAgICAgICAgdGFibGFfZXh0cmVtb3NfcmF0aW8gPC0gYmluZF9yb3dzKA0KICAgICAgICAgIHRvcDEwX3JhdGlvICU+JSANCiAgICAgICAgICAgIG11dGF0ZSh0aXBvID0gIk1heW9yIGRpdmVyc2lkYWQgKFRvcCAxMCkiKSAlPiUgDQogICAgICAgICAgICByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSksDQogICAgICAgICAgYm90dG9tMTBfcmF0aW8gJT4lIA0KICAgICAgICAgICAgbXV0YXRlKHRpcG8gPSAiTWVub3IgZGl2ZXJzaWRhZCAoQm90dG9tIDEwKSIpICU+JSANCiAgICAgICAgICAgIHJlbmFtZShDT01VTkEgPSBDT01VTkFfSURfTk9NQlJFKQ0KICAgICAgICApDQogICAgICAgICMgTm90YTogUmVtb3ZpbW9zIGxhcyBldGlxdWV0YXMgcHJlLWRlZmluaWRhcyBldGlxdWV0YV9IIHkgZXRpcXVldGFfSg0KDQogICAgICAgICMgQ2FsY3VsYXIgbWF4SF9yYXRpbw0KICAgICAgICBtYXhIX3JhdGlvIDwtIG1heCh0YWJsYV9leHRyZW1vc19yYXRpbyRIX3NoYW5ub24sIG5hLnJtID0gVFJVRSkgKiAxLjMNCg0KICAgICAgICAjIENyZWFyIGdyw6FmaWNvIGNvbiB2YWxvcmVzIGV4cG9uZW5jaWFsZXMgZW4gbGFzIGV0aXF1ZXRhcw0KICAgICAgICByYXRpb19wbG90IDwtIGdncGxvdCh0YWJsYV9leHRyZW1vc19yYXRpbywgYWVzKHggPSByZW9yZGVyKENPTVVOQSwgSF9zaGFubm9uKSwgeSA9IEhfc2hhbm5vbiwgZmlsbCA9IHRpcG8pKSArDQogICAgICAgICAgZ2VvbV9jb2woYWxwaGEgPSAwLjg1LCB3aWR0aCA9IDAuNykgKw0KICAgICAgICAgIA0KICAgICAgICAgICMgRXRpcXVldGFzIGRlIFNoYW5ub24gY29uIHZhbG9yIGV4cG9uZW5jaWFsDQogICAgICAgICAgZ2VvbV90ZXh0KA0KICAgICAgICAgICAgYWVzKGxhYmVsID0gc3ByaW50ZigiJS4yZiAoJS4xZikiLCBIX3NoYW5ub24sIGV4cChIX3NoYW5ub24pKSwgeSA9IEhfc2hhbm5vbiAqIDAuNSksIA0KICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLCANCiAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLA0KICAgICAgICAgICAgc2l6ZSA9IDIuOCAgIyBSZWR1Y2lkbyBsaWdlcmFtZW50ZQ0KICAgICAgICAgICkgKw0KICAgICAgICAgIA0KICAgICAgICAgICMgRXRpcXVldGFzIGRlIFBpZWxvdQ0KICAgICAgICAgIGdlb21fdGV4dCgNCiAgICAgICAgICAgIGFlcyhsYWJlbCA9IHNwcmludGYoIko9JS4yZiIsIHBpZWxvdSksIHkgPSBIX3NoYW5ub24gKyAwLjA1ICogbWF4SF9yYXRpbyksDQogICAgICAgICAgICBjb2xvciA9ICIjRDU1RTAwIiwNCiAgICAgICAgICAgIHNpemUgPSAyLjgsICAjIFJlZHVjaWRvDQogICAgICAgICAgICBoanVzdCA9IDANCiAgICAgICAgICApICsNCiAgICAgICAgICANCiAgICAgICAgICAjIEzDrW5lYSB5IHB1bnRvcyBkZSBQaWVsb3UNCiAgICAgICAgICBnZW9tX2xpbmUoDQogICAgICAgICAgICBhZXMoeSA9IHBpZWxvdSAqIG1heEhfcmF0aW8sIGdyb3VwID0gdGlwbyksIA0KICAgICAgICAgICAgY29sb3IgPSAiI0U2OUYwMCIsIA0KICAgICAgICAgICAgbGluZXdpZHRoID0gMS4yLCANCiAgICAgICAgICAgIGxpbmV0eXBlID0gInNvbGlkIg0KICAgICAgICAgICkgKw0KICAgICAgICAgIGdlb21fcG9pbnQoDQogICAgICAgICAgICBhZXMoeSA9IHBpZWxvdSAqIG1heEhfcmF0aW8pLCANCiAgICAgICAgICAgIGNvbG9yID0gIiNENTVFMDAiLCANCiAgICAgICAgICAgIHNpemUgPSAzLCANCiAgICAgICAgICAgIHNoYXBlID0gMTgNCiAgICAgICAgICApICsNCiAgICAgICAgICANCiAgICAgICAgICAjIENvbmZpZ3VyYWNpw7NuIGRlbCBncsOhZmljbw0KICAgICAgICAgIGZhY2V0X3dyYXAoDQogICAgICAgICAgICB+IHRpcG8sIA0KICAgICAgICAgICAgc2NhbGVzID0gImZyZWVfeSIsIA0KICAgICAgICAgICAgbmNvbCA9IDEsDQogICAgICAgICAgICBzdHJpcC5wb3NpdGlvbiA9ICJ0b3AiDQogICAgICAgICAgKSArDQogICAgICAgICAgY29vcmRfZmxpcCgpICsNCiAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgICAgICAgICBuYW1lID0gIsONbmRpY2UgZGUgU2hhbm5vbiAoSCkiLA0KICAgICAgICAgICAgc2VjLmF4aXMgPSBzZWNfYXhpcygNCiAgICAgICAgICAgICAgfiAuIC8gbWF4SF9yYXRpbywgDQogICAgICAgICAgICAgIG5hbWUgPSAiw41uZGljZSBkZSBQaWVsb3UgKEopIiwNCiAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKQ0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjE1KSkNCiAgICAgICAgICApICsNCiAgICAgICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKA0KICAgICAgICAgICAgIk1heW9yIGRpdmVyc2lkYWQgKFRvcCAxMCkiID0gIiMxYjllNzciLCANCiAgICAgICAgICAgICJNZW5vciBkaXZlcnNpZGFkIChCb3R0b20gMTApIiA9ICIjZDk1ZjAyIg0KICAgICAgICAgICkpICsNCiAgICAgICAgICBsYWJzKA0KICAgICAgICAgICAgdGl0bGUgPSAiRGl2ZXJzaWRhZCBkZSBlc3RhZG9zIGRlIGN1bG1pbmFjacOzbiBkZSBwcm95ZWN0b3MiLA0KICAgICAgICAgICAgc3VidGl0bGUgPSAiQ29tdW5hcyBjb24gbWF5b3IgeSBtZW5vciBkaXZlcnNpZGFkIGVuIGVzdGFkb3MgZGUgcHJveWVjdG9zIChSYXRpbyBBQ0EpIiwNCiAgICAgICAgICAgIHggPSAiQ29tdW5hIChJRCAtIE5vbWJyZSkiLA0KICAgICAgICAgICAgY2FwdGlvbiA9ICJGdWVudGU6IEVsYWJvcmFjacOzbiBwcm9waWEgLSBQcm95ZWN0b3MgQUNBICgyMDIyLTIwMjUpXG5Ob3RhOiBCYXJyYXMgPSBTaGFubm9uIChIKSBjb24gdmFsb3IgZXhwb25lbmNpYWwsIEzDrW5lYSA9IFBpZWxvdSAoSikiDQogICAgICAgICAgKSArDQogICAgICAgICAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMSkgKyAgIyBCYXNlIHNpemUgcmVkdWNpZG8NCiAgICAgICAgICB0aGVtZSgNCiAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0LCBoanVzdCA9IDAuNSksICAjIFTDrXR1bG8gbcOhcyBwZXF1ZcOxbw0KICAgICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEsIGNvbG9yID0gImdyYXkzMCIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4ociA9IDE1KSksDQogICAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAxMCkpLA0KICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCAgIyBUZXh0byBkZWwgZWplIFkgbcOhcyBwZXF1ZcOxbw0KICAgICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTEsIGNvbG9yID0gIndoaXRlIiksDQogICAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTI1IiwgY29sb3IgPSBOQSksDQogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgICAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSwNCiAgICAgICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDEsIDIsIDEsIDEsICJjbSIpICAjIE1hcmdlbiBkZXJlY2hvIGF1bWVudGFkbw0KICAgICAgICAgICkNCg0KICAgICAgICAjIEd1YXJkYXIgY29uIGRpbWVuc2lvbmVzIGVzcGVjw61maWNhcw0KICAgICAgICBnZ3NhdmUoInJhdGlvX2RpdmVyc2l0eV9wbG90LnBuZyIsIHJhdGlvX3Bsb3QsIHdpZHRoID0gMTQsIGhlaWdodCA9IDEwLCBkcGkgPSAzMDApDQogICAgICAgIHByaW50KHJhdGlvX3Bsb3QpDQogICAgICAgIA0KICMgQ3JlYXIgZ3LDoWZpY28gaW50ZXJhY3Rpdm8gcGFyYSBkaXZlcnNpZGFkIGRlIFJhdGlvIEFDQSAoVG9wL0JvdHRvbSkgY29uIGVee0gnfSB5IGFqdXN0ZXMgZGUgcHJlc2VudGFjacOzbg0KIyBOb3RhOiBhc3VtZSBxdWUgZGZfcmF3IHkgY29tbXVuZV9tYXAgeWEgZXhpc3RlbiAoY29tbyBlbiB0dSBjaHVuayBhbnRlcmlvcikuDQoNCiMgLS0tIDEuIFByZXBhcmFyIGRhdG9zIChyZWNyZWEgZWwgcHJvY2VkaW1pZW50byBkZSByYXRpbyB5IGNhbGN1bGEgZV57SCd9KQ0KZGZfcmF0aW9fY2xlYW4gPC0gZGZfcmF3ICU+JSANCiAgZmlsdGVyKCFpcy5uYShSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPKSkgJT4lICANCiAgbXV0YXRlKA0KICAgIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8gPSBmYWN0b3IoDQogICAgICBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPLA0KICAgICAgbGV2ZWxzID0gMTo0LA0KICAgICAgbGFiZWxzID0gYygiTVVZIEJBSkEiLCAiQkFKQSIsICJNRURJQSIsICJBTFRBIikNCiAgICApDQogICkNCg0KZGZfcmF0aW9fd2lkZSA8LSBkZl9yYXRpb19jbGVhbiAlPiUNCiAgZ3JvdXBfYnkoSURfQ09NVU5BLCBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPKSAlPiUNCiAgc3VtbWFyaXNlKG4gPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBjb21wbGV0ZShJRF9DT01VTkEsIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIGZpbGwgPSBsaXN0KG4gPSAwKSkgJT4lDQogIHBpdm90X3dpZGVyKA0KICAgIG5hbWVzX2Zyb20gPSBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPLCANCiAgICB2YWx1ZXNfZnJvbSA9IG4sIA0KICAgIG5hbWVzX3ByZWZpeCA9ICJyYXRpb18iDQogICkNCg0KIyBBc2VndXJhciBjb2x1bW5hcyByYXRpbw0KcmF0aW9fY29scyA8LSBjKCJyYXRpb19NVVkgQkFKQSIsICJyYXRpb19CQUpBIiwgInJhdGlvX01FRElBIiwgInJhdGlvX0FMVEEiKQ0KZm9yIChjb2wgaW4gcmF0aW9fY29scykgew0KICBpZiAoIWNvbCAlaW4lIG5hbWVzKGRmX3JhdGlvX3dpZGUpKSBkZl9yYXRpb193aWRlW1tjb2xdXSA8LSAwDQp9DQoNCmRpdl9yYXRpbyA8LSBkZl9yYXRpb193aWRlICU+JQ0KICBsZWZ0X2pvaW4oY29tbXVuZV9tYXAsIGJ5ID0gIklEX0NPTVVOQSIpICU+JQ0KICBtdXRhdGUobl9wcm95ZWN0b3NfcmF0aW8gPSByb3dTdW1zKHNlbGVjdCguLCBhbGxfb2YocmF0aW9fY29scykpKSkgJT4lDQogIHsNCiAgICBjbnRzIDwtIHNlbGVjdCguLCBhbGxfb2YocmF0aW9fY29scykpDQogICAgdGliIDwtIHNlbGVjdCguLCBJRF9DT01VTkEsIENPTVVOQSwgbl9wcm95ZWN0b3NfcmF0aW8pDQogICAgSCA8LSB2ZWdhbjo6ZGl2ZXJzaXR5KGNudHMsIGluZGV4ID0gInNoYW5ub24iKQ0KICAgIHJpY2hlc3NlIDwtIHJvd1N1bXMoY250cyA+IDApDQogICAgSiA8LSBpZmVsc2UocmljaGVzc2UgPiAwLCBIIC8gbG9nKHJpY2hlc3NlKSwgTkFfcmVhbF8pDQogICAgYmluZF9jb2xzKHRpYiwgSF9zaGFubm9uID0gSCwgcGllbG91ID0gSikNCiAgfSAlPiUNCiAgbXV0YXRlKENPTVVOQV9JRF9OT01CUkUgPSBwYXN0ZShJRF9DT01VTkEsICItIiwgQ09NVU5BKSkgJT4lDQogICMgY2FsY3VsYXIgZXhwb25lbmNpYWwgcGFyYSBpbnRlcnByZXRhY2nDs24NCiAgbXV0YXRlKGVfSCA9IHJvdW5kKGV4cChIX3NoYW5ub24pLCAyKSkNCg0KIyBUb3AgLyBCb3R0b20gMTANCnRvcDEwX3JhdGlvIDwtIGRpdl9yYXRpbyAlPiUgYXJyYW5nZShkZXNjKEhfc2hhbm5vbikpICU+JSBzbGljZSgxOjEwKSAlPiUgDQogIHNlbGVjdChDT01VTkFfSURfTk9NQlJFLCBuX3Byb3llY3Rvc19yYXRpbywgSF9zaGFubm9uLCBwaWVsb3UsIGVfSCkNCg0KYm90dG9tMTBfcmF0aW8gPC0gZGl2X3JhdGlvICU+JSBhcnJhbmdlKEhfc2hhbm5vbikgJT4lIHNsaWNlKDE6MTApICU+JSANCiAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIG5fcHJveWVjdG9zX3JhdGlvLCBIX3NoYW5ub24sIHBpZWxvdSwgZV9IKQ0KDQp0YWJsYV9leHRyZW1vc19yYXRpbyA8LSBiaW5kX3Jvd3MoDQogIHRvcDEwX3JhdGlvICAlPiUgbXV0YXRlKHRpcG8gPSAiTWF5b3IgZGl2ZXJzaWRhZCAoVG9wIDEwKSIpICAlPiUgcmVuYW1lKENPTVVOQSA9IENPTVVOQV9JRF9OT01CUkUpLA0KICBib3R0b20xMF9yYXRpbyAlPiUgbXV0YXRlKHRpcG8gPSAiTWVub3IgZGl2ZXJzaWRhZCAoQm90dG9tIDEwKSIpICU+JSByZW5hbWUoQ09NVU5BID0gQ09NVU5BX0lEX05PTUJSRSkNCikgJT4lDQogICMgY3JlYXIgdGV4dG8gcGFyYSB0b29sdGlwDQogIG11dGF0ZSgNCiAgICB0b29sdGlwID0gcGFzdGUwKA0KICAgICAgIkNvbXVuYTogIiwgQ09NVU5BLCAiXG4iLA0KICAgICAgIlByb3llY3RvczogIiwgbl9wcm95ZWN0b3NfcmF0aW8sICJcbiIsDQogICAgICAiSCA9ICIsIHNwcmludGYoIiUuM2YiLCBIX3NoYW5ub24pLCAiICB8ICBlXntIfSA9ICIsIHNwcmludGYoIiUuMmYiLCBlX0gpLCAiXG4iLA0KICAgICAgIkogPSAiLCBzcHJpbnRmKCIlLjNmIiwgcGllbG91KQ0KICAgICkNCiAgKQ0KDQojIC0tLSAyLiBHcsOhZmljbyAoZ2dwbG90KSBjb24gYWp1c3RlIHBhcmEgZXZpdGFyIGNsaXBwaW5nIHkgZXNwYWNpbyBwYXJhIGV0aXF1ZXRhcyAtLS0NCm1heEhfcmF0aW8gPC0gbWF4KHRhYmxhX2V4dHJlbW9zX3JhdGlvJEhfc2hhbm5vbiwgbmEucm0gPSBUUlVFKQ0KbWF4SF9wbG90IDwtIG1heEhfcmF0aW8gKiAxLjMNCg0KcmF0aW9fcGxvdDIgPC0gZ2dwbG90KHRhYmxhX2V4dHJlbW9zX3JhdGlvLCBhZXMoeCA9IHJlb3JkZXIoQ09NVU5BLCBIX3NoYW5ub24pLCB5ID0gSF9zaGFubm9uLCBmaWxsID0gdGlwbykpICsNCiAgZ2VvbV9jb2woYWVzKHRleHQgPSB0b29sdGlwKSwgYWxwaGEgPSAwLjg4LCB3aWR0aCA9IDAuNzIpICsNCiAgIyBldGlxdWV0YXMgSCArIGVeSCBkZW50cm8gZGUgbGEgYmFycmEgKHBvc2ljaW9uYWRvIG3DoXMgY2VyY2EgZGVsIGNlbnRybyBwYXJhIG5vIHNvbGFwYXJzZSkNCiAgZ2VvbV90ZXh0KGFlcyh5ID0gSF9zaGFubm9uICogMC40NSwgbGFiZWwgPSBzcHJpbnRmKCIlLjJmICglLjFmKSIsIEhfc2hhbm5vbiwgZV9IKSksDQogICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIGZvbnRmYWNlID0gImJvbGQiLCBzaXplID0gMi44KSArDQogICMgUGllbG91OiB0ZXh0byBsaWdlcmFtZW50ZSBwb3IgZW5jaW1hIGRlIGxhIGJhcnJhICh5ID0gSCArIG9mZnNldCkNCiAgZ2VvbV90ZXh0KGFlcyh5ID0gSF9zaGFubm9uICsgMC4wNCAqIG1heEhfcGxvdCwgbGFiZWwgPSBzcHJpbnRmKCJKPSUuMmYiLCBwaWVsb3UpKSwNCiAgICAgICAgICAgIGNvbG9yID0gIiNENTVFMDAiLCBzaXplID0gMi44LCBoanVzdCA9IDApICsNCiAgIyBMaW5lYSB5IHB1bnRvcyBkZSBQaWVsb3UgZXNjYWxhZGENCiAgZ2VvbV9saW5lKGFlcyh5ID0gcGllbG91ICogbWF4SF9wbG90LCBncm91cCA9IHRpcG8pLCBjb2xvciA9ICIjRTY5RjAwIiwgbGluZXdpZHRoID0gMS4xKSArDQogIGdlb21fcG9pbnQoYWVzKHkgPSBwaWVsb3UgKiBtYXhIX3Bsb3QpLCBjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgpICsNCiAgZmFjZXRfd3JhcCh+IHRpcG8sIHNjYWxlcyA9ICJmcmVlX3kiLCBuY29sID0gMSwgc3RyaXAucG9zaXRpb24gPSAidG9wIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbmFtZSA9ICLDjW5kaWNlIGRlIFNoYW5ub24gKEgpIiwNCiAgICBsaW1pdHMgPSBjKDAsIG1heEhfcGxvdCksDQogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyBtYXhIX3Bsb3QsIG5hbWUgPSAiw41uZGljZSBkZSBQaWVsb3UgKEopIiwgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4wMSkpDQogICkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNYXlvciBkaXZlcnNpZGFkIChUb3AgMTApIiA9ICIjMWI5ZTc3IiwgIk1lbm9yIGRpdmVyc2lkYWQgKEJvdHRvbSAxMCkiID0gIiNkOTVmMDIiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpdmVyc2lkYWQgZGUgZXN0YWRvcyBkZSBjdWxtaW5hY2nDs24gZGUgcHJveWVjdG9zIChSYXRpbyBBQ0EpIiwNCiAgICBzdWJ0aXRsZSA9ICJUb3AgMTAgbWF5b3IgeSBtZW5vciBkaXZlcnNpZGFkIHwgQmFycmFzOiBIIChjb24gZV57SH0pIHwgTMOtbmVhOiBKIiwNCiAgICB4ID0gIkNvbXVuYSAoSUQgLSBOb21icmUpIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSAtIFByb3llY3RvcyBBQ0EgKDIwMjItMjAyNSkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDExKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0LCBoanVzdCA9IDAuNSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEsIGNvbG9yID0gImdyYXkzMCIsIGhqdXN0ID0gMC41KSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEwLCBjb2xvciA9ICJ3aGl0ZSIpLA0KICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MjUiLCBjb2xvciA9IE5BKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMSwgImxpbmVzIiksDQogICAgIyBtw6FyZ2VuZXMgeSBjbGlwIG9mZiBwYXJhIHF1ZSBldGlxdWV0YXMgbm8gc2UgY29ydGVuDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDEyLCByID0gMTIwLCBiID0gMTIsIGwgPSAxODApLA0KICAgIHBhbmVsLmNsaXAgPSAib2ZmIg0KICApDQoNCiMgLS0tIDMuIENvbnZlcnRpciBhIHBsb3RseSBjb24gdGFtYcOxbyBmaWpvIDE2MDB4ODAwIHkgbW9zdHJhciAtLS0NCnBsb3RseV9maXhfc2l6ZSA8LSBmdW5jdGlvbihnZ29iaiwgd2lkdGggPSAxNjAwLCBoZWlnaHQgPSA4MDAsIG1hcmdpbiA9IGxpc3QobCA9IDIwMCwgciA9IDEyMCwgYiA9IDEwMCwgdCA9IDkwKSkgew0KICBwIDwtIGdncGxvdGx5KGdnb2JqLCB0b29sdGlwID0gInRleHQiKQ0KICBwIDwtIHAgJT4lIGxheW91dChhdXRvc2l6ZSA9IEZBTFNFLCB3aWR0aCA9IHdpZHRoLCBoZWlnaHQgPSBoZWlnaHQsIG1hcmdpbiA9IG1hcmdpbikNCiAgcCA8LSBwICU+JSBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBUUlVFLCBtb2RlQmFyQnV0dG9uc1RvQWRkID0gbGlzdCgidG9JbWFnZSIsICJ6b29tMmQiLCAicmVzZXRTY2FsZTJkIikpDQogIHJldHVybihwKQ0KfQ0KDQpyYXRpb19wbG90bHkgPC0gcGxvdGx5X2ZpeF9zaXplKHJhdGlvX3Bsb3QyLCB3aWR0aCA9IDE2MDAsIGhlaWdodCA9IDgwMCkNCnJhdGlvX3Bsb3RseQ0KYGBgDQogIA0KDQoqKkRpdmVyc2lkYWQgZGUgZXN0YWRvcyBkZSBjdWxtaW5hY2nDs24gKFJhdGlvIEFDQSkqKg0KDQoNCiAgRWwgw61uZGljZSBkZSBTaGFubm9uIGFwbGljYWRvIGFsIFJhdGlvIEFDQSBzaW50ZXRpemEgY3XDoW4gZGlzcGVyc29zIG8gY29uY2VudHJhZG9zIGVzdMOhbiBsb3MgcmVzdWx0YWRvcyBkZSBsb3MgcHJveWVjdG9zIGRlbnRybyBkZSBjYWRhIGNvbXVuYS4gVmFsb3JlcyBhbHRvcyBkZSBIJyAocG9yIGVqZW1wbG8sIENvbXVuYSBQcsOzY2VyIEpvc8OpIEbDqWxpeCBSaWJhcywgSCcgPSAxLjMxMSDihpIgKmU8c3VwPkgnPC9zdXA+KiDiiYggKiozLjcxKiopIGluZGljYW4gcXVlIGxhIGNvbXVuYSBjb25jZW50cmEgcmVzdWx0YWRvcyBlbiBjYXNpIDQgY2F0ZWdvcsOtYXMgZGlzdGludGFzIGRlIGVmZWN0aXZpZGFkLCBsbyBxdWUgcmVmbGVqYSBoZXRlcm9nZW5laWRhZCBvcGVyYXRpdmE6IHB1ZWRlIHNlciBnZXN0acOzbiBhY3RpdmEgeSB2YXJpYWRhIG8gZWplY3VjacOzbiBlcnLDoXRpY2EuIFZhbG9yZXMgbWVkaW9zIChIJyDiiYggMC42Mzcg4oaSICplPHN1cD5IJzwvc3VwPiog4omIICoqMS44OSoqKSBtdWVzdHJhbiBxdWUgbGEgbWF5b3LDrWEgZGUgY29tdW5hcyBvcGVyYW4gY29uIG1lbm9zIGRlIDIgZXN0YWRvcyBlZmVjdGl2b3MsIGxvIHF1ZSBzdWdpZXJlIGNvbmNlbnRyYWNpw7NuIGRlIHJlc3VsdGFkb3MgKGhhYml0dWFsbWVudGUgZW4g4oCcTVVZIEJBSkEvQkFKQeKAnSkuIFZhbG9yZXMgbnVsb3MgKEjigLIgPSAwKSBlcXVpdmFsZW4gYSAxIGVzdGFkbyBlZmVjdGl2bzogc2l0dWFjacOzbiBjcsOtdGljYSBxdWUgZGVtYW5kYSByZWluZ2VuaWVyw61hIHVyZ2VudGUuDQoNCiAgRWwgaGFsbGF6Z28gbcOhcyBhbGFybWFudGUgZXMgbGEgZXhpc3RlbmNpYSBkZSBvY2hvICg4KSBjb211bmFzIGNvbiBkaXZlcnNpZGFkIG51bGEgKEgnID0gMCwwMDApLCBkb25kZSBlbCAxMDAlIGRlIHN1cyBwcm95ZWN0b3MgY29tcGFydGVuIGVsIG1pc21vIGVzdGFkbyBkZSBjdWxtaW5hY2nDs24uIERhZG8gZWwgY29udGV4dG8gc29jaW8gaW5zdGl0dWNpb25hbCB2ZW5lem9sYW5vLCBlcyBhbHRhbWVudGUgcHJvYmFibGUgcXVlIGVsIGVzdGFkbyBjb23Dum4gc2VhICJNVVkgQkFKQSIgbyAiQkFKQSIuIEVzdG8gY29uZmlybWEgZGUgbWFuZXJhIGNvbnR1bmRlbnRlIGxhIEhpcMOzdGVzaXMgNCAoRmFsbGEgRXN0cnVjdHVyYWwgeSBEZXNjb25leGnDs24pLiBDb211bmFzIGNvbW8gKlVuacOzbiBkZSBDaMOhdmV6KiB5ICpQZW5zYW1pZW50byBDYW1wZXNpbm8qIHJlcHJlc2VudGFuIGVsIGNhc28gbcOhcyBjcsOtdGljbzogZWwgaW5zdHJ1bWVudG8gZGUgbGFzIEFDQSBoYSBmYWxsYWRvIHBvciBjb21wbGV0byBlbiBnZW5lcmFyIGF2YW5jZXMgdGFuZ2libGVzLCBldmlkZW5jaWFuZG8gdW5hIHBhcsOhbGlzaXMgdG90YWwgZGUgbGEgZ2VzdGnDs24gcHJveWVjdGl2YSB5YSBzZWEgcG9yIGVsIGFiYW5kb25vIGluc3RpdHVjaW9uYWwgbyBsYSBvYnN0aW5hY2nDs24gZW4gbWFjcm9wcm95ZWN0b3MgaW52aWFibGVzLg0KDQoqKlJlZ2xhcyBvcGVyYXRpdmFzIChyZXN1bWVuKToqKiAgDQotICplPHN1cD5IJzwvc3VwPiDiiYggMSog4oaSIGludGVydmVuY2nDs24gdXJnZW50ZSB5IHJlaW5nZW5pZXLDrWEuICANCi0gKjEgPCBlPHN1cD5IJzwvc3VwPiA8IDMqIOKGkiBjb25zb2xpZGFjacOzbiB5IGF1ZGl0b3LDrWEgZGUgcHJvY2Vzb3MuICANCi0gKmU8c3VwPkgnPC9zdXA+IOKJpSAzKiDihpIgYW7DoWxpc2lzIGN1YWxpdGF0aXZvIHBhcmEgZGlzdGluZ3VpciBjb21wbGVqaWRhZCBnZXN0aW9uYWJsZSB2cy4gZnJhZ21lbnRhY2nDs24gaW5zdGl0dWNpb25hbC4NCiIpDQoNCg0KXFsNCkgnID0gLVxzdW1fe2k9MX1ee1N9IHBfaSBcbG4ocF9pKQ0KXF0NCg0KXFsNClx0ZXh0e07Dum1lcm8gZWZlY3Rpdm99ID0gZV57SCd9DQpcXQ0KDQoqKkludGVycHJldGFjacOzbiBwb3IgY29tdW5hcyoqDQoNCi0gKipDb211bmEgUHLDs2NlciBKb3PDqSBGw6lsaXggUmliYXMqKiDigJQgXChIJyA9IDEuMzExXCkg4oaSIFwoZV57SCd9IFxhcHByb3ggMy43MVwpIOKAlCA5IHByb3llY3Rvcy4gQWx0YSBoZXRlcm9nZW5laWRhZDogc2UgY29tcG9ydGEgY29tbyBzaSB0dXZpZXJhICoq4omIIDQgdGlwb3MgZGUgcmVzdWx0YWRvKiogKGRlc2RlIHByb3llY3RvcyBjdWxtaW5hZG9zIGhhc3RhIG5vIGNvbnNpZGVyYWRvcyk7IHJlcXVpZXJlIGNvb3JkaW5hY2nDs24gbXVsdGlzZWN0b3JpYWwuICANCg0KLSAqKkNvbXVuYSBMYXMgSGVyb8OtbmFzIGRlIE3DqXJpZGEqKiDigJQgXChIJyA9IDEuMDU1XCkg4oaSIFwoZV57SCd9IFxhcHByb3ggMi44N1wpIOKAlCA1IHByb3llY3Rvcy4gRGl2ZXJzaWRhZCBub3RhYmxlOiDiiYggMyB0aXBvcyBkZSByZXN1bHRhZG87IGNvbnZpZW5lIGludmVzdGlnYXIgcXXDqSBleHBsaWNhIGxhIG1lemNsYSBkZSDDqXhpdG9zIHkgZnJhY2Fzb3MuICANCg0KLSAqKkNvbXVuYSBNdWN1asO6bioqIOKAlCBcKEgnID0gMS4wMTFcKSDihpIgXChlXntIJ30gXGFwcHJveCAyLjc1XCkg4oCUIDYgcHJveWVjdG9zLiBDb21wbGVqaWRhZCBtb2RlcmFkYTog4omIIDLigJMzIHRpcG9zIGVmZWN0aXZvczsgaGFjZXIgdW4gYW7DoWxpc2lzIGN1YWxpdGF0aXZvLiAgDQoNCi0gKipDb211bmEgQWx0byBkZSBsYSBDYXJib25lcmEqKiDigJQgXChIJyA9IDEuMDExXCkg4oaSIFwoZV57SCd9IFxhcHByb3ggMi43NVwpIOKAlCA2IHByb3llY3Rvcy4gVmFyaWFiaWxpZGFkIHNpbWlsYXIgYSBNdWN1asO6bjsgcHJpb3JpemFyIGNvb3JkaW5hY2nDs24gaW5zdGl0dWNpb25hbC4gDQoNCi0gKipDb211bmEgTWFudWVsaXRhIFPDoWVueioqIOKAlCBcKEgnID0gMS4wOTlcKSDihpIgXChlXntIJ30gXGFwcHJveCAzLjAwXCkg4oCUIDMgcHJveWVjdG9zLiBBbHRhIGRpdmVyc2lkYWQgcGVzZSBhbCBiYWpvIG7Dum1lcm8gZGUgcHJveWVjdG9zOyBpbnZlc3RpZ2FyIGxhIGNhdXNhIGRlIGxhIHZhcmlhYmlsaWRhZC4gIA0KLSAqKkNvbXVuYSBFbCBQYXNvIGRlIEJvbMOtdmFyIDE4MTMqKiDigJQgXChIJyA9IDAuNjczXCkg4oaSIFwoZV57SCd9IFxhcHByb3ggMS45NlwpIOKAlCA1IHByb3llY3Rvcy4gRGl2ZXJzaWRhZCBtb2RlcmFkYTog4omIIDIgdGlwb3MgZGUgcmVzdWx0YWRvOyBidWVuIGNhbmRpZGF0byBwYXJhIGludGVydmVuY2lvbmVzIGZvY2FsZXMuDQoNCi0gKipDb211bmEgRXRlcm5vIEdpZ2FudGUqKiDigJQgXChIJyA9IDAuNjkzXCkg4oaSIFwoZV57SCd9IFxhcHByb3ggMi4wMFwpIOKAlCAyIHByb3llY3Rvcy4gUmVzdWx0YWRvcyBjb25jZW50cmFkb3MgZW4gfjIgY2xhc2VzOyBhY2Npb25lcyBwdW50dWFsZXMgcHVlZGVuIHRlbmVyIGFsdG8gaW1wYWN0by4gDQoNCi0gKipDb211bmEgVW5pw7NuIGRlIENow6F2ZXoqKiDigJQgXChIJyA9IDAuMDAwXCkg4oaSIFwoZV57SCd9ID0gMS4wMFwpIOKAlCAzIHByb3llY3Rvcy4gRGl2ZXJzaWRhZCBudWxhOiB0b2RvcyBsb3MgcHJveWVjdG9zIGNvbXBhcnRlbiBlbCBtaXNtbyBlc3RhZG8g4oaSICoqaW50ZXJ2ZW5jacOzbiB1cmdlbnRlKiogKHJlaW5nZW5pZXLDrWEgeSBhcG95byB0w6ljbmljbykuDQoNCg0KDQojIyAqKkFwbGljYWNpw7NuIGRlIG5vcm1hbGlkYWQqKg0KDQogIFBhcmEgZGV0ZXJtaW5hciBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBkZSBlc3R1ZGlvLCBlcyBmdW5kYW1lbnRhbCBzZWxlY2Npb25hciBsYSBwcnVlYmEgZXN0YWTDrXN0aWNhIGFkZWN1YWRhLiBMYSBlbGVjY2nDs24gZW50cmUgdW4gbcOpdG9kbyBwYXJhbcOpdHJpY28gKGNvbW8gZWwgY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIGRlIFBlYXJzb24pIHkgdW5vIG5vIHBhcmFtw6l0cmljbyAoY29tbyBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4pIGRlcGVuZGUgY3J1Y2lhbG1lbnRlIGRlIHNpIGxvcyBkYXRvcyBjdW1wbGVuIGNvbiBlbCBzdXB1ZXN0byBkZSBub3JtYWxpZGFkLiBMYSB2aW9sYWNpw7NuIGRlIGVzdGUgc3VwdWVzdG8gcHVlZGUgbGxldmFyIGEgY29uY2x1c2lvbmVzIGVycsOzbmVhcywgYWZlY3RhbmRvIGxhIHZhbGlkZXogZGVsIGFuw6FsaXNpcyBlc3RhZMOtc3RpY28uIFBvciBlbGxvLCBhbnRlcyBkZSBwcm9jZWRlciBjb24gZWwgYW7DoWxpc2lzIGNvcnJlbGFjaW9uYWwsIHNlIHJlYWxpesOzIHVuYSBwcnVlYmEgZGUgYm9uZGFkIGRlIGFqdXN0ZSBwYXJhIGV2YWx1YXIgbGEgZGlzdHJpYnVjacOzbiBkZSBsYXMgdmFyaWFibGVzIGNsYXZlIGRlIGxhIGludmVzdGlnYWNpw7NuLg0KDQogIFBhcmEgZXZhbHVhciBsYSBub3JtYWxpZGFkIGRlIGxvcyBkYXRvcywgc2Ugc2VsZWNjaW9uw7MgbGEgcHJ1ZWJhIGRlIFNoYXBpcm8tV2lsay4gRXN0YSBlbGVjY2nDs24gc2UgZnVuZGFtZW50YSBlbiBzdSByZWNvbm9jaWRhIHBvdGVuY2lhIHBhcmEgZGV0ZWN0YXIgZGVzdmlhY2lvbmVzIGRlIGxhIG5vcm1hbGlkYWQgKEFyY2UgJiBSb3NhbGVzLCAyMDE1KSwgc2kgYmllbiBlc3RhIHNlIHJlc3RyaW5nacOzIG9yaWdpbmFsbWVudGUgcGFyYSB0YW1hw7FvcyBkZSBtdWVzdHJhIHBlcXVlw7FhIChuIDwgNTApLCBlc3RhIHBydWViYSBlcyBsYSBtw6FzIHBvdGVudGUgeSBjb23Dum4gc3UgdXNvIGVuIGVsIGFuw6FsaXNpcyBkZSBub3JtYWxpZGFkIGRlIGxvcyBkYXRvcyBkZSBjdWFscXVpZXIgZXN0dWRpby4NCiAgDQpgYGB7cn0NCiMjIFByZXBhcmFjacOzbiBkZSBsb3MgZGF0b3MNCiAjIEVsaW1pbmFyIHZhbG9yZXMgbnVsb3Mgc2kgZXMgbmVjZXNhcmlvDQpkZl9jbGVhbiA8LSBkZl9yYXcgJT4lIGZpbHRlcighaXMubmEobl9wcm95ZWN0b3MpICYgIWlzLm5hKFBMQVpPUykgJiAhaXMubmEoQ0xBU0lGSUNBQ0lPTl9ERUxfUFJPWUVDVE8pJiAhaXMubmEoUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETykmICFpcy5uYShDbGFzaWZpY2FjaW9uX0FjdG9yZXNfaW5zdGl0dWNpb25hbGVzKSYgIWlzLm5hKFRJUE9MT0dJQV9DRkdfTlVNKSYgIWlzLm5hKEdPQkVSTkFDSU9OX05VTSkpDQoNCiMgRnVuY2nDs24gcGFyYSBjcmVhciB1biBwYW5lbCBkZSBkaWFnbsOzc3RpY28gZGUgbm9ybWFsaWRhZA0KY3JlYXRlX25vcm1hbGl0eV9kaWFnbm9zdGljIDwtIGZ1bmN0aW9uKGRhdGEsIHZhcmlhYmxlLCB2YXJpYWJsZV9uYW1lKSB7DQogICMgRGF0b3MgcGFyYSBsYSB2YXJpYWJsZQ0KICB4IDwtIGRhdGFbW3ZhcmlhYmxlXV0NCiAgDQogICMgSGlzdG9ncmFtYSBjb24gY3VydmEgZGUgZGVuc2lkYWQNCiAgcDEgPC0gZ2dwbG90KGRhdGEsIGFlc19zdHJpbmcoeCA9IHZhcmlhYmxlKSkgKw0KICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW5zID0gMzAsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKw0KICAgIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiLCBsaW5ld2lkdGggPSAxKSArDQogICAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgDQogICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KG1lYW4gPSBtZWFuKHgsIG5hLnJtID0gVFJVRSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QgPSBzZCh4LCBuYS5ybSA9IFRSVUUpKSwNCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmx1ZSIsIGxpbmV3aWR0aCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoIkhpc3RvZ3JhbWEgeSBEZW5zaWRhZCAtIiwgdmFyaWFibGVfbmFtZSksDQogICAgICAgICB4ID0gdmFyaWFibGVfbmFtZSwgeSA9ICJEZW5zaWRhZCIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkNCiAgDQogICMgUS1RIHBsb3QNCiAgcDIgPC0gZ2dwbG90KGRhdGEsIGFlcyhzYW1wbGUgPSB4KSkgKw0KICAgIHN0YXRfcXEoKSArDQogICAgc3RhdF9xcV9saW5lKGNvbG9yID0gInJlZCIpICsNCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoIlEtUSBQbG90IC0iLCB2YXJpYWJsZV9uYW1lKSkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KICANCiAgIyBDb21iaW5hciBsb3MgZ3LDoWZpY29zDQogIGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKHAxLCBwMiwgbmNvbCA9IDIpDQp9DQoNCiMgTGlzdGEgZGUgdmFyaWFibGVzIHBhcmEgYW5hbGl6YXINCnZhcmlhYmxlc190b19hbmFseXplIDwtIGxpc3QoDQogICJuX3Byb3llY3RvcyIgPSAiTsO6bWVybyBkZSBQcm95ZWN0b3MiLA0KICAiUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETyIgPSAiUmF0aW8gQUNBIiwNCiAgIlRJUE9MT0dJQV9DRkdfTlVNIiA9ICJUaXBvbG9nw61hIENGRyIsDQogICJHT0JFUk5BQ0lPTl9OVU0iID0gIkdvYmVybmFjacOzbiIsDQogICJQTEFaT1MiID0gIlBsYXpvcyIsDQogICJDTEFTSUZJQ0FDSU9OX0RFTF9QUk9ZRUNUTyIgPSAiQ2xhc2lmaWNhY2nDs24gZGVsIFByb3llY3RvIiwNCiAgIkNsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMiID0gIkFjdG9yZXMgSW5zdGl0dWNpb25hbGVzIg0KKQ0KDQojIENyZWFyIHVuIHBhbmVsIHBhcmEgY2FkYSB2YXJpYWJsZQ0KZm9yKHZhciBpbiBuYW1lcyh2YXJpYWJsZXNfdG9fYW5hbHl6ZSkpIHsNCiAgY2F0KCJcblxuQW7DoWxpc2lzIGRlIG5vcm1hbGlkYWQgcGFyYToiLCB2YXJpYWJsZXNfdG9fYW5hbHl6ZVtbdmFyXV0sICJcbiIpDQogIHByaW50KGNyZWF0ZV9ub3JtYWxpdHlfZGlhZ25vc3RpYyhkZl9jbGVhbiwgdmFyLCB2YXJpYWJsZXNfdG9fYW5hbHl6ZVtbdmFyXV0pKQ0KICANCiAgIyBJbXByaW1pciByZXN1bHRhZG9zIGRlbCB0ZXN0IGRlIFNoYXBpcm8tV2lsaw0KICBzd190ZXN0IDwtIHNoYXBpcm8udGVzdChkZl9jbGVhbltbdmFyXV0pDQogIGNhdCgiXG5UZXN0IGRlIFNoYXBpcm8tV2lsazpcbiIpDQogIGNhdCgiVyA9Iiwgcm91bmQoc3dfdGVzdCRzdGF0aXN0aWMsIDQpLCAiXG4iKQ0KICBjYXQoInAtdmFsdWUgPSIsIGZvcm1hdC5wdmFsKHN3X3Rlc3QkcC52YWx1ZSwgZGlnaXRzID0gNCksICJcbiIpDQogIGNhdCgiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiIpDQp9DQoNCiMgUHJlcGFyYXIgZWwgZXNwYWNpbyBwYXJhIG3Dumx0aXBsZXMgZ3LDoWZpY29zDQpwYXIobWZyb3cgPSBjKDIsIDQpKSAgIyAyIGZpbGFzIHggNCBjb2x1bW5hcyBwYXJhIGFjb21vZGFyIHRvZG9zIGxvcyBRLVEgcGxvdHMNCg0KIyBDcmVhciBRLVEgcGxvdHMgcGFyYSBjYWRhIHZhcmlhYmxlIGNvbiB0w610dWxvcyBkZXNjcmlwdGl2b3MNCnFxbm9ybShkZl9jbGVhbiRuX3Byb3llY3RvcywgbWFpbj0iUS1RIFBsb3Q6IE7CsCBQcm95ZWN0b3MiLA0KICAgICAgIGNvbCA9ICJibHVlIiwgcGNoID0gMTkpDQpxcWxpbmUoZGZfY2xlYW4kbl9wcm95ZWN0b3MsIGNvbCA9ICJyZWQiKQ0KDQpxcW5vcm0oZGZfY2xlYW4kUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETywgbWFpbj0iUS1RIFBsb3Q6IFJhdGlvIEFDQSIsDQogICAgICAgY29sID0gImdyZWVuNCIsIHBjaCA9IDE5KQ0KcXFsaW5lKGRmX2NsZWFuJFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIGNvbCA9ICJyZWQiKQ0KDQpxcW5vcm0oZGZfY2xlYW4kVElQT0xPR0lBX0NGR19OVU0sIG1haW49IlEtUSBQbG90OiBUaXBvbG9nw61hIENGRyIsDQogICAgICAgY29sID0gInB1cnBsZSIsIHBjaCA9IDE5KQ0KcXFsaW5lKGRmX2NsZWFuJFRJUE9MT0dJQV9DRkdfTlVNLCBjb2wgPSAicmVkIikNCg0KcXFub3JtKGRmX2NsZWFuJEdPQkVSTkFDSU9OX05VTSwgbWFpbj0iUS1RIFBsb3Q6IEdvYmVybmFjacOzbiIsDQogICAgICAgY29sID0gIm9yYW5nZSIsIHBjaCA9IDE5KQ0KcXFsaW5lKGRmX2NsZWFuJEdPQkVSTkFDSU9OX05VTSwgY29sID0gInJlZCIpDQoNCnFxbm9ybShkZl9jbGVhbiRQTEFaT1MsIG1haW49IlEtUSBQbG90OiBQbGF6b3MiLA0KICAgICAgIGNvbCA9ICJicm93biIsIHBjaCA9IDE5KQ0KcXFsaW5lKGRmX2NsZWFuJFBMQVpPUywgY29sID0gInJlZCIpDQoNCnFxbm9ybShkZl9jbGVhbiRDTEFTSUZJQ0FDSU9OX0RFTF9QUk9ZRUNUTywgbWFpbj0iUS1RIFBsb3Q6IENsYXNpZmljYWNpw7NuIiwNCiAgICAgICBjb2wgPSAiZGFya2dyZWVuIiwgcGNoID0gMTkpDQpxcWxpbmUoZGZfY2xlYW4kQ0xBU0lGSUNBQ0lPTl9ERUxfUFJPWUVDVE8sIGNvbCA9ICJyZWQiKQ0KDQpxcW5vcm0oZGZfY2xlYW4kQ2xhc2lmaWNhY2lvbl9BY3RvcmVzX2luc3RpdHVjaW9uYWxlcywgDQogICAgICAgbWFpbj0iUS1RIFBsb3Q6IEFjdG9yZXMgSW5zdGl0dWNpb25hbGVzIiwNCiAgICAgICBjb2wgPSAiZGFya2JsdWUiLCBwY2ggPSAxOSkNCnFxbGluZShkZl9jbGVhbiRDbGFzaWZpY2FjaW9uX0FjdG9yZXNfaW5zdGl0dWNpb25hbGVzLCBjb2wgPSAicmVkIikNCg0KIyBSZXN0YXVyYXIgbGEgY29uZmlndXJhY2nDs24gb3JpZ2luYWwgZGUgZ3LDoWZpY29zDQpwYXIobWZyb3cgPSBjKDEsIDEpKQ0KDQojIFJlc3VtZW4gZXN0YWTDrXN0aWNvIGRlIGxhcyBwcnVlYmFzIGRlIG5vcm1hbGlkYWQNCm5vcm1hbGl0eV9zdW1tYXJ5IDwtIGRhdGEuZnJhbWUoDQogIFZhcmlhYmxlID0gbmFtZXModmFyaWFibGVzX3RvX2FuYWx5emUpLA0KICBXX3N0YXRpc3RpYyA9IHNhcHBseShuYW1lcyh2YXJpYWJsZXNfdG9fYW5hbHl6ZSksIA0KICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHNoYXBpcm8udGVzdChkZl9jbGVhbltbeF1dKSRzdGF0aXN0aWMpLA0KICBwX3ZhbHVlID0gc2FwcGx5KG5hbWVzKHZhcmlhYmxlc190b19hbmFseXplKSwgDQogICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgc2hhcGlyby50ZXN0KGRmX2NsZWFuW1t4XV0pJHAudmFsdWUpDQopICU+JQ0KICBtdXRhdGUoDQogICAgTm9ybWFsaWRhZCA9IGlmZWxzZShwX3ZhbHVlIDwgMC4wNSwgIk5vIE5vcm1hbCIsICJOb3JtYWwiKSwNCiAgICBWYXJpYWJsZV9OYW1lID0gdW5saXN0KHZhcmlhYmxlc190b19hbmFseXplKQ0KICApDQoNCiMgTW9zdHJhciB0YWJsYSByZXN1bWVuDQprYWJsZShub3JtYWxpdHlfc3VtbWFyeSAlPiUgDQogICAgICAgIHNlbGVjdChWYXJpYWJsZV9OYW1lLCBXX3N0YXRpc3RpYywgcF92YWx1ZSwgTm9ybWFsaWRhZCksDQogICAgICBjb2wubmFtZXMgPSBjKCJWYXJpYWJsZSIsICJFc3RhZMOtc3RpY28gVyIsICJWYWxvciBwIiwgIkNvbmNsdXNpw7NuIiksDQogICAgICBjYXB0aW9uID0gIlJlc3VtZW4gZGUgUHJ1ZWJhcyBkZSBOb3JtYWxpZGFkIFNoYXBpcm8tV2lsayIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpKQ0KYGBgDQoNClBhcmEgY2FkYSB2YXJpYWJsZSBhbmFsaXphZGEsIHNlIHBsYW50ZWFyb24gbGFzIHNpZ3VpZW50ZXMgaGlww7N0ZXNpcywgc2lndWllbmRvIGVsIHByb2NlZGltaWVudG8gZXN0w6FuZGFyIHBhcmEgdW5hIHBydWViYSBkZSBub3JtYWxpZGFkOg0KDQoqSGlww7N0ZXNpcyBOdWxhIChI4oKAKSo6IExvcyBkYXRvcyBkZSBsYSB2YXJpYWJsZSBzaWd1ZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsLg0KDQoqSGlww7N0ZXNpcyBBbHRlcm5hdGl2YSBI4oKQKjogTG9zIGRhdG9zIGRlIGxhIHZhcmlhYmxlIG5vIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuDQoNCiAgRW4gdG9kb3MgbG9zIGNhc29zIGFuYWxpemFkb3MsIGVsIHAtdmFsb3Igb2J0ZW5pZG8gZXMgZXh0cmVtYWRhbWVudGUgYmFqbyAocG9yIGVqZW1wbG8sIDwgMi4yZS0xNiksIGxvIGN1YWwgZXMgc2lnbmlmaWNhdGl2YW1lbnRlIGluZmVyaW9yIGEgY3VhbHF1aWVyIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEgZXN0w6FuZGFyIChjb23Dum5tZW50ZSDOsSA9IDAuMDUpLiBEZSBhY3VlcmRvIGNvbiBsYSByZWdsYSBkZSBkZWNpc2nDs24sIGN1YW5kbyBlbCBwLXZhbG9yIGVzIG1lbm9yIHF1ZSBlbCBuaXZlbCBkZSBzaWduaWZpY2FuY2lhLCBzZSByZWNoYXphIGxhIGhpcMOzdGVzaXMgbnVsYS4NClBvciBsbyB0YW50bywgc2UgcmVjaGF6YSBsYSBoaXDDs3Rlc2lzIG51bGEgZGUgbm9ybWFsaWRhZCBwYXJhIHRvZGFzIGxhcyB2YXJpYWJsZXMgY2xhdmUgZGVsIGVzdHVkaW8uIEVzdG8gY29uZmlybWEgcXVlIGxvcyBkYXRvcyBubyBzZSBkaXN0cmlidXllbiBkZSBtYW5lcmEgbm9ybWFsLg0KDQogIERhZG8gcXVlIGxhcyBwcnVlYmFzIGRlIG5vcm1hbGlkYWQgZGUgU2hhcGlyby1XaWxrIGluZGljYW4gZGUgbWFuZXJhIGNvbmNsdXllbnRlIHF1ZSBsYXMgdmFyaWFibGVzIGRlIGxhIGludmVzdGlnYWNpw7NuIG5vIHNpZ3VlbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwsIG5vIHNlIGN1bXBsZW4gbG9zIHN1cHVlc3RvcyBwYXJhIGxhIGFwbGljYWNpw7NuIGRlIHBydWViYXMgcGFyYW3DqXRyaWNhcy4NCkVuIGNvbnNlY3VlbmNpYSwgcGFyYSBhbmFsaXphciBsYSByZWxhY2nDs24gZW50cmUgbGFzIHZhcmlhYmxlcyBvcmRpbmFsZXMgZGUgZXN0ZSBlc3R1ZGlvLCBzZSBvcHRhIHBvciB1biBtw6l0b2RvIG5vIHBhcmFtw6l0cmljby4gRXNwZWPDrWZpY2FtZW50ZSwgc2UgdXRpbGl6YXLDoSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4gKM+BKSwgeWEgcXVlIGVzIGxhIGhlcnJhbWllbnRhIGlkZWFsIHBhcmEgY3VhbnRpZmljYXIgZWwgZ3JhZG8gZGUgYXNvY2lhY2nDs24gZW50cmUgdmFyaWFibGVzIG9yZGluYWxlcyBvIGN1YW50aXRhdGl2YXMgcXVlIG5vIHByZXNlbnRhbiB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuDQoNCiMjICoqNC43IE1vZGVsbyBkZSBDb3JyZWxhY2nDs24gR2VuZXJhbCBlbnRyZSBQcm95ZWN0b3MgQ29tdW5pdGFyaW9zIHkgUHVudG9zIENyw610aWNvcyoqDQoNCg0KUGFyYSBndWlhciBlbCBhbsOhbGlzaXMgZGUgY29ycmVsYWNpw7NuIGVudHJlIGxvcyBwcm95ZWN0b3MgY29tdW5pdGFyaW9zIGRlIGxhcyBBZ2VuZGFzIENvbmNyZXRhcyBkZSBBY2Npw7NuIHkgbG9zIG51ZG9zIGNyw610aWNvcyBlbiBlbCBFc3RhZG8gTcOpcmlkYSwgc2UgYWRvcHTDsyB1biBlbmZvcXVlIG5vIHBhcmFtw6l0cmljbyBtZWRpYW50ZSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4uIEVzdGEgZGVjaXNpw7NuIG1ldG9kb2zDs2dpY2Egc2UgZnVuZGFtZW50w7MgZW4gbGEgYXVzZW5jaWEgZGUgbm9ybWFsaWRhZCBkZXRlY3RhZGEgZW4gbGFzIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzIGEgdHJhdsOpcyBkZSBsYSBwcnVlYmEgZGUgU2hhcGlyby1XaWxrLCBkb25kZSB0b2RvcyBsb3MgcC12YWxvcmVzIHJlc3VsdGFyb24gbWVub3JlcyBhIDAuMDAxLg0KDQpFbCBjb2VmaWNpZW50ZSBkZSBTcGVhcm1hbiBlcyBwYXJ0aWN1bGFybWVudGUgYXByb3BpYWRvIHBhcmEgZXN0ZSBhbsOhbGlzaXMgcG9ycXVlIG5vIGFzdW1lIGRpc3RyaWJ1Y2lvbmVzIG5vcm1hbGVzIHkgZXMgcm9idXN0byBhbnRlIGxhIHByZXNlbmNpYSBkZSB2YWxvcmVzIGF0w61waWNvcywgY2FyYWN0ZXLDrXN0aWNhcyBwcmVzZW50ZXMgZW4gbnVlc3Ryb3MgZGF0b3MuIEVzdGUgY29lZmljaWVudGUgbWlkZSBlbCBncmFkbyBkZSBhc29jaWFjacOzbiBtb25vdMOzbmljYSBlbnRyZSBkb3MgdmFyaWFibGVzLCBwZXJtaXRpw6luZG9ub3MgaWRlbnRpZmljYXIgdGFudG8gcmVsYWNpb25lcyBsaW5lYWxlcyBjb21vIG5vIGxpbmVhbGVzLg0KDQpgYGB7cn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIE1PREVMTyBERSBDT1JSRUxBQ0nDk04gREUgU1BFQVJNQU4gUEFSQSBQUk9ZRUNUT1MgQ09NVU5BTEVTIEFDQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgMS4gUHJlcGFyYWNpw7NuIGRlIGRhdG9zIChJR1VBTCkNCnRvcDEwX2NmZyA8LSBkZl9kdW1taWVzICU+JSBjb3VudChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcpICU+JSBhcnJhbmdlKGRlc2MobikpICU+JSBzbGljZSgxOjEwKSAlPiUgcHVsbChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcpDQp0b3AxMF9nb2IgPC0gZGZfZHVtbWllcyAlPiUgY291bnQoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTikgJT4lIGFycmFuZ2UoZGVzYyhuKSkgJT4lIHNsaWNlKDE6MTApICU+JSBwdWxsKENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT04pDQpjZmdfZHVtbXlfY29scyA8LSBwYXN0ZTAoIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGR18iLCBnc3ViKCIgIiwgIl8iLCB0b3AxMF9jZmcpKQ0KZ29iX2R1bW15X2NvbHMgPC0gcGFzdGUwKCJDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OXyIsIGdzdWIoIiAiLCAiXyIsIHRvcDEwX2dvYikpDQpjZmdfZHVtbXlfY29scyA8LSBpbnRlcnNlY3QoY2ZnX2R1bW15X2NvbHMsIG5hbWVzKGRmX2R1bW1pZXMpKQ0KZ29iX2R1bW15X2NvbHMgPC0gaW50ZXJzZWN0KGdvYl9kdW1teV9jb2xzLCBuYW1lcyhkZl9kdW1taWVzKSkNCnZhcnNfcmVzdWx0YWRvIDwtIGMoIlJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8iLCAiQ0xBU0lGSUNBQ0lPTl9ERUxfUFJPWUVDVE8iLCAiUExBWk9TIiwgIkNsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMiKQ0KDQojIDIuIENSRUFSIGRmX2NvciBDT1JSRUdJRE8gKFNJTiBjYXNlX3doZW4pDQpkZl9jb3IgPC0gZGZfZHVtbWllcyAlPiUNCiAgc2VsZWN0KGFsbF9vZih2YXJzX3Jlc3VsdGFkbyksIGFsbF9vZihjZmdfZHVtbXlfY29scyksIGFsbF9vZihnb2JfZHVtbXlfY29scykpDQogICMg4oaRIEVMSU1JTkFETyBlbCBtdXRhdGUoKSBjb24gY2FzZV93aGVuIHBvcnF1ZSBsYSB2YXJpYWJsZSB5YSBlc3TDoSBjb3JyZWN0YSAoMSwyLDMsNCkNCg0KIyAzLiBDw6FsY3VsbyBkZSBjb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIChJR1VBTCkNCmNhbGN1bGFyX2Nvcl9zcGVhcm1hbiA8LSBmdW5jdGlvbihkYXRhKSB7DQogIG5fdmFycyA8LSBuY29sKGRhdGEpDQogIGNvcl9tYXRyaXggPC0gbWF0cml4KE5BLCBucm93ID0gbl92YXJzLCBuY29sID0gbl92YXJzKQ0KICBwX21hdHJpeCA8LSBtYXRyaXgoTkEsIG5yb3cgPSBuX3ZhcnMsIG5jb2wgPSBuX3ZhcnMpDQogIGZvciAoaSBpbiAxOm5fdmFycykgew0KICAgIGZvciAoaiBpbiAxOm5fdmFycykgew0KICAgICAgaWYgKGkgIT0gaikgew0KICAgICAgICB0ZW1wIDwtIGRhdGFbLCBjKGksIGopXSAlPiUgbmEub21pdCgpDQogICAgICAgIGlmIChucm93KHRlbXApID4gMTApIHsNCiAgICAgICAgICB0ZXN0IDwtIHN1cHByZXNzV2FybmluZ3MoY29yLnRlc3QodGVtcFtbMV1dLCB0ZW1wW1syXV0sIG1ldGhvZCA9ICJzcGVhcm1hbiIsIGV4YWN0ID0gRkFMU0UpKQ0KICAgICAgICAgIGNvcl9tYXRyaXhbaSwgal0gPC0gdGVzdCRlc3RpbWF0ZQ0KICAgICAgICAgIHBfbWF0cml4W2ksIGpdIDwtIHRlc3QkcC52YWx1ZQ0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICBjb3JfbWF0cml4W2ksIGpdIDwtIDENCiAgICAgIH0NCiAgICB9DQogIH0NCiAgcm93bmFtZXMoY29yX21hdHJpeCkgPC0gY29sbmFtZXMoY29yX21hdHJpeCkgPC0gY29sbmFtZXMoZGF0YSkNCiAgcm93bmFtZXMocF9tYXRyaXgpIDwtIGNvbG5hbWVzKHBfbWF0cml4KSA8LSBjb2xuYW1lcyhkYXRhKQ0KICByZXR1cm4obGlzdChjb3IgPSBjb3JfbWF0cml4LCBwID0gcF9tYXRyaXgpKQ0KfQ0Kc2V0LnNlZWQoMTIzKQ0KY29yX3Jlc3VsdHMgPC0gY2FsY3VsYXJfY29yX3NwZWFybWFuKGRmX2NvcikNCg0KIyA0LiBQcm9jZXNhbWllbnRvIGRlIHJlc3VsdGFkb3MgeSBub21icmVzIGNvcnRvcyAoSUdVQUwpDQphY29ydGFyX25vbWJyZXMgPC0gZnVuY3Rpb24obm9tYnJlcykgew0KICBub21icmVzIDwtIGdzdWIoIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGR18iLCAiQ0ZHOiAiLCBub21icmVzKQ0KICBub21icmVzIDwtIGdzdWIoIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT05fIiwgIkdPQjogIiwgbm9tYnJlcykNCiAgbm9tYnJlcyA8LSBnc3ViKCJfIiwgIiAiLCBub21icmVzKQ0KICBzdWJzdHIobm9tYnJlcywgMSwgMjgpDQp9DQpjb2xuYW1lcyhjb3JfcmVzdWx0cyRjb3IpIDwtIHJvd25hbWVzKGNvcl9yZXN1bHRzJGNvcikgPC0gYWNvcnRhcl9ub21icmVzKGNvbG5hbWVzKGRmX2NvcikpDQpjb2xuYW1lcyhjb3JfcmVzdWx0cyRwKSA8LSByb3duYW1lcyhjb3JfcmVzdWx0cyRwKSA8LSBhY29ydGFyX25vbWJyZXMoY29sbmFtZXMoZGZfY29yKSkNCg0KY29yX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29yX3Jlc3VsdHMkY29yKSAlPiUNCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlZhcmlhYmxlMSIpICU+JQ0KICBwaXZvdF9sb25nZXIoLVZhcmlhYmxlMSwgbmFtZXNfdG8gPSAiVmFyaWFibGUyIiwgdmFsdWVzX3RvID0gIkNvcnJlbGFjaW9uIikgJT4lDQogIGxlZnRfam9pbigNCiAgICBhcy5kYXRhLmZyYW1lKGNvcl9yZXN1bHRzJHApICU+JQ0KICAgICAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIlZhcmlhYmxlMSIpICU+JQ0KICAgICAgcGl2b3RfbG9uZ2VyKC1WYXJpYWJsZTEsIG5hbWVzX3RvID0gIlZhcmlhYmxlMiIsIHZhbHVlc190byA9ICJwX3ZhbG9yIiksDQogICAgYnkgPSBjKCJWYXJpYWJsZTEiLCAiVmFyaWFibGUyIikNCiAgKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShDb3JyZWxhY2lvbiksIFZhcmlhYmxlMSAhPSBWYXJpYWJsZTIpICU+JQ0KICBtdXRhdGUoDQogICAgU2lnbmlmaWNhdGl2YSA9IGlmZWxzZShwX3ZhbG9yIDwgMC4wNSwgIlPDrSIsICJObyIpLA0KICAgIE1hZ25pdHVkID0gY2FzZV93aGVuKA0KICAgICAgYWJzKENvcnJlbGFjaW9uKSA+IDAuNiB+ICJNdXkgZnVlcnRlIiwNCiAgICAgIGFicyhDb3JyZWxhY2lvbikgPiAwLjQgfiAiRnVlcnRlIiwNCiAgICAgIGFicyhDb3JyZWxhY2lvbikgPiAwLjIgfiAiTW9kZXJhZGEiLA0KICAgICAgVFJVRSB+ICJEw6liaWwiDQogICAgKQ0KICApDQoNCiMgNC4gVEFCTEEgQ09NUExFVEEgREUgQ09FRklDSUVOVEVTIERFIFNQRUFSTUFODQp0YWJsYV9jb2VmX3NwZWFybWFuIDwtIGNvcl9kZiAlPiUNCiAgc2VsZWN0KFZhcmlhYmxlMSwgVmFyaWFibGUyLCBDb3JyZWxhY2lvbiwgcF92YWxvciwgU2lnbmlmaWNhdGl2YSwgTWFnbml0dWQpICU+JQ0KICBhcnJhbmdlKGRlc2MoYWJzKENvcnJlbGFjaW9uKSkpDQoNCmthYmxlKHRhYmxhX2NvZWZfc3BlYXJtYW4sDQogICAgICBjYXB0aW9uID0gIkNvZWZpY2llbnRlcyBkZSBDb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4gZW50cmUgdmFyaWFibGVzIGNsYXZlIChBQ0EpIiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIlZhcmlhYmxlIDEiLCAiVmFyaWFibGUgMiIsICJSaG8gKM+BKSIsICJwLXZhbG9yIiwgIlNpZ25pZmljYXRpdmEiLCAiTWFnbml0dWQiKSwNCiAgICAgIGFsaWduID0gImwiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEZBTFNFKSAlPiUNCiAgcm93X3NwZWMod2hpY2godGFibGFfY29lZl9zcGVhcm1hbiRTaWduaWZpY2F0aXZhID09ICJTw60iICYgdGFibGFfY29lZl9zcGVhcm1hbiRNYWduaXR1ZCAhPSAiRMOpYmlsIiksIGJvbGQgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiIzFiOWU3NyIpICU+JQ0KICByb3dfc3BlYyh3aGljaCh0YWJsYV9jb2VmX3NwZWFybWFuJFNpZ25pZmljYXRpdmEgPT0gIlPDrSIgJiB0YWJsYV9jb2VmX3NwZWFybWFuJE1hZ25pdHVkID09ICJEw6liaWwiKSwgY29sb3IgPSAiYmxhY2siLCBiYWNrZ3JvdW5kID0gIiNlNmYyZTYiKSAlPiUNCiAgcm93X3NwZWMod2hpY2godGFibGFfY29lZl9zcGVhcm1hbiRTaWduaWZpY2F0aXZhID09ICJObyIpLCBjb2xvciA9ICJncmF5NDAiLCBiYWNrZ3JvdW5kID0gIiNmN2Y3ZjciKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1WaXN1YWxpemFjacOzbiBhbHRlcm5hdGl2YTogSGVhdG1hcCBkZSBjb3JyZWxhY2lvbmVzLS0tLS0tLS0tLS0tLS0tLS0tLQ0KZ2dwbG90KHRhYmxhX2NvZWZfc3BlYXJtYW4gJT4lIGZpbHRlcihNYWduaXR1ZCAhPSAiRMOpYmlsIiksIA0KICAgICAgIGFlcyh4ID0gVmFyaWFibGUxLCB5ID0gVmFyaWFibGUyLCBmaWxsID0gQ29ycmVsYWNpb24pKSArDQogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNwcmludGYoIiUuMmYiLCBDb3JyZWxhY2lvbikpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKA0KICAgIGxvdyA9ICIjZDcxOTFjIiwgbWlkID0gIiNmZmZmYmYiLCBoaWdoID0gIiMyYzdiYjYiLCBtaWRwb2ludCA9IDAsIGxpbWl0cyA9IGMoLTEsIDEpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkNvcnJlbGFjaW9uZXMgTW9kZXJhZGFzIHkgRnVlcnRlcyAoU3BlYXJtYW4pIiwNCiAgICBzdWJ0aXRsZSA9ICJFbnRyZSB0aXBvbG9nw61hcywgZ29iZXJuYWNpb25lcyB5IHJlc3VsdGFkb3MgZGUgcHJveWVjdG9zIiwNCiAgICB4ID0gIiIsIHkgPSAiIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEFOw4FMSVNJUyBDT01QTEVUTyBERSBDT1JSRUxBQ0lPTkVTIERFIFNQRUFSTUFOIC0gUFJPWUVDVE9TIEFDQQ0KIyBGTFVKTyBERSBUUkFCQUpPIElOVEVHUkFETyBQQVJBIE1PTk9HUkFGw41BDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAxLiBIRUFUTUFQIEFDQUTDiU1JQ08gLSBNQVRSSVogREUgQ09SUkVMQUNJT05FUyBTSUdOSUZJQ0FUSVZBUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNyZWFyX2hlYXRtYXBfY29ycmVsYWNpb25lcyA8LSBmdW5jdGlvbihjb3JfcmVzdWx0cywgdGl0dWxvID0gIk1hdHJpeiBkZSBDb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4gLSBQcm95ZWN0b3MgQUNBIikgew0KICANCiAgIyBTaW5jcm9uaXphciBtYXRyaWNlcw0KICB2YXJzX2NvbXVuZXMgPC0gaW50ZXJzZWN0KHJvd25hbWVzKGNvcl9yZXN1bHRzJGNvciksIHJvd25hbWVzKGNvcl9yZXN1bHRzJHApKQ0KICBjb3JfbWF0cml4IDwtIGNvcl9yZXN1bHRzJGNvclt2YXJzX2NvbXVuZXMsIHZhcnNfY29tdW5lc10NCiAgcF9tYXRyaXggPC0gY29yX3Jlc3VsdHMkcFt2YXJzX2NvbXVuZXMsIHZhcnNfY29tdW5lc10NCiAgDQogICMgKipDT1JSRUNDScOTTjogVXNhciByZXNoYXBlMjo6bWVsdCBleHBsw61jaXRhbWVudGUgcGFyYSBtYXRyaWNlcyoqDQogIGNvcl9sb25nIDwtIHJlc2hhcGUyOjptZWx0KGNvcl9tYXRyaXgsIHZhcm5hbWVzID0gYygiVmFyaWFibGUxIiwgIlZhcmlhYmxlMiIpLCB2YWx1ZS5uYW1lID0gIkNvcnJlbGFjaW9uIikNCiAgcF9sb25nIDwtIHJlc2hhcGUyOjptZWx0KHBfbWF0cml4LCB2YXJuYW1lcyA9IGMoIlZhcmlhYmxlMSIsICJWYXJpYWJsZTIiKSwgdmFsdWUubmFtZSA9ICJQX3ZhbG9yIikNCiAgDQogICMgQ29tYmluYXIgZGF0b3MNCiAgZGF0b3NfcGxvdCA8LSBtZXJnZShjb3JfbG9uZywgcF9sb25nLCBieSA9IGMoIlZhcmlhYmxlMSIsICJWYXJpYWJsZTIiKSkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgU2lnbmlmaWNhdGl2YSA9IFBfdmFsb3IgPCAwLjA1LA0KICAgICAgQ29ycmVsYWNpb25fbW9zdHJhciA9IGlmZWxzZShTaWduaWZpY2F0aXZhLCBDb3JyZWxhY2lvbiwgTkEpLA0KICAgICAgRXRpcXVldGEgPSBpZmVsc2UoU2lnbmlmaWNhdGl2YSAmIGFicyhDb3JyZWxhY2lvbikgPiAwLjMsIA0KICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCIlLjJmIiwgQ29ycmVsYWNpb24pLCAiIiksDQogICAgICBBc3RlcmlzY28gPSBjYXNlX3doZW4oDQogICAgICAgIFBfdmFsb3IgPCAwLjAwMSB+ICIqKioiLA0KICAgICAgICBQX3ZhbG9yIDwgMC4wMSB+ICIqKiIsDQogICAgICAgIFBfdmFsb3IgPCAwLjA1IH4gIioiLA0KICAgICAgICBUUlVFIH4gIiINCiAgICAgICkNCiAgICApDQogIA0KICAjIENyZWFyIGhlYXRtYXANCiAgcCA8LSBnZ3Bsb3QoZGF0b3NfcGxvdCwgYWVzKHggPSBWYXJpYWJsZTEsIHkgPSBWYXJpYWJsZTIpKSArDQogICAgZ2VvbV90aWxlKGFlcyhmaWxsID0gQ29ycmVsYWNpb25fbW9zdHJhciksIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDAuMykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBFdGlxdWV0YSksIHNpemUgPSAyLjgsIGNvbG9yID0gImJsYWNrIiwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gQXN0ZXJpc2NvKSwgc2l6ZSA9IDIsIGNvbG9yID0gInJlZCIsIA0KICAgICAgICAgICAgICBudWRnZV95ID0gMC4yLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKA0KICAgICAgbG93ID0gIiNkNzMwMjciLCBtaWQgPSAiI2ZmZmZiZiIsIGhpZ2ggPSAiIzFhOTg1MCIsDQogICAgICBtaWRwb2ludCA9IDAsIGxpbWl0cyA9IGMoLTEsIDEpLCBuYS52YWx1ZSA9ICJncmV5OTUiLA0KICAgICAgbmFtZSA9ICLPgSIsDQogICAgICBicmVha3MgPSBjKC0xLCAtMC41LCAwLCAwLjUsIDEpDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gdGl0dWxvLA0KICAgICAgc3VidGl0bGUgPSAiU29sbyBjb3JyZWxhY2lvbmVzIHNpZ25pZmljYXRpdmFzIHwgKioqIHA8MC4wMDEsICoqIHA8MC4wMSwgKiBwPDAuMDUiLA0KICAgICAgeCA9ICIiLCB5ID0gIiIsDQogICAgICBjYXB0aW9uID0gcGFzdGUoIm4gPSIsIHN1bShkYXRvc19wbG90JFNpZ25pZmljYXRpdmEsIG5hLnJtID0gVFJVRSksICJjb3JyZWxhY2lvbmVzIHNpZ25pZmljYXRpdmFzIikNCiAgICApICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKA0KICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTApLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksDQogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTEpLA0KICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCINCiAgICApICsNCiAgICBjb29yZF9lcXVhbCgpDQogIA0KICByZXR1cm4ocCkNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDIuIEVWQUxVQUNJw5NOIERFIEhJUMOTVEVTSVMgRVNQRUPDjUZJQ0FTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY3JlYXJfZXZhbHVhY2lvbl9oaXBvdGVzaXMgPC0gZnVuY3Rpb24oY29yX2RmKSB7DQogIA0KICAjIENsYXNpZmljYXIgY29ycmVsYWNpb25lcyBzZWfDum4gaGlww7N0ZXNpcyBkZSBpbnZlc3RpZ2FjacOzbg0KICBkYXRvc19oaXBvdGVzaXMgPC0gY29yX2RmICU+JQ0KICAgIGZpbHRlcihTaWduaWZpY2F0aXZhID09ICJTw60iKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBDYXRlZ29yaWFfSGlwb3Rlc2lzID0gY2FzZV93aGVuKA0KICAgICAgICAjIEhFMTogQ29uY29yZGFuY2lhIHNlY3RvcmlhbCBDRkctR09CDQogICAgICAgIChncmVwbCgiQ0ZHLipFTEVDVFJJQ0lEQUQiLCBWYXJpYWJsZTEpICYgZ3JlcGwoIkdPQi4qRUxFQ1RSSUNJREFEIiwgVmFyaWFibGUyKSkgfA0KICAgICAgICAoZ3JlcGwoIkNGRy4qVklWSUVOREEiLCBWYXJpYWJsZTEpICYgZ3JlcGwoIkdPQi4qVklWSUVOREEiLCBWYXJpYWJsZTIpKSB8DQogICAgICAgIChncmVwbCgiQ0ZHLipUUkFOU1BPUlRFIiwgVmFyaWFibGUxKSAmIGdyZXBsKCJHT0IuKlRSQU5TUE9SVEUiLCBWYXJpYWJsZTIpKSB8DQogICAgICAgIChncmVwbCgiQ0ZHLipWSUFMSURBRCIsIFZhcmlhYmxlMSkgJiBncmVwbCgiR09CLipWSUFMSURBRCIsIFZhcmlhYmxlMikpIH4gIkhFMTogQ29uY29yZGFuY2lhIFNlY3RvcmlhbCIsDQogICAgICAgIA0KICAgICAgICAjIEhFMjogQ29tcGxlamlkYWQgaW5zdGl0dWNpb25hbCBlbiB2aXZpZW5kYQ0KICAgICAgICAoZ3JlcGwoIlZJVklFTkRBIiwgVmFyaWFibGUxKSAmIGdyZXBsKCJDbGFzaWZpY2FjaW9uLipBY3RvcmVzIiwgVmFyaWFibGUyKSkgfA0KICAgICAgICAoZ3JlcGwoIkNsYXNpZmljYWNpb24uKkFjdG9yZXMiLCBWYXJpYWJsZTEpICYgZ3JlcGwoIlZJVklFTkRBIiwgVmFyaWFibGUyKSkgfiAiSEUyOiBDb21wbGVqaWRhZCBWaXZpZW5kYSIsDQogICAgICAgIA0KICAgICAgICAjIEhFMzogRWZpY2llbmNpYSBlbiB0cmFuc3BvcnRlDQogICAgICAgIChncmVwbCgiVFJBTlNQT1JURSIsIFZhcmlhYmxlMSkgJiBncmVwbCgiUkFUSU8uKlBST1lFQ1RPIiwgVmFyaWFibGUyKSkgfA0KICAgICAgICAoZ3JlcGwoIlJBVElPLipQUk9ZRUNUTyIsIFZhcmlhYmxlMSkgJiBncmVwbCgiVFJBTlNQT1JURSIsIFZhcmlhYmxlMikpIH4gIkhFMzogRWZpY2llbmNpYSBUcmFuc3BvcnRlIiwNCiAgICAgICAgDQogICAgICAgICMgSEU0OiBDb21wbGVqaWRhZCB0ZW1wb3JhbCBlbiBpbmZyYWVzdHJ1Y3R1cmENCiAgICAgICAgKGdyZXBsKCJJTkZSQUVTVFJVQ1RVUiIsIFZhcmlhYmxlMSkgJiBncmVwbCgiUExBWk9TIiwgVmFyaWFibGUyKSkgfA0KICAgICAgICAoZ3JlcGwoIlBMQVpPUyIsIFZhcmlhYmxlMSkgJiBncmVwbCgiSU5GUkFFU1RSVUNUVVIiLCBWYXJpYWJsZTIpKSB+ICJIRTQ6IENvbXBsZWppZGFkIFRlbXBvcmFsIiwNCiAgICAgICAgDQogICAgICAgIFRSVUUgfiAiQ29ycmVsYWNpb25lcyBFeHBsb3JhdG9yaWFzIg0KICAgICAgKSwNCiAgICAgIEVzdGFkb19Db25maXJtYWNpb24gPSBjYXNlX3doZW4oDQogICAgICAgIENhdGVnb3JpYV9IaXBvdGVzaXMgPT0gIkhFMTogQ29uY29yZGFuY2lhIFNlY3RvcmlhbCIgJiBhYnMoQ29ycmVsYWNpb24pID4gMC43IH4gIkNvbmZpcm1hZGEiLA0KICAgICAgICBDYXRlZ29yaWFfSGlwb3Rlc2lzID09ICJIRTI6IENvbXBsZWppZGFkIFZpdmllbmRhIiAmIENvcnJlbGFjaW9uIDwgMCAmIGFicyhDb3JyZWxhY2lvbikgPiAwLjIgfiAiQ29uZmlybWFkYSIsDQogICAgICAgIENhdGVnb3JpYV9IaXBvdGVzaXMgPT0gIkhFMzogRWZpY2llbmNpYSBUcmFuc3BvcnRlIiAmIENvcnJlbGFjaW9uID4gMCAmIGFicyhDb3JyZWxhY2lvbikgPiAwLjEgfiAiQ29uZmlybWFkYSIsDQogICAgICAgIENhdGVnb3JpYV9IaXBvdGVzaXMgPT0gIkhFNDogQ29tcGxlamlkYWQgVGVtcG9yYWwiICYgQ29ycmVsYWNpb24gPCAwICYgYWJzKENvcnJlbGFjaW9uKSA+IDAuMSB+ICJDb25maXJtYWRhIiwNCiAgICAgICAgQ2F0ZWdvcmlhX0hpcG90ZXNpcyAhPSAiQ29ycmVsYWNpb25lcyBFeHBsb3JhdG9yaWFzIiB+ICJQYXJjaWFsIiwNCiAgICAgICAgVFJVRSB+ICJFeHBsb3JhdG9yaWEiDQogICAgICApDQogICAgKQ0KICANCiAgIyBSZXN1bWlyIHBvciBoaXDDs3Rlc2lzDQogIHJlc3VtZW4gPC0gZGF0b3NfaGlwb3Rlc2lzICU+JQ0KICAgIGdyb3VwX2J5KENhdGVnb3JpYV9IaXBvdGVzaXMsIEVzdGFkb19Db25maXJtYWNpb24pICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIENhbnRpZGFkID0gbigpLA0KICAgICAgUmhvX1Byb21lZGlvID0gbWVhbihhYnMoQ29ycmVsYWNpb24pKSwNCiAgICAgIFJob19NYXhpbW8gPSBtYXgoYWJzKENvcnJlbGFjaW9uKSksDQogICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MoUmhvX1Byb21lZGlvKSkNCiAgDQogICMgQ3JlYXIgZ3LDoWZpY28gZGUgYmFycmFzIGhvcml6b250YWxlcw0KICBwIDwtIGdncGxvdChyZXN1bWVuLCBhZXMoeCA9IHJlb3JkZXIoQ2F0ZWdvcmlhX0hpcG90ZXNpcywgUmhvX1Byb21lZGlvKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBSaG9fUHJvbWVkaW8sIGZpbGwgPSBFc3RhZG9fQ29uZmlybWFjaW9uKSkgKw0KICAgIGdlb21fY29sKGFscGhhID0gMC44LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjMpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKCJuPSIsIENhbnRpZGFkLCAiXG7PgW1heD0iLCByb3VuZChSaG9fTWF4aW1vLCAyKSkpLA0KICAgICAgICAgICAgICBoanVzdCA9IC0wLjEsIHNpemUgPSAzLjUsIGZvbnRmYWNlID0gImJvbGQiKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwoDQogICAgICB2YWx1ZXMgPSBjKCJDb25maXJtYWRhIiA9ICIjMjdhZTYwIiwgIlBhcmNpYWwiID0gIiNmMzljMTIiLCAiRXhwbG9yYXRvcmlhIiA9ICIjMmMzZTUwIiksDQogICAgICBuYW1lID0gIkVzdGFkbyBkZSBIaXDDs3Rlc2lzIg0KICAgICkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIkV2YWx1YWNpw7NuIEVtcMOtcmljYSBkZSBIaXDDs3Rlc2lzIGRlIEludmVzdGlnYWNpw7NuIiwNCiAgICAgIHN1YnRpdGxlID0gIkZ1ZXJ6YSBwcm9tZWRpbyBkZSBjb3JyZWxhY2lvbmVzIHkgZXN0YWRvIGRlIGNvbmZpcm1hY2nDs24gcG9yIGhpcMOzdGVzaXMiLA0KICAgICAgeCA9ICJIaXDDs3Rlc2lzIEVzcGVjw61maWNhcyIsDQogICAgICB5ID0gIkNvcnJlbGFjacOzbiBQcm9tZWRpbyB8z4F8IiwNCiAgICAgIGNhcHRpb24gPSAibiA9IG7Dum1lcm8gZGUgY29ycmVsYWNpb25lcyBkZXRlY3RhZGFzLCDPgW1heCA9IGNvcnJlbGFjacOzbiBtw6F4aW1hIG9ic2VydmFkYSINCiAgICApICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTQpLA0KICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMS4xKSwgYnJlYWtzID0gc2VxKDAsIDEsIDAuMikpDQogIA0KICByZXR1cm4obGlzdChncmFmaWNvID0gcCwgZGF0b3MgPSByZXN1bWVuLCBkYXRvc19kZXRhbGxhZG9zID0gZGF0b3NfaGlwb3Rlc2lzKSkNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDMuIEFOw4FMSVNJUyBERSBWQVJJQUJMRVMgQ0VOVFJBTEVTIC0gUkVEIERFIElORkxVRU5DSUENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjcmVhcl9hbmFsaXNpc192YXJpYWJsZXNfY2VudHJhbGVzIDwtIGZ1bmN0aW9uKGNvcl9kZikgew0KICANCiAgIyBJZGVudGlmaWNhciB2YXJpYWJsZXMgbcOhcyAiY29uZWN0YWRhcyIgKGNvbiBtw6FzIGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMpDQogIGNvbmVjdGl2aWRhZCA8LSBjb3JfZGYgJT4lDQogICAgZmlsdGVyKFNpZ25pZmljYXRpdmEgPT0gIlPDrSIpICU+JQ0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gYyhWYXJpYWJsZTEsIFZhcmlhYmxlMiksIG5hbWVzX3RvID0gInBvc2ljaW9uIiwgdmFsdWVzX3RvID0gInZhcmlhYmxlIikgJT4lDQogICAgY291bnQodmFyaWFibGUsIG5hbWUgPSAibl9jb25leGlvbmVzIikgJT4lDQogICAgYXJyYW5nZShkZXNjKG5fY29uZXhpb25lcykpDQogIA0KICAjIENhbGN1bGFyIGZ1ZXJ6YSBwcm9tZWRpbyBkZSBjb3JyZWxhY2lvbmVzIHBvciB2YXJpYWJsZQ0KICBmdWVyemFfcHJvbWVkaW8gPC0gY29yX2RmICU+JQ0KICAgIGZpbHRlcihTaWduaWZpY2F0aXZhID09ICJTw60iKSAlPiUNCiAgICBwaXZvdF9sb25nZXIoY29scyA9IGMoVmFyaWFibGUxLCBWYXJpYWJsZTIpLCBuYW1lc190byA9ICJwb3NpY2lvbiIsIHZhbHVlc190byA9ICJ2YXJpYWJsZSIpICU+JQ0KICAgIGdyb3VwX2J5KHZhcmlhYmxlKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBjb3JyZWxhY2lvbl9wcm9tZWRpbyA9IG1lYW4oYWJzKENvcnJlbGFjaW9uKSksDQogICAgICBjb3JyZWxhY2lvbl9tYXhpbWEgPSBtYXgoYWJzKENvcnJlbGFjaW9uKSksDQogICAgICBuX211eV9mdWVydGVzID0gc3VtKGFicyhDb3JyZWxhY2lvbikgPiAwLjcpLA0KICAgICAgbl9mdWVydGVzID0gc3VtKGFicyhDb3JyZWxhY2lvbikgPiAwLjUpLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICkNCiAgDQogICMgQ29tYmluYXIgbcOpdHJpY2FzDQogIHZhcmlhYmxlc19jZW50cmFsZXMgPC0gbWVyZ2UoY29uZWN0aXZpZGFkLCBmdWVyemFfcHJvbWVkaW8sIGJ5ID0gInZhcmlhYmxlIikgJT4lDQogICAgbXV0YXRlKA0KICAgICAgc2NvcmVfY2VudHJhbGlkYWQgPSBzY2FsZShuX2NvbmV4aW9uZXMpWywxXSArIHNjYWxlKGNvcnJlbGFjaW9uX3Byb21lZGlvKVssMV0sDQogICAgICB0aXBvX3ZhcmlhYmxlID0gY2FzZV93aGVuKA0KICAgICAgICBncmVwbCgiQ0ZHIiwgdmFyaWFibGUpIH4gIkNsYXNpZmljYWNpw7NuIENGRyIsDQogICAgICAgIGdyZXBsKCJHT0IiLCB2YXJpYWJsZSkgfiAiQ2xhc2lmaWNhY2nDs24gR29iZXJuYWNpw7NuIiwgDQogICAgICAgIGdyZXBsKCJSQVRJTyIsIHZhcmlhYmxlKSB+ICJJbmRpY2Fkb3IgZGUgUmVzdWx0YWRvIiwNCiAgICAgICAgZ3JlcGwoIlBMQVpPUyIsIHZhcmlhYmxlKSB+ICJJbmRpY2Fkb3IgVGVtcG9yYWwiLA0KICAgICAgICBncmVwbCgiQ2xhc2lmaWNhY2lvbi4qQWN0b3JlcyIsIHZhcmlhYmxlKSB+ICJJbmRpY2Fkb3IgSW5zdGl0dWNpb25hbCIsDQogICAgICAgIFRSVUUgfiAiT3RyYSINCiAgICAgICkNCiAgICApICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhzY29yZV9jZW50cmFsaWRhZCkpDQogIA0KICAjIENyZWFyIGdyw6FmaWNvIGRlIHZhcmlhYmxlcyBjZW50cmFsZXMNCiAgcCA8LSBnZ3Bsb3QoaGVhZCh2YXJpYWJsZXNfY2VudHJhbGVzLCAxNSksIA0KICAgICAgICAgICAgICBhZXMoeCA9IHJlb3JkZXIodmFyaWFibGUsIHNjb3JlX2NlbnRyYWxpZGFkKSwgeSA9IHNjb3JlX2NlbnRyYWxpZGFkKSkgKw0KICAgIGdlb21fY29sKGFlcyhmaWxsID0gdGlwb192YXJpYWJsZSksIGFscGhhID0gMC44LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjMpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKCJDb25leGlvbmVzOiAiLCBuX2NvbmV4aW9uZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG7PgcyEPSIsIHJvdW5kKGNvcnJlbGFjaW9uX3Byb21lZGlvLCAyKSkpLA0KICAgICAgICAgICAgICBoanVzdCA9IC0wLjEsIHNpemUgPSAzLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19kKG5hbWUgPSAiVGlwbyBkZSBWYXJpYWJsZSIsIG9wdGlvbiA9ICJwbGFzbWEiKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiVmFyaWFibGVzIENlbnRyYWxlcyBlbiBsYSBSZWQgZGUgQ29ycmVsYWNpb25lcyIsDQogICAgICBzdWJ0aXRsZSA9ICJUb3AgMTUgdmFyaWFibGVzIHBvciBjZW50cmFsaWRhZCAoY29uZWN0aXZpZGFkICsgZnVlcnphIHByb21lZGlvKSIsDQogICAgICB4ID0gIlZhcmlhYmxlcyIsDQogICAgICB5ID0gIlNjb3JlIGRlIENlbnRyYWxpZGFkIChlc3RhbmRhcml6YWRvKSIsDQogICAgICBjYXB0aW9uID0gIs+BzIQgPSBjb3JyZWxhY2nDs24gcHJvbWVkaW8sIENvbmV4aW9uZXMgPSBuw7ptZXJvIGRlIGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMiDQogICAgKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICB0aGVtZSgNCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE0KSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIg0KICAgICkNCiAgDQogIHJldHVybihsaXN0KGdyYWZpY28gPSBwLCBkYXRvcyA9IHZhcmlhYmxlc19jZW50cmFsZXMpKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgNC4gQU7DgUxJU0lTIFNFQ1RPUklBTCBDT01QQVJBVElWTw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNyZWFyX2FuYWxpc2lzX3NlY3RvcmlhbCA8LSBmdW5jdGlvbihjb3JfZGYpIHsNCiAgDQogICMgSWRlbnRpZmljYXIgY29ycmVsYWNpb25lcyBwb3Igc2VjdG9yDQogIGFuYWxpc2lzX3NlY3RvcmlhbCA8LSBjb3JfZGYgJT4lDQogICAgZmlsdGVyKFNpZ25pZmljYXRpdmEgPT0gIlPDrSIpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHNlY3Rvcl9wcmluY2lwYWwgPSBjYXNlX3doZW4oDQogICAgICAgIGdyZXBsKCJFTEVDVFJJQ0lEQUQiLCBwYXN0ZShWYXJpYWJsZTEsIFZhcmlhYmxlMikpIH4gIkVsZWN0cmljaWRhZCIsDQogICAgICAgIGdyZXBsKCJWSVZJRU5EQSIsIHBhc3RlKFZhcmlhYmxlMSwgVmFyaWFibGUyKSkgfiAiVml2aWVuZGEiLCANCiAgICAgICAgZ3JlcGwoIlRSQU5TUE9SVEUiLCBwYXN0ZShWYXJpYWJsZTEsIFZhcmlhYmxlMikpIH4gIlRyYW5zcG9ydGUiLA0KICAgICAgICBncmVwbCgiVklBTElEQUQiLCBwYXN0ZShWYXJpYWJsZTEsIFZhcmlhYmxlMikpIH4gIlZpYWxpZGFkIiwNCiAgICAgICAgZ3JlcGwoIklORlJBRVNUUlVDVFVSIiwgcGFzdGUoVmFyaWFibGUxLCBWYXJpYWJsZTIpKSB+ICJJbmZyYWVzdHJ1Y3R1cmEiLA0KICAgICAgICBncmVwbCgiQU1CSUVOVEV8Q0FOQUxJWkFDSU9OIiwgcGFzdGUoVmFyaWFibGUxLCBWYXJpYWJsZTIpKSB+ICJBbWJpZW50ZS9DYW5hbGl6YWNpw7NuIiwNCiAgICAgICAgZ3JlcGwoIlNBTFVEIiwgcGFzdGUoVmFyaWFibGUxLCBWYXJpYWJsZTIpKSB+ICJTYWx1ZCIsDQogICAgICAgIGdyZXBsKCJFRFVDQUNJw5NOIiwgcGFzdGUoVmFyaWFibGUxLCBWYXJpYWJsZTIpKSB+ICJFZHVjYWNpw7NuIiwNCiAgICAgICAgVFJVRSB+ICJJbnRlcnNlY3RvcmlhbCINCiAgICAgICkNCiAgICApICU+JQ0KICAgIGdyb3VwX2J5KHNlY3Rvcl9wcmluY2lwYWwpICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIG5fY29ycmVsYWNpb25lcyA9IG4oKSwNCiAgICAgIGNvcnJlbGFjaW9uX3Byb21lZGlvID0gbWVhbihhYnMoQ29ycmVsYWNpb24pKSwNCiAgICAgIGNvcnJlbGFjaW9uX21heGltYSA9IG1heChhYnMoQ29ycmVsYWNpb24pKSwNCiAgICAgIG5fbXV5X2Z1ZXJ0ZXMgPSBzdW0oTWFnbml0dWQgPT0gIk11eSBmdWVydGUiKSwNCiAgICAgIG5fZnVlcnRlcyA9IHN1bShNYWduaXR1ZCAlaW4lIGMoIkZ1ZXJ0ZSIsICJNdXkgZnVlcnRlIikpLA0KICAgICAgcF92YWxvcl9wcm9tZWRpbyA9IG1lYW4ocF92YWxvciksDQogICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MoY29ycmVsYWNpb25fcHJvbWVkaW8pKQ0KICANCiAgIyBDcmVhciBncsOhZmljbyBjb21wYXJhdGl2byBzZWN0b3JpYWwNCiAgcCA8LSBnZ3Bsb3QoYW5hbGlzaXNfc2VjdG9yaWFsLCBhZXMoeCA9IHJlb3JkZXIoc2VjdG9yX3ByaW5jaXBhbCwgY29ycmVsYWNpb25fcHJvbWVkaW8pLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gY29ycmVsYWNpb25fcHJvbWVkaW8pKSArDQogICAgZ2VvbV9jb2woYWVzKGZpbGwgPSBuX2NvcnJlbGFjaW9uZXMpLCBhbHBoYSA9IDAuOCwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4zKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMCgibj0iLCBuX2NvcnJlbGFjaW9uZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiXG5Nw6F4PSIsIHJvdW5kKGNvcnJlbGFjaW9uX21heGltYSwgMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkZ1ZXJ0ZXM9Iiwgbl9mdWVydGVzKSksDQogICAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDMsIGZvbnRmYWNlID0gImJvbGQiKSArDQogICAgc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJOwrAgQ29ycmVsYWNpb25lcyIsIG9wdGlvbiA9ICJ2aXJpZGlzIikgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIkFuw6FsaXNpcyBTZWN0b3JpYWwgZGUgQ29ycmVsYWNpb25lcyIsDQogICAgICBzdWJ0aXRsZSA9ICJGdWVyemEgcHJvbWVkaW8gZGUgY29ycmVsYWNpb25lcyBwb3Igc2VjdG9yIGRlIGludGVydmVuY2nDs24iLA0KICAgICAgeCA9ICJTZWN0b3JlcyIsDQogICAgICB5ID0gIkNvcnJlbGFjacOzbiBQcm9tZWRpbyB8z4F8IiwNCiAgICAgIGNhcHRpb24gPSAibiA9IGNvcnJlbGFjaW9uZXMgZGV0ZWN0YWRhcywgTcOheCA9IGNvcnJlbGFjacOzbiBtw6F4aW1hLCBGdWVydGVzID0gY29ycmVsYWNpb25lcyA+MC41Ig0KICAgICkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCksDQogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSINCiAgICApICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBtYXgoYW5hbGlzaXNfc2VjdG9yaWFsJGNvcnJlbGFjaW9uX3Byb21lZGlvKSAqIDEuMikpDQogIA0KICByZXR1cm4obGlzdChncmFmaWNvID0gcCwgZGF0b3MgPSBhbmFsaXNpc19zZWN0b3JpYWwpKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgNS4gVEFCTEEgUkVTVU1FTiBFSkVDVVRJVkENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjcmVhcl90YWJsYV9yZXN1bWVuX2VqZWN1dGl2YSA8LSBmdW5jdGlvbihjb3JfZGYsIGRhdG9zX2hpcG90ZXNpcywgdmFyaWFibGVzX2NlbnRyYWxlcywgYW5hbGlzaXNfc2VjdG9yaWFsKSB7DQogIA0KICAjIFJlc3VtZW4gZ2VuZXJhbCBkZSBjb3JyZWxhY2lvbmVzDQogIHJlc3VtZW5fZ2VuZXJhbCA8LSBjb3JfZGYgJT4lDQogICAgZmlsdGVyKFNpZ25pZmljYXRpdmEgPT0gIlPDrSIpICU+JQ0KICAgIGdyb3VwX2J5KE1hZ25pdHVkKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBOX0NvcnJlbGFjaW9uZXMgPSBuKCksDQogICAgICBSYW5nb19Db3JyZWxhY2lvbiA9IHBhc3RlMCgiWyIsIHJvdW5kKG1pbihhYnMoQ29ycmVsYWNpb24pKSwgMiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIC0gIiwgcm91bmQobWF4KGFicyhDb3JyZWxhY2lvbikpLCAyKSwgIl0iKSwNCiAgICAgIFZhcmlhYmxlc19JbnZvbHVjcmFkYXMgPSBsZW5ndGgodW5pcXVlKGMoVmFyaWFibGUxLCBWYXJpYWJsZTIpKSksDQogICAgICBQX1ZhbG9yX1Byb21lZGlvID0gcm91bmQobWVhbihwX3ZhbG9yKSwgNCksDQogICAgICAuZ3JvdXBzID0gImRyb3AiDQogICAgKSAlPiUNCiAgICBhcnJhbmdlKG1hdGNoKE1hZ25pdHVkLCBjKCJNdXkgZnVlcnRlIiwgIkZ1ZXJ0ZSIsICJNb2RlcmFkYSIsICJEw6liaWwiKSkpDQogIA0KICAjIFJlc3VtZW4gZGUgaGlww7N0ZXNpcw0KICByZXN1bWVuX2hpcG90ZXNpc190YWJsYSA8LSBkYXRvc19oaXBvdGVzaXMgJT4lDQogICAgZ3JvdXBfYnkoQ2F0ZWdvcmlhX0hpcG90ZXNpcywgRXN0YWRvX0NvbmZpcm1hY2lvbikgJT4lDQogICAgc3VtbWFyaXNlKG4gPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBFc3RhZG9fQ29uZmlybWFjaW9uLCB2YWx1ZXNfZnJvbSA9IG4sIHZhbHVlc19maWxsID0gMCkNCiAgDQogIHJldHVybihsaXN0KA0KICAgIHJlc3VtZW5fZ2VuZXJhbCA9IHJlc3VtZW5fZ2VuZXJhbCwNCiAgICByZXN1bWVuX2hpcG90ZXNpcyA9IHJlc3VtZW5faGlwb3Rlc2lzX3RhYmxhLA0KICAgIHRvcF92YXJpYWJsZXMgPSBoZWFkKHZhcmlhYmxlc19jZW50cmFsZXMsIDEwKSwNCiAgICByZXN1bWVuX3NlY3RvcmlhbCA9IGFuYWxpc2lzX3NlY3RvcmlhbA0KICApKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRlVOQ0nDk04gUFJJTkNJUEFMIC0gRkxVSk8gREUgVFJBQkFKTyBDT01QTEVUTw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmVqZWN1dGFyX2FuYWxpc2lzX2NvbXBsZXRvX2NvcnJlbGFjaW9uZXMgPC0gZnVuY3Rpb24oY29yX3Jlc3VsdHMsIGNvcl9kZikgew0KICANCiAgY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KICBjYXQoIklOSUNJQU5ETyBBTsOBTElTSVMgQ09NUExFVE8gREUgQ09SUkVMQUNJT05FUyBERSBTUEVBUk1BTiAtIFBST1lFQ1RPUyBBQ0FcbiIpDQogIGNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCiAgDQogICMgVmVyaWZpY2FyIGRhdG9zIGRlIGVudHJhZGENCiAgaWYgKCFleGlzdHMoImNvcl9yZXN1bHRzIikgfHwgIWV4aXN0cygiY29yX2RmIikpIHsNCiAgICBzdG9wKCJFUlJPUjogRmFsdGFuIG9iamV0b3MgJ2Nvcl9yZXN1bHRzJyB5L28gJ2Nvcl9kZicuIEVqZWN1dGEgcHJpbWVybyBlbCBhbsOhbGlzaXMgZGUgY29ycmVsYWNpw7NuLiIpDQogIH0NCiAgDQogIGNhdCgiRGF0b3MgdmVyaWZpY2Fkb3MgY29ycmVjdGFtZW50ZS5cbiIpDQogIGNhdCgiY29yX3Jlc3VsdHMgY29tcG9uZW50ZXM6IiwgbmFtZXMoY29yX3Jlc3VsdHMpLCAiXG4iKQ0KICBjYXQoImNvcl9kZiBkaW1lbnNpb25lczoiLCBkaW0oY29yX2RmKSwgIlxuXG4iKQ0KICANCiAgIyBWSVNVQUxJWkFDScOTTiAxOiBIRUFUTUFQIFBSSU5DSVBBTA0KICBjYXQoIjEuIENSRUFORE8gSEVBVE1BUCBERSBDT1JSRUxBQ0lPTkVTIFNJR05JRklDQVRJVkFTLi4uXG4iKQ0KICBoZWF0bWFwIDwtIGNyZWFyX2hlYXRtYXBfY29ycmVsYWNpb25lcyhjb3JfcmVzdWx0cykNCiAgcHJpbnQoaGVhdG1hcCkNCiAgY2F0KCJIZWF0bWFwIGNvbXBsZXRhZG8uXG5cbiIpDQogIA0KICAjIFZJU1VBTElaQUNJw5NOIDI6IEVWQUxVQUNJw5NOIERFIEhJUMOTVEVTSVMNCiAgY2F0KCIyLiBFVkFMVUFORE8gSElQw5NURVNJUyBERSBJTlZFU1RJR0FDScOTTi4uLlxuIikNCiAgcmVzdWx0YWRvX2hpcG90ZXNpcyA8LSBjcmVhcl9ldmFsdWFjaW9uX2hpcG90ZXNpcyhjb3JfZGYpDQogIHByaW50KHJlc3VsdGFkb19oaXBvdGVzaXMkZ3JhZmljbykNCiAgY2F0KCJFdmFsdWFjacOzbiBkZSBoaXDDs3Rlc2lzIGNvbXBsZXRhZGEuXG5cbiIpDQogIA0KICAjIFZJU1VBTElaQUNJw5NOIDM6IEFOw4FMSVNJUyBERSBWQVJJQUJMRVMgQ0VOVFJBTEVTDQogIGNhdCgiMy4gQU5BTElaQU5ETyBWQVJJQUJMRVMgQ0VOVFJBTEVTLi4uXG4iKQ0KICBhbmFsaXNpc19jZW50cmFsaWRhZCA8LSBjcmVhcl9hbmFsaXNpc192YXJpYWJsZXNfY2VudHJhbGVzKGNvcl9kZikNCiAgcHJpbnQoYW5hbGlzaXNfY2VudHJhbGlkYWQkZ3JhZmljbykNCiAgY2F0KCJBbsOhbGlzaXMgZGUgY2VudHJhbGlkYWQgY29tcGxldGFkby5cblxuIikNCiAgDQogICMgVklTVUFMSVpBQ0nDk04gNDogQU7DgUxJU0lTIFNFQ1RPUklBTA0KICBjYXQoIjQuIFJFQUxJWkFORE8gQU7DgUxJU0lTIFNFQ1RPUklBTC4uLlxuIikNCiAgYW5hbGlzaXNfc2VjdG9yZXMgPC0gY3JlYXJfYW5hbGlzaXNfc2VjdG9yaWFsKGNvcl9kZikNCiAgcHJpbnQoYW5hbGlzaXNfc2VjdG9yZXMkZ3JhZmljbykNCiAgY2F0KCJBbsOhbGlzaXMgc2VjdG9yaWFsIGNvbXBsZXRhZG8uXG5cbiIpDQogIA0KICAjIEdFTkVSQVIgVEFCTEFTIFJFU1VNRU4NCiAgY2F0KCI1LiBHRU5FUkFORE8gVEFCTEFTIFJFU1VNRU4uLi5cbiIpDQogIHRhYmxhc19yZXN1bWVuIDwtIGNyZWFyX3RhYmxhX3Jlc3VtZW5fZWplY3V0aXZhKA0KICAgIGNvcl9kZiwgDQogICAgcmVzdWx0YWRvX2hpcG90ZXNpcyRkYXRvc19kZXRhbGxhZG9zLA0KICAgIGFuYWxpc2lzX2NlbnRyYWxpZGFkJGRhdG9zLA0KICAgIGFuYWxpc2lzX3NlY3RvcmVzJGRhdG9zDQogICkNCiAgDQogICMgTU9TVFJBUiBSRVNVTFRBRE9TIFBSSU5DSVBBTEVTDQogIGNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCiAgY2F0KCJSRVNVTUVOIEVKRUNVVElWTyBERSBSRVNVTFRBRE9TXG4iKQ0KICBjYXQoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpDQogIA0KICBjYXQoIkRJU1RSSUJVQ0nDk04gREUgQ09SUkVMQUNJT05FUyBTSUdOSUZJQ0FUSVZBUzpcbiIpDQogIHByaW50KHRhYmxhc19yZXN1bWVuJHJlc3VtZW5fZ2VuZXJhbCkNCiAgY2F0KCJcbiIpDQogIA0KICBjYXQoIkVWQUxVQUNJw5NOIERFIEhJUMOTVEVTSVM6XG4iKQ0KICBwcmludCh0YWJsYXNfcmVzdW1lbiRyZXN1bWVuX2hpcG90ZXNpcykNCiAgY2F0KCJcbiIpDQogIA0KICBjYXQoIlRPUCA1IFZBUklBQkxFUyBNw4FTIENFTlRSQUxFUzpcbiIpDQogIHByaW50KGhlYWQodGFibGFzX3Jlc3VtZW4kdG9wX3ZhcmlhYmxlc1tjKCJ2YXJpYWJsZSIsICJuX2NvbmV4aW9uZXMiLCAiY29ycmVsYWNpb25fcHJvbWVkaW8iKV0sIDUpKQ0KICBjYXQoIlxuIikNCiAgDQogIGNhdCgiQU7DgUxJU0lTIFNFQ1RPUklBTDpcbiIpDQogIHByaW50KHRhYmxhc19yZXN1bWVuJHJlc3VtZW5fc2VjdG9yaWFsKQ0KICBjYXQoIlxuIikNCiAgDQogIGNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCiAgY2F0KCJBTsOBTElTSVMgQ09NUExFVEFETyBFWElUT1NBTUVOVEVcbiIpDQogIGNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCiAgDQogICMgUmV0b3JuYXIgdG9kb3MgbG9zIHJlc3VsdGFkb3MNCiAgcmV0dXJuKGxpc3QoDQogICAgdmlzdWFsaXphY2lvbmVzID0gbGlzdCgNCiAgICAgIGhlYXRtYXAgPSBoZWF0bWFwLA0KICAgICAgZXZhbHVhY2lvbl9oaXBvdGVzaXMgPSByZXN1bHRhZG9faGlwb3Rlc2lzJGdyYWZpY28sDQogICAgICB2YXJpYWJsZXNfY2VudHJhbGVzID0gYW5hbGlzaXNfY2VudHJhbGlkYWQkZ3JhZmljbywNCiAgICAgIGFuYWxpc2lzX3NlY3RvcmlhbCA9IGFuYWxpc2lzX3NlY3RvcmVzJGdyYWZpY28NCiAgICApLA0KICAgIGRhdG9zX2FuYWxpdGljb3MgPSBsaXN0KA0KICAgICAgcmVzdW1lbl9oaXBvdGVzaXMgPSByZXN1bHRhZG9faGlwb3Rlc2lzJGRhdG9zLA0KICAgICAgZGV0YWxsZV9oaXBvdGVzaXMgPSByZXN1bHRhZG9faGlwb3Rlc2lzJGRhdG9zX2RldGFsbGFkb3MsDQogICAgICB2YXJpYWJsZXNfY2VudHJhbGVzID0gYW5hbGlzaXNfY2VudHJhbGlkYWQkZGF0b3MsDQogICAgICBhbmFsaXNpc19zZWN0b3JpYWwgPSBhbmFsaXNpc19zZWN0b3JlcyRkYXRvcw0KICAgICksDQogICAgdGFibGFzX3Jlc3VtZW4gPSB0YWJsYXNfcmVzdW1lbg0KICApKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIEZVTkNJw5NOIFBBUkEgQ1JFQVIgREFUT1MgREUgVEFCTEFTIFJFU1VNRU4gRElOQU1JQ0FTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyAxLiBEaXN0cmlidWNpw7NuIGRlIGNvcnJlbGFjaW9uZXMNCmRpc3RyaWJ1Y2lvbl9jb3IgPC0gZGF0YS5mcmFtZSgNCiAgTWFnbml0dWQgPSBjKCJNdXkgZnVlcnRlIiwgIk1vZGVyYWRhIiwgIkTDqWJpbCIpLA0KICBOX0NvcnJlbGFjaW9uZXMgPSBjKDEyLCA0LCAxNiksDQogIFJhbmdvX0NvcnJlbGFjaW9uID0gYygiWzAuNzUgLSAxXSIsICJbMC4zNSAtIDAuMzddIiwgIlswLjE1IC0gMC4xOV0iKSwNCiAgVmFyaWFibGVzX0ludm9sdWNyYWRhcyA9IGMoMTIsIDMsIDExKSwNCiAgUF9WYWxvcl9Qcm9tZWRpbyA9IGMoMC4wMDAsIDAuMDAyLCAwLjA0OCkNCikNCg0KIyAyLiBFdmFsdWFjacOzbiBkZSBoaXDDs3Rlc2lzDQpldmFsdWFjaW9uX2hpcG90ZXNpcyA8LSBkYXRhLmZyYW1lKA0KICBDYXRlZ29yaWFfSGlwb3Rlc2lzID0gYygiQ29ycmVsYWNpb25lcyBFeHBsb3JhdG9yaWFzIiwgIkhFMTogQ29uY29yZGFuY2lhIFNlY3RvcmlhbCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICJIRTI6IENvbXBsZWppZGFkIFZpdmllbmRhIiwgIkhFMzogRWZpY2llbmNpYSBUcmFuc3BvcnRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIkhFNDogQ29tcGxlamlkYWQgVGVtcG9yYWwiKSwNCiAgRXhwbG9yYXRvcmlhID0gYygyMCwgMCwgMCwgMCwgMCksDQogIENvbmZpcm1hZGEgPSBjKDAsIDQsIDQsIDIsIDIpLA0KICBQYXJjaWFsID0gYygwLCAwLCAwLCAwLCAwKSwNCiAgVG90YWwgPSBjKDIwLCA0LCA0LCAyLCAyKQ0KKQ0KDQojIDMuIFZhcmlhYmxlcyBtw6FzIGNlbnRyYWxlcw0KdmFyaWFibGVzX2NlbnRyYWxlcyA8LSBkYXRhLmZyYW1lKA0KICBWYXJpYWJsZSA9IGMoIkNsYXNpZmljYWNpb24gQWN0b3JlcyBpbnN0aXQiLCAiQ0ZHOiBFTEVDVFJJQ0lEQUQiLCAiR09COiBFTEVDVFJJQ0lEQUQiLA0KICAgICAgICAgICAgICAgIkNGRzogVklBTElEQUQiLCAiQ0ZHOiBUUkFOU1BPUlRFIiksDQogIE5fQ29uZXhpb25lcyA9IGMoMTAsIDIsIDIsIDgsIDIpLA0KICBDb3JyZWxhY2lvbl9Qcm9tZWRpbyA9IGMoMC4yNDUsIDEuMDAwLCAxLjAwMCwgMC4zMTAsIDAuOTMzKSwNCiAgQ29ycmVsYWNpb25fTWF4aW1hID0gYygwLjI0NSwgMS4wMDAsIDEuMDAwLCAwLjMxMCwgMC45MzMpDQopDQoNCiMgNC4gQW7DoWxpc2lzIHNlY3RvcmlhbA0KYW5hbGlzaXNfc2VjdG9yaWFsIDwtIGRhdGEuZnJhbWUoDQogIFNlY3Rvcl9QcmluY2lwYWwgPSBjKCJFbGVjdHJpY2lkYWQiLCAiSW50ZXJzZWN0b3JpYWwiLCAiVmlhbGlkYWQiLCAiQW1iaWVudGUvQ2FuYWxpemFjacOzbiIsDQogICAgICAgICAgICAgICAgICAgICAgIlRyYW5zcG9ydGUiLCAiVml2aWVuZGEiLCAiSW5mcmFlc3RydWN0dXJhIiksDQogIE5fQ29ycmVsYWNpb25lcyA9IGMoMiwgMiwgNCwgNiwgNiwgMTAsIDIpLA0KICBDb3JyZWxhY2lvbl9Qcm9tZWRpbyA9IGMoMS4wMDAsIDEuMDAwLCAwLjQ3MCwgMC40MzcsIDAuNDIyLCAwLjM5NCwgMC4xODUpLA0KICBDb3JyZWxhY2lvbl9NYXhpbWEgPSBjKDEuMDAwLCAxLjAwMCwgMC43NDgsIDEuMDAwLCAwLjkzMywgMC45NTAsIDAuMTg1KSwNCiAgQ29ycmVsYWNpb25lc19GdWVydGVzID0gYygyLCAyLCAwLCA2LCAyLCA0LCAwKQ0KKQ0KDQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT1DcmVhciBsYXMgdGFibGFzIGthYmxlPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Iw0KDQojIFRhYmxhIDE6IERpc3RyaWJ1Y2nDs24gZGUgY29ycmVsYWNpb25lcw0Ka2FibGVfZGlzdHJpYnVjaW9uIDwtIGRpc3RyaWJ1Y2lvbl9jb3IgJT4lDQogIGthYmxlKGZvcm1hdCA9ICJodG1sIiwNCiAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSAxOiBEaXN0cmlidWNpw7NuIGRlIENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgcG9yIE1hZ25pdHVkIiwNCiAgICAgICAgYWxpZ24gPSBjKCJsIiwgImMiLCAiYyIsICJjIiwgImMiKSwNCiAgICAgICAgY29sLm5hbWVzID0gYygiTWFnbml0dWQiLCAiTsKwIENvcnJlbGFjaW9uZXMiLCAiUmFuZ28gfM+BfCIsIA0KICAgICAgICAgICAgICAgICAgICAgIlZhcmlhYmxlcyBJbnZvbHVjcmFkYXMiLCAicC12YWxvciBQcm9tZWRpbyIpKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSwNCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRkFMU0UsDQogICAgICAgICAgICAgICAgZm9udF9zaXplID0gMTMsDQogICAgICAgICAgICAgICAgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lDQogIHJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiM2NEI1RjYiLCBjb2xvciA9ICJ3aGl0ZSIsIGZvbnRfc2l6ZSA9IDE0KSAlPiUNCiAgcm93X3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJhY2tncm91bmQgPSAiI0U1NzM3MyIsIGNvbG9yID0gIndoaXRlIikgJT4lICAjIE11eSBmdWVydGUgZW4gcm9qbyBjbGFybw0KICByb3dfc3BlYygyLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjODFDNzg0IiwgY29sb3IgPSAid2hpdGUiKSAlPiUgICMgTW9kZXJhZGEgZW4gdmVyZGUgY2xhcm8NCiAgcm93X3NwZWMoMywgYm9sZCA9IFRSVUUsIGJhY2tncm91bmQgPSAiI0ZGRjE3NiIsIGNvbG9yID0gImJsYWNrIikgJT4lICAjIETDqWJpbCBlbiBhbWFyaWxsbyBjbGFybw0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgd2lkdGggPSAiMTUlIikgJT4lDQogIGNvbHVtbl9zcGVjKDI6NSwgd2lkdGggPSAiMTUlIikgJT4lDQogIGZvb3Rub3RlKGdlbmVyYWwgPSAiQ2xhc2lmaWNhY2nDs246IE11eSBmdWVydGUgKHzPgXwgPiAwLjcpLCBNb2RlcmFkYSAoMC4zLTAuNSksIETDqWJpbCAofM+BfCA8IDAuMykiLA0KICAgICAgICAgICBnZW5lcmFsX3RpdGxlID0gIk5vdGE6ICIpDQoNCiMgVGFibGEgMjogRXZhbHVhY2nDs24gZGUgaGlww7N0ZXNpcw0Ka2FibGVfaGlwb3Rlc2lzIDwtIGV2YWx1YWNpb25faGlwb3Rlc2lzICU+JQ0KICBrYWJsZShmb3JtYXQgPSAiaHRtbCIsDQogICAgICAgIGNhcHRpb24gPSAiVGFibGEgMjogRXZhbHVhY2nDs24gZGUgSGlww7N0ZXNpcyBkZSBJbnZlc3RpZ2FjacOzbiIsDQogICAgICAgIGFsaWduID0gYygibCIsICJjIiwgImMiLCAiYyIsICJjIiwgImMiKSwNCiAgICAgICAgY29sLm5hbWVzID0gYygiSGlww7N0ZXNpcyIsICJFeHBsb3JhdG9yaWEiLCAiQ29uZmlybWFkYSIsIA0KICAgICAgICAgICAgICAgICAgICAgIlBhcmNpYWwiLCAiVG90YWwiKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IDEzLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIpICU+JQ0KICByb3dfc3BlYygwLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjNDJBNUY1IiwgY29sb3IgPSAid2hpdGUiLCBmb250X3NpemUgPSAxNCkgJT4lDQogIHJvd19zcGVjKDEsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNFM0YyRkQiLCBjb2xvciA9ICJibGFjayIpICU+JSAgIyBFeHBsb3JhdG9yaWFzDQogIHJvd19zcGVjKDI6NSwgYmFja2dyb3VuZCA9ICIjRThGNUU4IikgJT4lICAjIENvbmZpcm1hZGFzDQogIHJvd19zcGVjKDIsIGJhY2tncm91bmQgPSAiI0M4RTZDOSIpICU+JSAgIyBIRTENCiAgcm93X3NwZWMoMywgYmFja2dyb3VuZCA9ICIjQTVENkE3IikgJT4lICAjIEhFMg0KICByb3dfc3BlYyg0LCBiYWNrZ3JvdW5kID0gIiM4MUM3ODQiKSAlPiUgICMgSEUzDQogIHJvd19zcGVjKDUsIGJhY2tncm91bmQgPSAiIzY2QkI2QSIpICU+JSAgIyBIRTQNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIHdpZHRoID0gIjM1JSIpICU+JQ0KICBjb2x1bW5fc3BlYygyOjUsIHdpZHRoID0gIjEwJSIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIkhpcMOzdGVzaXMgY29uZmlybWFkYXMgY3VhbmRvIGN1bXBsZW4gY3JpdGVyaW9zIGVzdGFkw61zdGljb3MgeSB0ZcOzcmljb3MgcHJlZGVmaW5pZG9zIiwNCiAgICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICJOb3RhOiAiKQ0KDQojIFRhYmxhIDM6IFZhcmlhYmxlcyBtw6FzIGNlbnRyYWxlcw0Ka2FibGVfY2VudHJhbGVzIDwtIHZhcmlhYmxlc19jZW50cmFsZXMgJT4lDQogIHNlbGVjdChWYXJpYWJsZSA9IFZhcmlhYmxlLCANCiAgICAgICAgIENvbmV4aW9uZXMgPSBOX0NvbmV4aW9uZXMsIA0KICAgICAgICAgYM+BIFByb21lZGlvYCA9IENvcnJlbGFjaW9uX1Byb21lZGlvLCANCiAgICAgICAgIGDPgSBNw6F4aW1vYCA9IENvcnJlbGFjaW9uX01heGltYSkgJT4lDQogIGthYmxlKGZvcm1hdCA9ICJodG1sIiwNCiAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSAzOiBUb3AgNSBWYXJpYWJsZXMgTcOhcyBDZW50cmFsZXMgZW4gbGEgUmVkIGRlIENvcnJlbGFjaW9uZXMiLA0KICAgICAgICBhbGlnbiA9IGMoImwiLCAiYyIsICJjIiwgImMiKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IDEzLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIpICU+JQ0KICByb3dfc3BlYygwLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjQUI0N0JDIiwgY29sb3IgPSAid2hpdGUiLCBmb250X3NpemUgPSAxNCkgJT4lDQogIHJvd19zcGVjKDEsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNGM0U1RjUiLCBjb2xvciA9ICJibGFjayIpICU+JSAgIyBUb3AgMQ0KICByb3dfc3BlYygyOjMsIGJhY2tncm91bmQgPSAiI0Y4QkJEOSIpICU+JSAgIyBUb3AgMi0zDQogIHJvd19zcGVjKDQ6NSwgYmFja2dyb3VuZCA9ICIjRkNFNEVDIikgJT4lICAjIFRvcCA0LTUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIHdpZHRoID0gIjM1JSIpICU+JQ0KICBjb2x1bW5fc3BlYygyOjQsIHdpZHRoID0gIjE1JSIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIkNlbnRyYWxpZGFkIGJhc2FkYSBlbiBuw7ptZXJvIGRlIGNvbmV4aW9uZXMgc2lnbmlmaWNhdGl2YXMgeSBmdWVyemEgcHJvbWVkaW8gZGUgY29ycmVsYWNpb25lcyIsDQogICAgICAgICAgIGdlbmVyYWxfdGl0bGUgPSAiTm90YTogIikNCg0KIyBUYWJsYSA0OiBBbsOhbGlzaXMgc2VjdG9yaWFsDQprYWJsZV9zZWN0b3JpYWwgPC0gYW5hbGlzaXNfc2VjdG9yaWFsICU+JQ0KICBzZWxlY3QoU2VjdG9yID0gU2VjdG9yX1ByaW5jaXBhbCwgDQogICAgICAgICBgTsKwIENvcnJlbGFjaW9uZXNgID0gTl9Db3JyZWxhY2lvbmVzLA0KICAgICAgICAgYM+BIFByb21lZGlvYCA9IENvcnJlbGFjaW9uX1Byb21lZGlvLA0KICAgICAgICAgYM+BIE3DoXhpbW9gID0gQ29ycmVsYWNpb25fTWF4aW1hLA0KICAgICAgICAgYENvcnJlbGFjaW9uZXMgRnVlcnRlc2AgPSBDb3JyZWxhY2lvbmVzX0Z1ZXJ0ZXMpICU+JQ0KICBrYWJsZShmb3JtYXQgPSAiaHRtbCIsDQogICAgICAgIGNhcHRpb24gPSAiVGFibGEgNDogQW7DoWxpc2lzIFNlY3RvcmlhbCBkZSBDb3JyZWxhY2lvbmVzIFNpZ25pZmljYXRpdmFzIiwNCiAgICAgICAgYWxpZ24gPSBjKCJsIiwgImMiLCAiYyIsICJjIiwgImMiKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIiksDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIGZvbnRfc2l6ZSA9IDEzLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImNlbnRlciIpICU+JQ0KICByb3dfc3BlYygwLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjNERCNkFDIiwgY29sb3IgPSAid2hpdGUiLCBmb250X3NpemUgPSAxNCkgJT4lDQogIHJvd19zcGVjKDE6MiwgYm9sZCA9IFRSVUUsIGJhY2tncm91bmQgPSAiI0IyREZEQiIsIGNvbG9yID0gImJsYWNrIikgJT4lICAjIEVsZWN0cmljaWRhZCBlIEludGVyc2VjdG9yaWFsICjPgT0xLjApDQogIHJvd19zcGVjKDYsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNDOEU2QzkiKSAlPiUgICMgVml2aWVuZGEgKG3DoXMgY29ycmVsYWNpb25lcykNCiAgcm93X3NwZWMoNDo1LCBiYWNrZ3JvdW5kID0gIiNFMEYyRjEiKSAlPiUgICMgQW1iaWVudGUgeSBUcmFuc3BvcnRlDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCB3aWR0aCA9ICIyNSUiKSAlPiUNCiAgY29sdW1uX3NwZWMoMjo1LCB3aWR0aCA9ICIxNSUiKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICJTZWN0b3JlcyBvcmRlbmFkb3MgcG9yIGZ1ZXJ6YSBwcm9tZWRpbyBkZSBjb3JyZWxhY2lvbmVzIHzPgXwiLA0KICAgICAgICAgICBnZW5lcmFsX3RpdGxlID0gIk5vdGE6ICIpDQoNCiMgTW9zdHJhciBsYXMgdGFibGFzDQpjYXQoIlxuIyMjIFJlc3VsdGFkb3MgZGVsIEFuw6FsaXNpcyBkZSBDb3JyZWxhY2lvbmVzXG5cbiIpDQpjYXQoIkEgY29udGludWFjacOzbiBzZSBwcmVzZW50YW4gbGFzIHRhYmxhcyByZXN1bWVuIGRlbCBhbsOhbGlzaXM6XG5cbiIpDQoNCmthYmxlX2Rpc3RyaWJ1Y2lvbg0KY2F0KCJcbiIpDQprYWJsZV9oaXBvdGVzaXMNCmNhdCgiXG4iKQ0Ka2FibGVfY2VudHJhbGVzDQpjYXQoIlxuIikNCmthYmxlX3NlY3RvcmlhbA0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRUpFQ1VDScOTTiBBVVRPTcOBVElDQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgRWplY3V0YXIgYW7DoWxpc2lzIGNvbXBsZXRvIHNpIGxvcyBkYXRvcyBlc3TDoW4gZGlzcG9uaWJsZXMNCmlmIChleGlzdHMoImNvcl9yZXN1bHRzIikgJiYgZXhpc3RzKCJjb3JfZGYiKSkgew0KICByZXN1bHRhZG9zX2ZpbmFsZXMgPC0gZWplY3V0YXJfYW5hbGlzaXNfY29tcGxldG9fY29ycmVsYWNpb25lcyhjb3JfcmVzdWx0cywgY29yX2RmKQ0KICANCiAgIyBEZXNjb21lbnRhciBwYXJhIGd1YXJkYXIgYXV0b23DoXRpY2FtZW50ZToNCiAgIyBndWFyZGFyX3Jlc3VsdGFkb3NfY29tcGxldG9zKHJlc3VsdGFkb3NfZmluYWxlcykNCn0gZWxzZSB7DQogIGNhdCgiRXNwZXJhbmRvIGRhdG9zICdjb3JfcmVzdWx0cycgeSAnY29yX2RmJyBwYXJhIGVqZWN1dGFyIGVsIGFuw6FsaXNpcy4uLlxuIikNCn0NCg0KIyBDcmVhciB1bmEgZnVuY2nDs24gcGFyYSBnZW5lcmFyIGdyw6FmaWNvcyBkZSBkaXNwZXJzacOzbiBjb24gU3BlYXJtYW4NCnBsb3Rfc3BlYXJtYW4gPC0gZnVuY3Rpb24oZGF0YSwgeF92YXIsIHlfdmFyLCB4X2xhYmVsLCB5X2xhYmVsLCB0aXRsZSkgew0KICBnZ3NjYXR0ZXIoDQogICAgZGF0YSA9IGRhdGEsDQogICAgeCA9IHhfdmFyLA0KICAgIHkgPSB5X3ZhciwNCiAgICBhZGQgPSAicmVnLmxpbmUiLCAjIEHDsWFkaXIgbMOtbmVhIGRlIHJlZ3Jlc2nDs24NCiAgICBjb25mLmludCA9IFRSVUUsICMgQcOxYWRpciBpbnRlcnZhbG8gZGUgY29uZmlhbnphDQogICAgY29yLmNvZWYgPSBUUlVFLCAjIE1vc3RyYXIgY29lZmljaWVudGUNCiAgICBjb3IubWV0aG9kID0gInNwZWFybWFuIiwgIyBNw6l0b2RvIGRlIGNvcnJlbGFjacOzbg0KICAgIHRpdGxlID0gdGl0bGUsDQogICAgeGxhYiA9IHhfbGFiZWwsDQogICAgeWxhYiA9IHlfbGFiZWwsDQogICAgZm9udC54ID0gMTAsDQogICAgZm9udC55ID0gMTAsDQogICAgY29yLmNvZWZmLmFyZ3MgPSBsaXN0KHNpemUgPSA0LCBjb2xvciA9ICJibHVlIikgIyBFc3RpbG8gZGVsIGNvZWZpY2llbnRlDQogICkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoDQogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikNCiAgICApDQp9DQoNCg0KIyBIRTE6IENGRzogRUxFQ1RSSUNJREFEIHZzIEdPQjogRUxFQ1RSSUNJREFEDQojIChBc3VtaWVuZG8gcXVlIHRpZW5lcyBjb2x1bW5hcyAiQ0ZHX0VMRUNUUklDSURBRCIgeSAiR09CX0VMRUNUUklDSURBRCIgZW4gZGZfY29yKQ0KcDEgPC0gcGxvdF9zcGVhcm1hbigNCiAgZGZfY29yLA0KICAiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHX0VMRUNUUklDSURBRCIsDQogICJDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX0dPQkVSTkFDSU9OX0VMRUNUUklDSURBRCIsDQogICJDRkc6IEVMRUNUUklDSURBRCIsDQogICJHT0I6IEVMRUNUUklDSURBRCIsDQogICJIRTE6IENvcnJlbGFjacOzbiBQZXJmZWN0YSBlbnRyZSBEaWFnbsOzc3RpY28geSBHZXN0acOzbiBlbiBFbGVjdHJpY2lkYWQgKM+BID0gMS4wKSINCikNCg0KIyBIRTI6IENGRzogVklWSUVOREEgdnMgR09COiBWSVZJRU5EQQ0KcDIgPC0gcGxvdF9zcGVhcm1hbigNCiAgZGZfY29yLA0KICAiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHX1ZJVklFTkRBIiwNCiAgIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT05fVklWSUVOREEiLA0KICAiQ0ZHOiBWSVZJRU5EQSIsDQogICJHT0I6IFZJVklFTkRBIiwNCiAgIkhFMjogQWx0YSBDb3JyZWxhY2nDs24gZW4gVml2aWVuZGEgKM+BID0gMC45NSkiDQopDQoNCiMgSEUzOiBDbGFzaWZpY2FjaW9uX0FjdG9yZXNfaW5zdGl0dWNpb25hbGVzIHZzIENGRzogVklWSUVOREENCnAzIDwtIHBsb3Rfc3BlYXJtYW4oDQogIGRmX2NvciwNCiAgIkNsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMiLA0KICAiQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHX1ZJVklFTkRBIiwNCiAgIkNsYXNpZmljYWNpw7NuIEFjdG9yZXMgKDE9QWx0byBOaXZlbCkiLA0KICAiQ0ZHOiBWSVZJRU5EQSIsDQogICJIRTM6IENlbnRyYWxpemFjacOzbiBlbiBQcm9ibGVtYXMgZGUgVml2aWVuZGEgKM+BID0gLTAuMzY4KSINCikNCg0KIyBIRTQ6IFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8gdnMgR09COiBUUkFOU1BPUlRFDQpwNCA8LSBwbG90X3NwZWFybWFuKA0KICBkZl9jb3IsDQogICJSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPIiwNCiAgIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fR09CRVJOQUNJT05fVFJBTlNQT1JURSIsDQogICJSYXRpbyBBQ0EgKEVmZWN0aXZpZGFkKSIsDQogICJHT0I6IFRSQU5TUE9SVEUiLA0KICAiSEU0OiBFZmVjdGl2aWRhZCBMZXZlIGVuIFByb3llY3RvcyBkZSBUcmFuc3BvcnRlICjPgSA9IDAuMTY3KSINCikNCg0KIyBIRTU6IFBMQVpPUyB2cyBDRkc6IElORlJBRVNUUlVDVFVSQQ0KcDUgPC0gcGxvdF9zcGVhcm1hbigNCiAgZGZfY29yLA0KICAiUExBWk9TIiwNCiAgIkNMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGR19JTkZSQUVTVFJVQ1RVUkEiLA0KICAiUExBWk9TICgxPUNvcnRvLCAyPU1lZGlhbm8pIiwNCiAgIkNGRzogSU5GUkFFU1RSVUNUVVJBIiwNCiAgIkhFNTogUGxhem9zIENvcnRvcyBwYXJhIEluZnJhZXN0cnVjdHVyYSAoz4EgPSAtMC4xODUpIg0KKQ0KDQojIE1vc3RyYXIgbG9zIGdyw6FmaWNvcyAocHVlZGVzIG1vc3RyYXJsb3MgZGUgdW5vIGVuIHVubyBvIGVuIHVuYSBjdWFkcsOtY3VsYSkNCnAxDQpwMg0KcDMNCnA0DQpwNQ0KDQoNCiMgT3BjaW9uYWw6IE1vc3RyYXJsb3MgZW4gdW5hIGN1YWRyw61jdWxhIGRlIDJ4MyAoZGVqYW5kbyB1biBlc3BhY2lvIHZhY8OtbykNCg0KZ2dhcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBwNSwgbmNvbCA9IDIsIG5yb3cgPSAzKQ0KDQojIyMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLUhpcMOzdGVzaXMgZGUgbGEgaW52ZXN0aWdhY2nDs24tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBDcmVhciBsYSB0YWJsYSBkZSBoaXDDs3Rlc2lzDQp0YWJsYV9oaXBvdGVzaXMgPC0gZGF0YS5mcmFtZSgNCiAgSGlww7N0ZXNpcyA9IGMoDQogICAgIioqSGlww7N0ZXNpcyBHZW5lcmFsIChIRykqKiIsDQogICAgIkV4aXN0ZSB1bmEgcmVsYWNpw7NuIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmEgZW50cmUgbGEgdGlwb2xvZ8OtYSBkZSBsb3MgbnVkb3MgY3LDrXRpY29zIGlkZW50aWZpY2Fkb3MgKENGRyksIGxhIGNsYXNpZmljYWNpw7NuIGRlIGxvcyBhY3RvcmVzIGluc3RpdHVjaW9uYWxlcyAoR29iZXJuYWNpw7NuKSB5IGxhIGVmZWN0aXZpZGFkIGVuIGxhIGVqZWN1Y2nDs24gZGUgbG9zIHByb3llY3RvcyAoUkFUSU8gQUNBKSBlbiBsYXMgY29tdW5hcyBkZWwgRXN0YWRvIE3DqXJpZGEgZHVyYW50ZSBlbCBwZXLDrW9kbyAyMDE4LTIwMjUuIiwNCiAgICAiIiwNCiAgICAiKipIRTE6KiogRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEgbXV5IGZ1ZXJ0ZSB5IHNpZ25pZmljYXRpdmEgZW50cmUgbGEgaWRlbnRpZmljYWNpw7NuIGRlIG51ZG9zIGNyw610aWNvcyByZWxhY2lvbmFkb3MgY29uIEVMRUNUUklDSURBRChDRkcpIHkgbGEgcGFydGljaXBhY2nDs24gZGUgbGEgR29iZXJuYWNpw7NuIGVuIGVsIMOhcmVhIGRlIEVMRUNUUklDSURBRChHT0IpIGVuIGxvcyBwcm95ZWN0b3MgQUNBLiIsDQogICAgIioqSEUyOioqIEV4aXN0ZSB1bmEgY29ycmVsYWNpw7NuIHBvc2l0aXZhIG11eSBmdWVydGUgeSBzaWduaWZpY2F0aXZhIGVudHJlIGxhIGlkZW50aWZpY2FjacOzbiBkZSBudWRvcyBjcsOtdGljb3MgZGUgVklWSUVOREEoQ0ZHKSB5IGxhIHBhcnRpY2lwYWNpw7NuIGRlIGxhIEdvYmVybmFjacOzbiBlbiBlbCDDoXJlYSBkZSBWSVZJRU5EQShHT0IpIGVuIGxvcyBwcm95ZWN0b3MgQUNBLiIsDQogICAgIioqSEUzOioqIEV4aXN0ZSB1bmEgY29ycmVsYWNpw7NuIG5lZ2F0aXZhIG1vZGVyYWRhIHkgc2lnbmlmaWNhdGl2YSBlbnRyZSBsYSBDbGFzaWZpY2FjacOzbiBkZSBBY3RvcmVzIEluc3RpdHVjaW9uYWxlcyAoZG9uZGUgdmFsb3JlcyBtw6FzIGJham9zIGluZGljYW4gYWN0b3JlcyBkZSBtYXlvciBuaXZlbCBqZXLDoXJxdWljbywgY29tbyBNaW5pc3RlcmlvcyB5IEdvYmVybmFjaW9uZXMpIHkgbGEgcHJlc2VuY2lhIGRlIG51ZG9zIGNyw610aWNvcyBkZSBWSVZJRU5EQSAoQ0ZHKS4iLA0KICAgICIqKkhFNDoqKiBFeGlzdGUgdW5hIGNvcnJlbGFjacOzbiBwb3NpdGl2YSBkw6liaWwsIHBlcm8gc2lnbmlmaWNhdGl2YSwgZW50cmUgZWwgUkFUSU8gQUNBIFBST1lFQ1RPIENVTE1JTkFETyB5IGxhIHBhcnRpY2lwYWNpw7NuIGRlIGxhIEdvYmVybmFjacOzbiBlbiBlbCDDoXJlYSBkZSBUUkFOU1BPUlRFKEdPQikgZW4gbG9zIHByb3llY3RvcyBBQ0EuIiwNCiAgICAiKipIRTU6KiogTG9zIFBMQVpPUyBkZSBlamVjdWNpw7NuIGRlIGxvcyBwcm95ZWN0b3MgKGRvbmRlIHZhbG9yZXMgbcOhcyBhbHRvcyBpbmRpY2FuIHBsYXpvcyBtw6FzIGxhcmdvcykgc2UgcmVsYWNpb25hbiBkZSBtYW5lcmEgaW52ZXJzYSB5IGTDqWJpbCwgeSBzaWduaWZpY2F0aXZhbWVudGUsIGNvbiBsYSBwcmVzZW5jaWEgZGUgbnVkb3MgY3LDrXRpY29zIGRlIElORlJBRVNUUlVDVFVSQShDRkcpIGVuIGxvcyBwcm95ZWN0b3MgQUNBLiINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgTW9zdHJhciBsYSB0YWJsYQ0Ka2FibGUodGFibGFfaGlwb3Rlc2lzLCBjb2wubmFtZXMgPSBOVUxMLCBjYXB0aW9uID0gIlRhYmxhIGRlIEhpcMOzdGVzaXMgMzogSGlww7N0ZXNpcyBkZSBJbnZlc3RpZ2FjacOzbiBzb2JyZSBsYSBDb3JyZWxhY2nDs24gZW50cmUgUHJveWVjdG9zIEFDQSB5IE51ZG9zIENyw610aWNvcyIsIGZvcm1hdCA9ICJodG1sIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpICU+JQ0KICBjb2x1bW5fc3BlYygxLCB3aWR0aCA9ICIxMDAlIikNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLURhdG9zIGRlIHZlcmlmaWNhY2nDs24gZGUgaGlww7N0ZXNpcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQp2ZXJpZmljYWNpb24gPC0gZGF0YS5mcmFtZSgNCiAgSGlww7N0ZXNpcyA9IGMoIkhFMSIsICJIRTIiLCAiSEUzIiwgIkhFNCIsICJIRTUiKSwNCiAgVmFyaWFibGVfMSA9IGMoIkNGRzogRUxFQ1RSSUNJREFEIiwgIkNGRzogVklWSUVOREEiLCAiQ2xhc2lmaWNhY2lvbl9BY3RvcmVzX2luc3RpdCIsICJSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPIiwgIlBMQVpPUyIpLA0KICBWYXJpYWJsZV8yID0gYygiR09COiBFTEVDVFJJQ0lEQUQiLCAiR09COiBWSVZJRU5EQSIsICJDRkc6IFZJVklFTkRBIiwgIkdPQjogVFJBTlNQT1JURSIsICJDRkc6IElORlJBRVNUUlVDVFVSQSIpLA0KICBgUmhvICjPgSlgID0gYygxLjAwMCwgMC45NTAsIC0wLjM2OCwgMC4xNjcsIC0wLjE4NSksDQogIGBwLXZhbG9yYCA9IGMoMC4wMDAwMDAwLCAwLjAwMDAwMDAsIDAuMDAwMDAwMSwgMC4wMTg5LCAwLjAwODkpLA0KICBWZXJpZmljYWNpw7NuID0gYygiQ09SUk9CT1JBREEiLCAiQ09SUk9CT1JBREEiLCAiQ09SUk9CT1JBREEiLCAiUEFSQ0lBTE1FTlRFIENPUlJPQk9SQURBIiwgIkNPUlJPQk9SQURBIiksDQogIEludGVycHJldGFjacOzbiA9IGMoDQogICAgIkNvcnJlbGFjacOzbiBwb3NpdGl2YSBwZXJmZWN0YSB5IHNpZ25pZmljYXRpdmEuIEFsaW5lYWNpw7NuIGFic29sdXRhIGVudHJlIGRpYWduw7NzdGljbyB5IGdlc3Rpw7NuLiIsDQogICAgIkNvcnJlbGFjacOzbiBwb3NpdGl2YSBtdXkgZnVlcnRlIHkgc2lnbmlmaWNhdGl2YS4gQWx0YSBlZmVjdGl2aWRhZCBlbiBlbCBtYXBlbyB5IGFzaWduYWNpw7NuLiIsDQogICAgIkNvcnJlbGFjacOzbiBuZWdhdGl2YSBtb2RlcmFkYSB5IHNpZ25pZmljYXRpdmEuIFByb2JsZW1hcyBkZSB2aXZpZW5kYSBnZXN0aW9uYWRvcyBwb3IgYWN0b3JlcyBkZSBhbHRvIG5pdmVsLiIsDQogICAgIkNvcnJlbGFjacOzbiBwb3NpdGl2YSBkw6liaWwgcGVybyBzaWduaWZpY2F0aXZhLiBSZWxhY2nDs24gbcOtbmltYSBlbnRyZSBjdWxtaW5hY2nDs24geSBwcm95ZWN0b3MgZGUgdHJhbnNwb3J0ZS4iLA0KICAgICJDb3JyZWxhY2nDs24gbmVnYXRpdmEgZMOpYmlsIHBlcm8gc2lnbmlmaWNhdGl2YS4gUHJveWVjdG9zIGRlIGluZnJhZXN0cnVjdHVyYSB0aWVuZGVuIGEgdGVuZXIgcGxhem9zIG3DoXMgY29ydG9zLiINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgTW9zdHJhciB0YWJsYSBkZSB2ZXJpZmljYWNpw7NuDQprYWJsZSh2ZXJpZmljYWNpb24sIGNhcHRpb24gPSAiVGFibGEgWC4xOiBWZXJpZmljYWNpw7NuIGRlIEhpcMOzdGVzaXMgRXNwZWPDrWZpY2FzIiwgYm9va3RhYnMgPSBUUlVFLCBhbGlnbiA9ICJjIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpKSAlPiUNCiAgY29sdW1uX3NwZWMoMTozLCB3aWR0aCA9ICI4ZW0iKSAlPiUNCiAgY29sdW1uX3NwZWMoNDo1LCB3aWR0aCA9ICI2ZW0iKSAlPiUNCiAgY29sdW1uX3NwZWMoNiwgd2lkdGggPSAiMTBlbSIpICU+JQ0KICBjb2x1bW5fc3BlYyg3LCB3aWR0aCA9ICIyMGVtIikgJT4lDQogIHJvd19zcGVjKHdoaWNoKHZlcmlmaWNhY2lvbiRWZXJpZmljYWNpw7NuID09ICJDT1JST0JPUkFEQSIpLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjZTZmMmU2IikgJT4lDQogIHJvd19zcGVjKHdoaWNoKHZlcmlmaWNhY2lvbiRWZXJpZmljYWNpw7NuID09ICJQQVJDSUFMTUVOVEUgQ09SUk9CT1JBREEiKSwgYm9sZCA9IFRSVUUsIGJhY2tncm91bmQgPSAiI2ZmZjNjZCIpDQoNCiMjLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoqSGFsbGF6Z29zIGFkaWNpb25hbGVzIGNsYXZlKiotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KaGFsbGF6Z29zIDwtIGRhdGEuZnJhbWUoDQogIEhhbGxhemdvID0gYygiQ29udmVyZ2VuY2lhIERpYWduw7NzdGljby1JbnN0aXR1Y2nDs24iLCAiTGEgR3JhbiBEZXNjb25leGnDs246IFBsYW5pZmljYWNpw7NuIHZzLiBSZXN1bHRhZG9zIiksDQogIFZhcmlhYmxlXzEgPSBjKCJDRkc6IEFNQklFTlRFIiwgIlJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8iKSwNCiAgVmFyaWFibGVfMiA9IGMoIkdPQjogQ0FOQUxJWkFDSU9OIiwgIkN1YWxxdWllciBvdHJhIHZhcmlhYmxlIiksDQogIGBSaG8gKM+BKWAgPSBjKDEuMDAwLCAiTm8gaGF5IGNvcnJlbGFjaW9uZXMgZnVlcnRlcy9tb2RlcmFkYXMiKSwNCiAgYHAtdmFsb3JgID0gYygwLjAwMDAwMDAsICJOL0EiKSwNCiAgSW50ZXJwcmV0YWNpw7NuID0gYygNCiAgICAiU2UgaWRlbnRpZmljYXJvbiBvdHJhcyBjb3JyZWxhY2lvbmVzIG11eSBmdWVydGVzIHkgcGVyZmVjdGFzIChwLmVqLiwgQ0ZHOiBBTUJJRU5URSAmIEdPQjogQ0FOQUxJWkFDSU9OLCDPgT0xLjApLiBFc3RvIGluZGljYSB1bmEgcnV0YSBjcsOtdGljYSBiaWVuIGRlZmluaWRhIHF1ZSBjb25lY3RhIGxhIG5lY2VzaWRhZCBjb211bml0YXJpYSBjb24gbGEgaW5zdGFuY2lhIHJlc3BvbnNhYmxlLiIsDQogICAgIkVsIGhhbGxhemdvIG3DoXMgY3LDrXRpY286IG5vIHNlIGVuY29udHJhcm9uIGNvcnJlbGFjaW9uZXMgZnVlcnRlcyBvIG1vZGVyYWRhcyBlbnRyZSBsYSB2YXJpYWJsZSBkZSByZXN1bHRhZG8gKFJBVElPX0FDQSkgeSBuaW5ndW5hIG90cmEgKGV4Y2VwdG8gbGEgZMOpYmlsIGNvbiBUUkFOU1BPUlRFKS4gRXN0byBldmlkZW5jaWEgdW5hIGJyZWNoYSBlc3RydWN0dXJhbCBlbnRyZSBsYSBwbGFuaWZpY2FjacOzbiB5IGxhIGVqZWN1Y2nDs24gZWZlY3RpdmEgZGUgbG9zIHByb3llY3Rvcy4iDQogICksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQprYWJsZShoYWxsYXpnb3MsIGNhcHRpb24gPSAiVGFibGEgWC4yOiBIYWxsYXpnb3MgQWRpY2lvbmFsZXMgQ2xhdmUiLCBib29rdGFicyA9IFRSVUUsIGFsaWduID0gImMiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpICU+JQ0KICBjb2x1bW5fc3BlYygxLCB3aWR0aCA9ICIyMGVtIikgJT4lDQogIGNvbHVtbl9zcGVjKDI6Mywgd2lkdGggPSAiMTBlbSIpICU+JQ0KICBjb2x1bW5fc3BlYyg0OjUsIHdpZHRoID0gIjZlbSIpICU+JQ0KICBjb2x1bW5fc3BlYyg2LCB3aWR0aCA9ICIzMGVtIikNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSoqVGFibGFzIHBhcmEgZWwgYW5leG8gZGUgbGEgbW9ub2dyYWbDrWEqKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBQcmltZXJvLCBhc2VndXLDqW1vbm9zIGRlIHF1ZSBsb3Mgbm9tYnJlcyBkZSBsYXMgdmFyaWFibGVzIG5vIHNlYW4gZGVtYXNpYWRvIGxhcmdvcw0KdGFibGFfYW5leG8gPC0gdGFibGFfY29lZl9zcGVhcm1hbiAlPiUNCiAgbXV0YXRlKA0KICAgIFZhcmlhYmxlMSA9IHN1YnN0cihWYXJpYWJsZTEsIDEsIDQwKSwNCiAgICBWYXJpYWJsZTIgPSBzdWJzdHIoVmFyaWFibGUyLCAxLCA0MCkNCiAgKQ0KDQojIERpdmlkaXIgbGEgdGFibGEgZW4gcGFydGVzIG1hbmVqYWJsZXMgKHBvciBlamVtcGxvLCBwb3Igc2lnbmlmaWNhbmNpYSB5IG1hZ25pdHVkKSBwYXJhIGV2aXRhciBww6FnaW5hcyBpbnRlcm1pbmFibGVzDQojIFBhcnRlIDE6IENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgeSBNdXkgRnVlcnRlcy9GdWVydGVzDQpwYXJ0ZTEgPC0gdGFibGFfYW5leG8gJT4lDQogIGZpbHRlcihTaWduaWZpY2F0aXZhID09ICJTw60iICYgTWFnbml0dWQgJWluJSBjKCJNdXkgZnVlcnRlIiwgIkZ1ZXJ0ZSIpKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhDb3JyZWxhY2lvbikpKQ0KDQojIFBhcnRlIDI6IENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgeSBNb2RlcmFkYXMNCnBhcnRlMiA8LSB0YWJsYV9hbmV4byAlPiUNCiAgZmlsdGVyKFNpZ25pZmljYXRpdmEgPT0gIlPDrSIgJiBNYWduaXR1ZCA9PSAiTW9kZXJhZGEiKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhDb3JyZWxhY2lvbikpKQ0KDQojIFBhcnRlIDM6IENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgeSBEw6liaWxlcw0KcGFydGUzIDwtIHRhYmxhX2FuZXhvICU+JQ0KICBmaWx0ZXIoU2lnbmlmaWNhdGl2YSA9PSAiU8OtIiAmIE1hZ25pdHVkID09ICJEw6liaWwiKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhDb3JyZWxhY2lvbikpKQ0KDQojIFBhcnRlIDQ6IENvcnJlbGFjaW9uZXMgTk8gU2lnbmlmaWNhdGl2YXMgKHNvbG8gbGFzIG3DoXMgZnVlcnRlcyBwYXJhIG5vIGFicnVtYXIpDQpwYXJ0ZTQgPC0gdGFibGFfYW5leG8gJT4lDQogIGZpbHRlcihTaWduaWZpY2F0aXZhID09ICJObyIpICU+JQ0KICBhcnJhbmdlKGRlc2MoYWJzKENvcnJlbGFjaW9uKSkpICU+JQ0KICBoZWFkKDIwKSAjIFNvbG8gbGFzIDIwIG3DoXMgZnVlcnRlcyAoYXVucXVlIG5vIHNpZ25pZmljYXRpdmFzKQ0KDQpjYXQoIiMjIyBQYXJ0ZSAxOiBDb3JyZWxhY2lvbmVzIFNpZ25pZmljYXRpdmFzIChwIDwgMC4wNSkgLSBNdXkgRnVlcnRlcyB5IEZ1ZXJ0ZXNcbiIpDQprYWJsZShwYXJ0ZTEsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJBbmV4byBYLjE6IENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgLSBNdXkgRnVlcnRlcyB5IEZ1ZXJ0ZXMiKSAlPiUNCiAga2FibGVfc3R5bGluZygpICU+JQ0KICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiNDAwcHgiKQ0KDQpjYXQoIlxuXG4jIyMgUGFydGUgMjogQ29ycmVsYWNpb25lcyBTaWduaWZpY2F0aXZhcyAocCA8IDAuMDUpIC0gTW9kZXJhZGFzXG4iKQ0Ka2FibGUocGFydGUyLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiQW5leG8gWC4yOiBDb3JyZWxhY2lvbmVzIFNpZ25pZmljYXRpdmFzIC0gTW9kZXJhZGFzIikgJT4lDQogIGthYmxlX3N0eWxpbmcoKSAlPiUNCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjQwMHB4IikNCg0KY2F0KCJcblxuIyMjIFBhcnRlIDM6IENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgKHAgPCAwLjA1KSAtIETDqWJpbGVzXG4iKQ0Ka2FibGUocGFydGUzLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiQW5leG8gWC4zOiBDb3JyZWxhY2lvbmVzIFNpZ25pZmljYXRpdmFzIC0gRMOpYmlsZXMiKSAlPiUNCiAga2FibGVfc3R5bGluZygpICU+JQ0KICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiNDAwcHgiKQ0KDQpjYXQoIlxuXG4jIyMgUGFydGUgNDogQ29ycmVsYWNpb25lcyBOTyBTaWduaWZpY2F0aXZhcyAocCA+IDAuMDUpIC0gVG9wIDIwIHBvciBNYWduaXR1ZFxuIikNCmthYmxlKHBhcnRlNCwgZm9ybWF0ID0gImh0bWwiLCBjYXB0aW9uID0gIkFuZXhvIFguNDogQ29ycmVsYWNpb25lcyBOTyBTaWduaWZpY2F0aXZhcyAtIFRvcCAyMCIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKCkgJT4lDQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI0MDBweCIpDQpgYGANCg0KIyMqKk1vZGVsbyBkZSBDb3JyZWxhY2nDs24gR2VuZXJhbCoqDQoNCiAgUGFyYSBndWlhciBlbCBhbsOhbGlzaXMgZGUgY29ycmVsYWNpw7NuIGVudHJlIGxvcyBwcm95ZWN0b3MgY29tdW5pdGFyaW9zIGRlIGxhcyBBZ2VuZGFzIENvbmNyZXRhcyBkZSBBY2Npw7NuIHkgbG9zIG51ZG9zIGNyw610aWNvcyBlbiBlbCBFc3RhZG8gTcOpcmlkYSwgc2UgYWRvcHTDsyB1biBlbmZvcXVlIG5vIHBhcmFtw6l0cmljbyBtZWRpYW50ZSBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgU3BlYXJtYW4uIEVzdGEgZGVjaXNpw7NuIG1ldG9kb2zDs2dpY2Egc2UgZnVuZGFtZW50w7MgZW4gbGEgYXVzZW5jaWEgZGUgbm9ybWFsaWRhZCBkZXRlY3RhZGEgZW4gbGFzIHZhcmlhYmxlcyBjdWFudGl0YXRpdmFzIGEgdHJhdsOpcyBkZSBsYSBwcnVlYmEgZGUgU2hhcGlyby1XaWxrLCBkb25kZSB0b2RvcyBsb3MgcC12YWxvcmVzIHJlc3VsdGFyb24gbWVub3JlcyBhIDAuMDAxLg0KDQogIEVsIGNvZWZpY2llbnRlIGRlIFNwZWFybWFuIGVzIHBhcnRpY3VsYXJtZW50ZSBhcHJvcGlhZG8gcGFyYSBlc3RlIGFuw6FsaXNpcyBwb3JxdWUgbm8gYXN1bWUgZGlzdHJpYnVjaW9uZXMgbm9ybWFsZXMgeSBlcyByb2J1c3RvIGFudGUgbGEgcHJlc2VuY2lhIGRlIHZhbG9yZXMgYXTDrXBpY29zLCBjYXJhY3RlcsOtc3RpY2FzIHByZXNlbnRlcyBlbiBudWVzdHJvcyBkYXRvcy4gRXN0ZSBjb2VmaWNpZW50ZSBtaWRlIGVsIGdyYWRvIGRlIGFzb2NpYWNpw7NuIG1vbm90w7NuaWNhIGVudHJlIGRvcyB2YXJpYWJsZXMsIHBlcm1pdGnDqW5kb25vcyBpZGVudGlmaWNhciB0YW50byByZWxhY2lvbmVzIGxpbmVhbGVzIGNvbW8gbm8gbGluZWFsZXMuDQoNCmBgYHtyfQ0KDQojIENyZWFyIHRhYmxhIGRlIGhpcMOzdGVzaXMgY29uIGVzdHJ1Y3R1cmEgY2xhcmENCmhpcG90ZXNpc19nZW5lcmFsIDwtIGRhdGEuZnJhbWUoDQogIEhpcMOzdGVzaXMgPSBjKA0KICAgICIqKkhpcMOzdGVzaXMgR2VuZXJhbCAoSEcpKioiLA0KICAgICJFeGlzdGUgdW5hIHJlbGFjacOzbiBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhIGVudHJlIGxhIHRpcG9sb2fDrWEgZGUgbG9zIG51ZG9zIGNyw610aWNvcyBpZGVudGlmaWNhZG9zIChDRkcpLCBsYSBjbGFzaWZpY2FjacOzbiBkZSBsb3MgYWN0b3JlcyBpbnN0aXR1Y2lvbmFsZXMgKEdvYmVybmFjacOzbikgeSBsYSBlZmVjdGl2aWRhZCBlbiBsYSBlamVjdWNpw7NuIGRlIGxvcyBwcm95ZWN0b3MgKFJBVElPIEFDQSkgZW4gbGFzIGNvbXVuYXMgZGVsIEVzdGFkbyBNw6lyaWRhIGR1cmFudGUgZWwgcGVyw61vZG8gMjAxOC0yMDI1LiIsDQogICAgIiIsDQogICAgIioqSEUxOiBDb25jb3JkYW5jaWEgU2VjdG9yaWFsIGVuIEVsZWN0cmljaWRhZCoqIiwNCiAgICAiRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEgbXV5IGZ1ZXJ0ZSB5IHNpZ25pZmljYXRpdmEgKM+BIOKJpSAwLjkwKSBlbnRyZSBsYSBpZGVudGlmaWNhY2nDs24gZGUgbnVkb3MgY3LDrXRpY29zIHJlbGFjaW9uYWRvcyBjb24gRUxFQ1RSSUNJREFEIChDRkcpIHkgbGEgcGFydGljaXBhY2nDs24gZGUgbGEgR29iZXJuYWNpw7NuIGVuIGVsIMOhcmVhIGRlIEVMRUNUUklDSURBRCAoR09CKSBlbiBsb3MgcHJveWVjdG9zIEFDQS4iLA0KICAgICIiLA0KICAgICIqKkhFMjogQ29uY29yZGFuY2lhIFNlY3RvcmlhbCBlbiBWaXZpZW5kYSoqIiwNCiAgICAiRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEgbXV5IGZ1ZXJ0ZSB5IHNpZ25pZmljYXRpdmEgKM+BIOKJpSAwLjkwKSBlbnRyZSBsYSBpZGVudGlmaWNhY2nDs24gZGUgbnVkb3MgY3LDrXRpY29zIGRlIFZJVklFTkRBIChDRkcpIHkgbGEgcGFydGljaXBhY2nDs24gZGUgbGEgR29iZXJuYWNpw7NuIGVuIGVsIMOhcmVhIGRlIFZJVklFTkRBIChHT0IpIGVuIGxvcyBwcm95ZWN0b3MgQUNBLiIsDQogICAgIiIsDQogICAgIioqSEUzOiBDZW50cmFsaXphY2nDs24gSW5zdGl0dWNpb25hbCoqIiwNCiAgICAiRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gbmVnYXRpdmEgbW9kZXJhZGEgeSBzaWduaWZpY2F0aXZhICgtMC42MCA8IM+BIDwgLTAuMjApIGVudHJlIGxhIENsYXNpZmljYWNpw7NuIGRlIEFjdG9yZXMgSW5zdGl0dWNpb25hbGVzIChkb25kZSB2YWxvcmVzIG3DoXMgYmFqb3MgaW5kaWNhbiBhY3RvcmVzIGRlIG1heW9yIG5pdmVsIGplcsOhcnF1aWNvKSB5IGxhIHByZXNlbmNpYSBkZSBudWRvcyBjcsOtdGljb3MgZGUgVklWSUVOREEgKENGRykuIiwNCiAgICAiIiwNCiAgICAiKipIRTQ6IEVmaWNpZW5jaWEgZW4gVHJhbnNwb3J0ZSoqIiwNCiAgICAiRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEgZMOpYmlsIHBlcm8gc2lnbmlmaWNhdGl2YSAoMC4xMCA8IM+BIDwgMC40MCkgZW50cmUgZWwgUkFUSU8gQUNBIFBST1lFQ1RPIENVTE1JTkFETyB5IGxhIHBhcnRpY2lwYWNpw7NuIGRlIGxhIEdvYmVybmFjacOzbiBlbiBlbCDDoXJlYSBkZSBUUkFOU1BPUlRFIChHT0IpLiIsDQogICAgIiIsDQogICAgIioqSEU1OiBDb21wbGVqaWRhZCBUZW1wb3JhbCBlbiBJbmZyYWVzdHJ1Y3R1cmEqKiIsDQogICAgIkxvcyBQTEFaT1MgZGUgZWplY3VjacOzbiBkZSBsb3MgcHJveWVjdG9zIHNlIHJlbGFjaW9uYW4gZGUgbWFuZXJhIGludmVyc2EgeSBkw6liaWwgKC0wLjQwIDwgz4EgPCAtMC4xMCkgY29uIGxhIHByZXNlbmNpYSBkZSBudWRvcyBjcsOtdGljb3MgZGUgSU5GUkFFU1RSVUNUVVJBIChDRkcpLiINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCiMgQ3JlYXIgdGFibGEgZXN0aWxpemFkYQ0Ka2FibGUoaGlwb3Rlc2lzX2dlbmVyYWwsIA0KICAgICAgY29sLm5hbWVzID0gTlVMTCwNCiAgICAgIGNhcHRpb24gPSAiSGlww7N0ZXNpcyBkZSBJbnZlc3RpZ2FjacOzbiBzb2JyZSBDb3JyZWxhY2nDs24gZW50cmUgUHJveWVjdG9zIEFDQSB5IE51ZG9zIENyw610aWNvcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IFRSVUUsDQogICAgICAgICAgICAgICAgZm9udF9zaXplID0gMTYpICU+JQ0KICBjb2x1bW5fc3BlYygxLCB3aWR0aCA9ICIxMDAlIikgJT4lDQogIHJvd19zcGVjKGMoMSwgNCwgNywgMTAsIDEzLCAxNiksIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNlOGY0ZjgiLCBjb2xvciA9ICIjMmMzZTUwIikNCmBgYA0KDQoqKk5vdGEgbWV0b2RvbMOzZ2ljYToqKiBMYXMgaGlww7N0ZXNpcyBmdWVyb24gZm9ybXVsYWRhcyBzaWd1aWVuZG8gZWwgbWFyY28gY29uY2VwdHVhbCBkZSBDYXN0aWxsbyB5IFRlbGxvICgyMDIyKSwgZXN0YWJsZWNpZW5kbyByYW5nb3MgZXNwZWPDrWZpY29zIGRlIG1hZ25pdHVkIGVzcGVyYWRhIHBhcmEgY2FkYSByZWxhY2nDs24uIEVsIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEgc2UgZmlqw7MgZW4gzrEgPSAwLjA1LCBjb25zaXN0ZW50ZSBjb24gZXN0w6FuZGFyZXMgZGUgaW52ZXN0aWdhY2nDs24gZW4gY2llbmNpYXMgc29jaWFsZXMuDQoNCg0KDQojIyoqTWF0cml6IGRlIENvcnJlbGFjaW9uZXMgSW50ZXJhY3RpdmEqKg0KDQpgYGB7cn0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBNQVRSSVogREUgQ09SUkVMQUNJT05FUyBJTlRFUkFDVElWQSAtIFZFUlNJw5NOIENPUlJFR0lEQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgUHJlcGFyYXIgZGF0b3MgcGFyYSB2aXN1YWxpemFjacOzbiBpbnRlcmFjdGl2YSAtIFVTQU5ETyByZXNoYXBlMjo6bWVsdA0KY29yX21hdHJpeF9tZWx0ZWQgPC0gcmVzaGFwZTI6Om1lbHQoY29yX3Jlc3VsdHMkY29yKQ0KcF9tYXRyaXhfbWVsdGVkIDwtIHJlc2hhcGUyOjptZWx0KGNvcl9yZXN1bHRzJHApDQpjb2xuYW1lcyhjb3JfbWF0cml4X21lbHRlZCkgPC0gYygiVmFyMSIsICJWYXIyIiwgIkNvcnJlbGFjaW9uIikNCmNvbG5hbWVzKHBfbWF0cml4X21lbHRlZCkgPC0gYygiVmFyMSIsICJWYXIyIiwgIlBfdmFsb3IiKQ0KDQpoZWF0bWFwX2RhdGEgPC0gY29yX21hdHJpeF9tZWx0ZWQgJT4lDQogIGxlZnRfam9pbihwX21hdHJpeF9tZWx0ZWQsIGJ5ID0gYygiVmFyMSIsICJWYXIyIikpICU+JQ0KICBtdXRhdGUoDQogICAgU2lnbmlmaWNhdGl2YSA9IGNhc2Vfd2hlbigNCiAgICAgIFBfdmFsb3IgPCAwLjAwMSB+ICIqKioiLA0KICAgICAgUF92YWxvciA8IDAuMDEgfiAiKioiLCANCiAgICAgIFBfdmFsb3IgPCAwLjA1IH4gIioiLA0KICAgICAgVFJVRSB+ICJucyINCiAgICApLA0KICAgIE1hZ25pdHVkID0gY2FzZV93aGVuKA0KICAgICAgYWJzKENvcnJlbGFjaW9uKSA+PSAwLjgwIH4gIk11eSBmdWVydGUiLA0KICAgICAgYWJzKENvcnJlbGFjaW9uKSA+PSAwLjYwIH4gIkZ1ZXJ0ZSIsDQogICAgICBhYnMoQ29ycmVsYWNpb24pID49IDAuNDAgfiAiTW9kZXJhZGEiLA0KICAgICAgYWJzKENvcnJlbGFjaW9uKSA+PSAwLjIwIH4gIkTDqWJpbCIsDQogICAgICBUUlVFIH4gIkRlc3ByZWNpYWJsZSINCiAgICApLA0KICAgIFRleHRvX0hvdmVyID0gcGFzdGUwKA0KICAgICAgIjxiPiIsIFZhcjEsICI8L2I+IOKGlCA8Yj4iLCBWYXIyLCAiPC9iPjxicj4iLA0KICAgICAgIs+BIChTcGVhcm1hbik6IDxiPiIsIHJvdW5kKENvcnJlbGFjaW9uLCAzKSwgIjwvYj48YnI+IiwNCiAgICAgICJwLXZhbG9yOiAiLCBmb3JtYXQucHZhbChQX3ZhbG9yLCBkaWdpdHMgPSAzKSwgIjxicj4iLA0KICAgICAgIlNpZ25pZmljYW5jaWE6ICIsIFNpZ25pZmljYXRpdmEsICI8YnI+IiwNCiAgICAgICJNYWduaXR1ZDogIiwgTWFnbml0dWQNCiAgICApLA0KICAgICMgU29sbyBtb3N0cmFyIGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMNCiAgICBDb3JyZWxhY2lvbl9tb3N0cmFyID0gaWZlbHNlKFBfdmFsb3IgPCAwLjA1LCBDb3JyZWxhY2lvbiwgTkEpDQogICkNCg0KIyBFbCByZXN0byBkZWwgY8OzZGlnbyBwYXJhIGNyZWFyIGVsIGhlYXRtYXAgaW50ZXJhY3Rpdm8gcGVybWFuZWNlIGlndWFsLi4uDQpwbG90X2x5KGRhdGEgPSBoZWF0bWFwX2RhdGEsDQogICAgICAgIHggPSB+VmFyMiwgDQogICAgICAgIHkgPSB+VmFyMSwgDQogICAgICAgIHogPSB+Q29ycmVsYWNpb25fbW9zdHJhciwNCiAgICAgICAgdHlwZSA9ICJoZWF0bWFwIiwNCiAgICAgICAgY29sb3JzID0gY29sb3JSYW1wKGMoIiNkNzMwMjciLCAiI2ZlZTA4YiIsICIjZmZmZmJmIiwgIiNkOWVmOGIiLCAiIzFhOTg1MCIpKSwNCiAgICAgICAgem1pZCA9IDAsDQogICAgICAgIHptaW4gPSAtMSwNCiAgICAgICAgem1heCA9IDEsDQogICAgICAgIHRleHQgPSB+VGV4dG9fSG92ZXIsDQogICAgICAgIGhvdmVyaW5mbyA9ICJ0ZXh0IiwNCiAgICAgICAgY29sb3JiYXIgPSBsaXN0KA0KICAgICAgICAgIHRpdGxlID0gbGlzdCh0ZXh0ID0gIs+BIChTcGVhcm1hbikiLCBzaWRlID0gInJpZ2h0IiksDQogICAgICAgICAgdGlja3ZhbHMgPSBjKC0xLCAtMC41LCAwLCAwLjUsIDEpLA0KICAgICAgICAgIHRpY2t0ZXh0ID0gYygiLTEuMCIsICItMC41IiwgIjAiLCAiMC41IiwgIjEuMCIpLA0KICAgICAgICAgIGxlbiA9IDAuNywNCiAgICAgICAgICB0aGlja25lc3MgPSAyMA0KICAgICAgICApKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gbGlzdCgNCiAgICAgIHRleHQgPSAiPGI+TWF0cml6IGRlIENvcnJlbGFjacOzbiBkZSBTcGVhcm1hbiAtIFByb3llY3RvcyBBQ0E8L2I+PGJyPjxzdWI+U29sbyBjb3JyZWxhY2lvbmVzIHNpZ25pZmljYXRpdmFzIChwIDwgMC4wNSkgfCBJbnRlcmFjdGl2bzogcGFzZSBlbCBjdXJzb3IgcGFyYSBkZXRhbGxlczwvc3ViPiIsDQogICAgICBmb250ID0gbGlzdChzaXplID0gMTgsIGNvbG9yID0gIiMyYzNlNTAiKQ0KICAgICksDQogICAgeGF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAiIiwgDQogICAgICB0aWNrYW5nbGUgPSA0NSwgDQogICAgICB0aWNrZm9udCA9IGxpc3Qoc2l6ZSA9IDExKSwNCiAgICAgIHNpZGUgPSAiYm90dG9tIg0KICAgICksDQogICAgeWF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAiIiwgDQogICAgICB0aWNrZm9udCA9IGxpc3Qoc2l6ZSA9IDExKSwNCiAgICAgIGF1dG9yYW5nZSA9ICJyZXZlcnNlZCINCiAgICApLA0KICAgIG1hcmdpbiA9IGxpc3QobCA9IDE4MCwgciA9IDgwLCB0ID0gMTIwLCBiID0gMTgwKSwNCiAgICBwYXBlcl9iZ2NvbG9yID0gIiNmZmZmZmYiLA0KICAgIHBsb3RfYmdjb2xvciA9ICIjZjhmOWZhIg0KICApICU+JQ0KICBjb25maWcoDQogICAgZGlzcGxheU1vZGVCYXIgPSBUUlVFLA0KICAgIGRpc3BsYXlsb2dvID0gRkFMU0UsDQogICAgbW9kZUJhckJ1dHRvbnNUb1JlbW92ZSA9IGMoInBhbjJkIiwgImxhc3NvMmQiLCAic2VsZWN0MmQiKQ0KICApDQpgYGANCg0KDQoNCiAgTGEgbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgcmV2ZWxhIHRyZXMgcGF0cm9uZXMgZXN0cnVjdHVyYWxlcyBmdW5kYW1lbnRhbGVzIHF1ZSBjYXJhY3Rlcml6YW4gZWwgZnVuY2lvbmFtaWVudG8gZGVsIHNpc3RlbWEgZGUgQWdlbmRhcyBDb25jcmV0YXMgZGUgQWNjacOzbiBlbiBlbCBFc3RhZG8gTcOpcmlkYToNCg0KKipQcmltZXIgcGF0csOzbioqOiBDb3JyZWxhY2lvbmVzIHBlcmZlY3RhcyBlbiBsYSBmYXNlIGRpYWduw7NzdGljby1hc2lnbmFjacOzbi4gTGFzIGNlbGRhcyBhenVsIG9zY3VybyBlbiBsYSBtYXRyaXogaWRlbnRpZmljYW4gY29ycmVsYWNpb25lcyBwZXJmZWN0YXMgbyBjYXNpIHBlcmZlY3RhcyAoz4Eg4omlIDAuOTApIGVudHJlIGxhIGlkZW50aWZpY2FjacOzbiBkZSBudWRvcyBjcsOtdGljb3MgZXNwZWPDrWZpY29zIHkgc3UgYXNpZ25hY2nDs24gaW5zdGl0dWNpb25hbCBjb3JyZXNwb25kaWVudGUuIEVzdGUgcGF0csOzbiBlcyBwYXJ0aWN1bGFybWVudGUgZXZpZGVudGUgZW4gc2VjdG9yZXMgY29tbyBlbGVjdHJpY2lkYWQsIHZpdmllbmRhLCB0cmFuc3BvcnRlIHkgdmlhbGlkYWQuIEVzdGFzIGNvcnJlbGFjaW9uZXMgbm8gc29uIGNvaW5jaWRlbmNpYXMgZXN0YWTDrXN0aWNhcywgc2lubyBldmlkZW5jaWEgZGUgcHJvdG9jb2xvcyBpbnN0aXR1Y2lvbmFsZXMgYWx0YW1lbnRlIGVzdGFuZGFyaXphZG9zIGRvbmRlIGNhZGEgdGlwbyBkZSBwcm9ibGVtYSBlcyBzaXN0ZW3DoXRpY2FtZW50ZSBhc2lnbmFkbyBhbCBhY3RvciBndWJlcm5hbWVudGFsIGNvbXBldGVudGUuDQoNCioqU2VndW5kbyBwYXRyw7NuKio6IExhIEdyYW4gRGVzY29uZXhpw7NuIGNvbiByZXN1bHRhZG9zLiBFbCBoYWxsYXpnbyBtw6FzIGNyw610aWNvIGVtZXJnZSBhbCBvYnNlcnZhciBsYSBjb2x1bW5hIGNvcnJlc3BvbmRpZW50ZSBhIGxhIHZhcmlhYmxlIFJhdGlvIEFDQSAoZWZlY3RpdmlkYWQgZGUgY3VsbWluYWNpw7NuKS4gTGFzIGNlbGRhcyBwcmVkb21pbmFudGVtZW50ZSBibGFuY2FzIG8gYW1hcmlsbGFzIHDDoWxpZGFzIGVuIGVzdGEgY29sdW1uYSBldmlkZW5jaWFuIGxhIGF1c2VuY2lhIGRlIGNvcnJlbGFjaW9uZXMgZnVlcnRlcyBvIG1vZGVyYWRhcyBjb24gb3RyYXMgdmFyaWFibGVzIGRlbCBzaXN0ZW1hLiBFc3RhIGRlc2NvbmV4acOzbiBjdWFudGlmaWNhIGVtcMOtcmljYW1lbnRlIHVuYSBicmVjaGEgZXN0cnVjdHVyYWw6IGVsIHNpc3RlbWEgaWRlbnRpZmljYSBwcm9ibGVtYXMgY29uIHByZWNpc2nDs24geSBsb3MgYXNpZ25hIGNvcnJlY3RhbWVudGUsIHBlcm8gZXN0YSBlZmljaWVuY2lhIGRpYWduw7NzdGljYSBubyBwcmVkaWNlIGxhIHByb2JhYmlsaWRhZCBkZSByZXNvbHVjacOzbiBlZmVjdGl2YS4NCg0KKipUZXJjZXIgcGF0csOzbioqOiBDb3JyZWxhY2lvbmVzIHNlY3RvcmlhbGVzIGVzcGVjw61maWNhcy4gQWxndW5vcyBzZWN0b3JlcyBtdWVzdHJhbiBjb3JyZWxhY2lvbmVzIG1vZGVyYWRhcyAoY2VsZGFzIHZlcmRlIGNsYXJvKSBxdWUgc3VnaWVyZW4gZGluw6FtaWNhcyBwYXJ0aWN1bGFyZXMuIFBvciBlamVtcGxvLCBlbCBzZWN0b3IgdHJhbnNwb3J0ZSBwcmVzZW50YSB1bmEgY29ycmVsYWNpw7NuIGTDqWJpbCBwZXJvIHNpZ25pZmljYXRpdmEgY29uIGxhIGVmZWN0aXZpZGFkLCBpbmRpY2FuZG8gcXVlIGNpZXJ0b3Mgw6FtYml0b3MgdGllbmVuIGNhcmFjdGVyw61zdGljYXMgcXVlIGxvcyBoYWNlbiBsaWdlcmFtZW50ZSBtw6FzIHByb3BlbnNvcyBhIGxhIGN1bG1pbmFjacOzbiBleGl0b3NhLg0KDQoqKkltcGxpY2FjaW9uZXMgbWV0b2RvbMOzZ2ljYXMqKjogTGEgaW50ZXJhY3RpdmlkYWQgZGVsIGdyw6FmaWNvIHBlcm1pdGUgZXhwbG9yYXIgY2FkYSBjZWxkYSBpbmRpdmlkdWFsbWVudGUsIHJldmVsYW5kbyBubyBzb2xvIGxhIG1hZ25pdHVkIGRlIGxhIGNvcnJlbGFjacOzbiBzaW5vIHRhbWJpw6luIHN1IHNpZ25pZmljYW5jaWEgZXN0YWTDrXN0aWNhIHkgZWwgY29udGV4dG8gZXNwZWPDrWZpY28gZGUgbGFzIHZhcmlhYmxlcyBpbnZvbHVjcmFkYXMuIEVzdGUgbml2ZWwgZGUgZGV0YWxsZSBlcyBmdW5kYW1lbnRhbCBwYXJhIGRpc3Rpbmd1aXIgZW50cmUgcGF0cm9uZXMgcm9idXN0b3MgeSByZWxhY2lvbmVzIGVzcHVyaWFzLg0KDQojIyAqKkV2YWx1YWNpw7NuIGRlIEhpcMOzdGVzaXMgZGUgSW52ZXN0aWdhY2nDs24qKg0KDQpgYGB7cn0NCiMgUHJlcGFyYXIgZGF0b3MgY29uIGxvcyByZXN1bHRhZG9zIHJlYWxlcyBkZWwgYW7DoWxpc2lzDQpldmFsdWFjaW9uX2hpcG90ZXNpcyA8LSBkYXRhLmZyYW1lKA0KICBIaXBvdGVzaXMgPSBjKA0KICAgICJIRTE6IENvbmNvcmRhbmNpYSBTZWN0b3JpYWw8YnI+KEVsZWN0cmljaWRhZCkiLA0KICAgICJIRTI6IENvbmNvcmRhbmNpYSBTZWN0b3JpYWw8YnI+KFZpdmllbmRhKSIsDQogICAgIkhFMzogQ2VudHJhbGl6YWNpw7NuPGJyPkluc3RpdHVjaW9uYWwgKFZpdmllbmRhKSIsDQogICAgIkhFNDogRWZpY2llbmNpYSBlbjxicj5UcmFuc3BvcnRlIiwNCiAgICAiSEU1OiBDb21wbGVqaWRhZCBUZW1wb3JhbDxicj4oSW5mcmFlc3RydWN0dXJhKSINCiAgKSwNCiAgUmhvID0gYygxLjAwMCwgMC45NTAsIC0wLjM2OCwgMC4xNjcsIC0wLjE4NSksDQogIFBfdmFsb3IgPSBjKDAuMDAwMDAwMCwgMC4wMDAwMDAwLCAwLjAwMDAwMDEsIDAuMDE4OSwgMC4wMDg5KSwNCiAgTWFnbml0dWQgPSBjKCJNdXkgZnVlcnRlIiwgIk11eSBmdWVydGUiLCAiTW9kZXJhZGEiLCAiRMOpYmlsIiwgIkTDqWJpbCIpLA0KICBFc3RhZG8gPSBjKCJDb25maXJtYWRhIiwgIkNvbmZpcm1hZGEiLCAiQ29uZmlybWFkYSIsIA0KICAgICAgICAgICAgICJQYXJjaWFsbWVudGUgQ29uZmlybWFkYSIsICJDb25maXJtYWRhIiksDQogIFZhcmlhYmxlcyA9IGMoDQogICAgIkNGRzogRUxFQ1RSSUNJREFEIOKGlCBHT0I6IEVMRUNUUklDSURBRCIsDQogICAgIkNGRzogVklWSUVOREEg4oaUIEdPQjogVklWSUVOREEiLA0KICAgICJDbGFzaWZpY2FjacOzbiBBY3RvcmVzIOKGlCBDRkc6IFZJVklFTkRBIiwNCiAgICAiUkFUSU8gQUNBIOKGlCBHT0I6IFRSQU5TUE9SVEUiLA0KICAgICJQTEFaT1Mg4oaUIENGRzogSU5GUkFFU1RSVUNUVVJBIg0KICApDQopICU+JQ0KICBtdXRhdGUoDQogICAgQ29sb3IgPSBjYXNlX3doZW4oDQogICAgICBFc3RhZG8gPT0gIkNvbmZpcm1hZGEiIH4gIiMyN2FlNjAiLA0KICAgICAgRXN0YWRvID09ICJQYXJjaWFsbWVudGUgQ29uZmlybWFkYSIgfiAiI2YzOWMxMiIsDQogICAgICBUUlVFIH4gIiNlNzRjM2MiDQogICAgKSwNCiAgICBUZXh0b19Ib3ZlciA9IHBhc3RlMCgNCiAgICAgICI8Yj4iLCBnc3ViKCI8YnI+IiwgIiAiLCBIaXBvdGVzaXMpLCAiPC9iPjxicj4iLA0KICAgICAgIlZhcmlhYmxlczogIiwgVmFyaWFibGVzLCAiPGJyPiIsDQogICAgICAiz4EgKFNwZWFybWFuKTogPGI+Iiwgcm91bmQoUmhvLCAzKSwgIjwvYj48YnI+IiwNCiAgICAgICJwLXZhbG9yOiAiLCBmb3JtYXQucHZhbChQX3ZhbG9yLCBkaWdpdHMgPSAzKSwgIjxicj4iLA0KICAgICAgIk1hZ25pdHVkOiAiLCBNYWduaXR1ZCwgIjxicj4iLA0KICAgICAgIkVzdGFkbzogPGI+IiwgRXN0YWRvLCAiPC9iPiINCiAgICApDQogICkNCg0KIyBDcmVhciBncsOhZmljbyBpbnRlcmFjdGl2bw0KcGxvdF9seShldmFsdWFjaW9uX2hpcG90ZXNpcywgDQogICAgICAgIHkgPSB+cmVvcmRlcihIaXBvdGVzaXMsIGFicyhSaG8pKSwgDQogICAgICAgIHggPSB+YWJzKFJobyksDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgb3JpZW50YXRpb24gPSAnaCcsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSB+Q29sb3IsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JnYig4LDQ4LDEwNyknLCB3aWR0aCA9IDEuNSkpLA0KICAgICAgICB0ZXh0ID0gflRleHRvX0hvdmVyLA0KICAgICAgICBob3ZlcmluZm8gPSAndGV4dCcsDQogICAgICAgIHRleHRwb3NpdGlvbiA9ICdub25lJykgJT4lDQogIGFkZF9hbm5vdGF0aW9ucygNCiAgICB4ID0gfmFicyhSaG8pICsgMC4wNSwNCiAgICB5ID0gfkhpcG90ZXNpcywNCiAgICB0ZXh0ID0gfnBhc3RlMCgiPGI+z4E9Iiwgcm91bmQoUmhvLCAzKSwgIjwvYj48YnI+IiwgRXN0YWRvKSwNCiAgICBzaG93YXJyb3cgPSBGQUxTRSwNCiAgICB4YW5jaG9yID0gJ2xlZnQnLA0KICAgIGZvbnQgPSBsaXN0KHNpemUgPSAxMiwgY29sb3IgPSAnYmxhY2snKQ0KICApICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICI8Yj5FdmFsdWFjacOzbiBFbXDDrXJpY2EgZGUgSGlww7N0ZXNpcyBkZSBJbnZlc3RpZ2FjacOzbjwvYj48YnI+PHN1Yj5NYWduaXR1ZCBkZSBjb3JyZWxhY2lvbmVzICh2YWxvciBhYnNvbHV0bykgeSBlc3RhZG8gZGUgY29uZmlybWFjacOzbjwvc3ViPiIsDQogICAgICBmb250ID0gbGlzdChzaXplID0gMTgsIGNvbG9yID0gIiMyYzNlNTAiKQ0KICAgICksDQogICAgeGF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAiTWFnbml0dWQgZGUgQ29ycmVsYWNpw7NuIHzPgXwiLCANCiAgICAgIHJhbmdlID0gYygwLCAxLjE1KSwNCiAgICAgIHRpY2t2YWxzID0gc2VxKDAsIDEsIDAuMiksDQogICAgICBncmlkY29sb3IgPSAiI2VjZjBmMSINCiAgICApLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICIiLCB0aWNrZm9udCA9IGxpc3Qoc2l6ZSA9IDEyKSksDQogICAgbWFyZ2luID0gbGlzdChsID0gMjIwLCByID0gMTUwLCB0ID0gMTIwLCBiID0gODApLA0KICAgIHNob3dsZWdlbmQgPSBGQUxTRSwNCiAgICBwYXBlcl9iZ2NvbG9yID0gIiNmZmZmZmYiLA0KICAgIHBsb3RfYmdjb2xvciA9ICIjZjhmOWZhIiwNCiAgICBzaGFwZXMgPSBsaXN0KA0KICAgICAgIyBMw61uZWEgZGUgcmVmZXJlbmNpYSBwYXJhIGNvcnJlbGFjacOzbiBtb2RlcmFkYQ0KICAgICAgbGlzdCh0eXBlID0gImxpbmUiLCB4MCA9IDAuNCwgeDEgPSAwLjQsIHkwID0gLTAuNSwgeTEgPSA1LjUsDQogICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gIiM5NWE1YTYiLCB3aWR0aCA9IDIsIGRhc2ggPSAiZG90IikpLA0KICAgICAgIyBMw61uZWEgZGUgcmVmZXJlbmNpYSBwYXJhIGNvcnJlbGFjacOzbiBmdWVydGUNCiAgICAgIGxpc3QodHlwZSA9ICJsaW5lIiwgeDAgPSAwLjYsIHgxID0gMC42LCB5MCA9IC0wLjUsIHkxID0gNS41LA0KICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICIjN2Y4YzhkIiwgd2lkdGggPSAyLCBkYXNoID0gImRvdCIpKSwNCiAgICAgICMgTMOtbmVhIGRlIHJlZmVyZW5jaWEgcGFyYSBjb3JyZWxhY2nDs24gbXV5IGZ1ZXJ0ZQ0KICAgICAgbGlzdCh0eXBlID0gImxpbmUiLCB4MCA9IDAuOCwgeDEgPSAwLjgsIHkwID0gLTAuNSwgeTEgPSA1LjUsDQogICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gIiMzNDQ5NWUiLCB3aWR0aCA9IDIsIGRhc2ggPSAiZGFzaCIpKQ0KICAgICksDQogICAgYW5ub3RhdGlvbnMgPSBsaXN0KA0KICAgICAgbGlzdCh4ID0gMC40LCB5ID0gNSwgdGV4dCA9ICJNb2RlcmFkYSIsIHNob3dhcnJvdyA9IEZBTFNFLCANCiAgICAgICAgICAgeGFuY2hvciA9ICJjZW50ZXIiLCB5YW5jaG9yID0gImJvdHRvbSIsIGZvbnQgPSBsaXN0KHNpemUgPSAxMCwgY29sb3IgPSAiIzk1YTVhNiIpKSwNCiAgICAgIGxpc3QoeCA9IDAuNiwgeSA9IDUsIHRleHQgPSAiRnVlcnRlIiwgc2hvd2Fycm93ID0gRkFMU0UsDQogICAgICAgICAgIHhhbmNob3IgPSAiY2VudGVyIiwgeWFuY2hvciA9ICJib3R0b20iLCBmb250ID0gbGlzdChzaXplID0gMTAsIGNvbG9yID0gIiM3ZjhjOGQiKSksDQogICAgICBsaXN0KHggPSAwLjgsIHkgPSA1LCB0ZXh0ID0gIk11eSBmdWVydGUiLCBzaG93YXJyb3cgPSBGQUxTRSwNCiAgICAgICAgICAgeGFuY2hvciA9ICJjZW50ZXIiLCB5YW5jaG9yID0gImJvdHRvbSIsIGZvbnQgPSBsaXN0KHNpemUgPSAxMCwgY29sb3IgPSAiIzM0NDk1ZSIpKQ0KICAgICkNCiAgKSAlPiUNCiAgY29uZmlnKA0KICAgIGRpc3BsYXlNb2RlQmFyID0gVFJVRSwNCiAgICBkaXNwbGF5bG9nbyA9IEZBTFNFLA0KICAgIG1vZGVCYXJCdXR0b25zVG9SZW1vdmUgPSBjKCJwYW4yZCIsICJsYXNzbzJkIiwgInNlbGVjdDJkIikNCiAgKQ0KYGBgDQoNCiMjICoqQW7DoWxpc2lzIERldGFsbGFkbyBwb3IgSGlww7N0ZXNpcyoqDQoNCkhFMSAoz4EgPSAxLjAwMCk6IENvbmNvcmRhbmNpYSBwZXJmZWN0YSBlbiBlbGVjdHJpY2lkYWQuIExhIGNvcnJlbGFjacOzbiBwZXJmZWN0YSBlbnRyZSBsYSBpZGVudGlmaWNhY2nDs24gZGUgcHJvYmxlbWFzIGVsw6ljdHJpY29zIHkgc3UgYXNpZ25hY2nDs24gYSBDb3Jwb2VsZWMgbyBsYSBHb2Jlcm5hY2nDs24gcmVwcmVzZW50YSBlbCBwdW50byBtw6FzIGZ1ZXJ0ZSBkZWwgc2lzdGVtYS4gRXN0YSBwcmVjaXNpw7NuIGluc3RpdHVjaW9uYWwgZXZpZGVuY2lhIHVuIHByb3RvY29sbyBlc3RhbmRhcml6YWRvIGRvbmRlIG5vIGhheSBhbWJpZ8O8ZWRhZCBzb2JyZSBxdWnDqW4gZGViZSBhY3R1YXIuIEVuIHVuIGNvbnRleHRvIHZlbmV6b2xhbm8gY2FyYWN0ZXJpemFkbyBwb3IgZnJhZ21lbnRhY2nDs24gaW5zdGl0dWNpb25hbCwgZXN0ZSByZXN1bHRhZG8gZXMgZXhjZXBjaW9uYWwgeSBzdWdpZXJlIHF1ZSBlbCBzZWN0b3IgZWzDqWN0cmljbyBoYSBsb2dyYWRvIGVzdGFibGVjZXIgdW4gY29uc2Vuc28gY2xhcm8gZW50cmUgbGEgc29jaWVkYWQgY2l2aWwgeSBlbCBFc3RhZG8gc29icmUgbGFzIHJ1dGFzIGRlIHJlc3BvbnNhYmlsaWRhZC4NCg0KSEUyICjPgSA9IDAuOTUwKTogQWx0YSBlZmVjdGl2aWRhZCBlbiB2aXZpZW5kYS4gTGEgY29ycmVsYWNpw7NuIGNhc2kgcGVyZmVjdGEgZW4gdml2aWVuZGEgY29uZmlybWEgcXVlLCBwYXJhIHByb2JsZW1hcyBkZSBhbHRhIGNvbXBsZWppZGFkIHF1ZSBpbnZvbHVjcmFuIHRpZXJyYSwgZmluYW5jaWFtaWVudG8geSBjb29yZGluYWNpw7NuIGludGVyaW5zdGl0dWNpb25hbCwgZWwgc2lzdGVtYSB0YW1iacOpbiBmdW5jaW9uYSBjb24gcHJlY2lzacOzbiBub3RhYmxlLiBMYSBsaWdlcmEgcmVkdWNjacOzbiByZXNwZWN0byBhIGVsZWN0cmljaWRhZCAoMC45NTAgdnMgMS4wMDApIHBvZHLDrWEgcmVmbGVqYXIgbWF5b3IgaGV0ZXJvZ2VuZWlkYWQgZW4gbG9zIGFjdG9yZXMgY29tcGV0ZW50ZXMgbyBzb2xhcGFtaWVudG9zIGp1cmlzZGljY2lvbmFsZXMgb2Nhc2lvbmFsZXMuDQoNCkhFMyAoz4EgPSAtMC4zNjgpOiBDZW50cmFsaXphY2nDs24gZnVuY2lvbmFsLiBMYSBjb3JyZWxhY2nDs24gbmVnYXRpdmEgbW9kZXJhZGEgZW50cmUgbml2ZWwgamVyw6FycXVpY28gZGUgYWN0b3JlcyB5IHByb2JsZW1hcyBkZSB2aXZpZW5kYSByZXZlbGEgdW4gbWVjYW5pc21vIGRlIHNvYnJldml2ZW5jaWEgaW5zdGl0dWNpb25hbC4gTGFzIGNvbXVuYXMsIHJlY29ub2NpZW5kbyBsYSBjb21wbGVqaWRhZCBkZWwgcHJvYmxlbWEgaGFiaXRhY2lvbmFsLCB0aWVuZGVuIGEgZXNjYWxhciBlc3RhcyBkZW1hbmRhcyBoYWNpYSBhY3RvcmVzIGRlIG1heW9yIG5pdmVsIChNaW5pc3RlcmlvcywgR29iZXJuYWNpw7NuKSBlbiBsdWdhciBkZSBkZWxlZ2FybGFzIGEgaW5zdGFuY2lhcyBsb2NhbGVzLiBFc3RhIGNlbnRyYWxpemFjacOzbiBubyBlcyB1biBlcnJvciBzaW5vIHVuYSBhZGFwdGFjacOzbiByYWNpb25hbCBhIGxhIHJlYWxpZGFkIGRlIHJlY3Vyc29zIGxpbWl0YWRvcyBlbiBuaXZlbGVzIG11bmljaXBhbGVzIG8gY29tdW5hbGVzLg0KDQpIRTQgKM+BID0gMC4xNjcpOiBFZmVjdGl2aWRhZCBtYXJnaW5hbCBlbiB0cmFuc3BvcnRlLiBMYSBjb3JyZWxhY2nDs24gZMOpYmlsIHBlcm8gc2lnbmlmaWNhdGl2YSBjb24gdHJhbnNwb3J0ZSBzdWdpZXJlIHF1ZSBlc3RlIHNlY3RvciB0aWVuZSBjYXJhY3RlcsOtc3RpY2FzIHF1ZSBsbyBoYWNlbiBsaWdlcmFtZW50ZSBtw6FzIHByb3BpY2lvIGEgbGEgY3VsbWluYWNpw7NuLiBQb3NpYmxlbWVudGUsIGxvcyBwcm95ZWN0b3MgZGUgdHJhbnNwb3J0ZSB0aWVuZW4gZXNwZWNpZmljYWNpb25lcyB0w6ljbmljYXMgbcOhcyBvYmpldGl2YXMsIG1lbm9yZXMgZGVwZW5kZW5jaWFzIGludGVyaW5zdGl0dWNpb25hbGVzIG8gbWF5b3IgdmlzaWJpbGlkYWQgcG9sw610aWNhIHF1ZSBsb3MgY29udmllcnRlIGVuICJwcm95ZWN0b3Mgdml0cmluYSIgcXVlIHNlIHByaW9yaXphbiBwYXJhIG1vc3RyYXIgcmVzdWx0YWRvcyB0YW5naWJsZXMuDQoNCkhFNSAoz4EgPSAtMC4xODUpOiBVcmdlbmNpYSB2cyB2aWFiaWxpZGFkIHTDqWNuaWNhLiBMYSBjb3JyZWxhY2nDs24gbmVnYXRpdmEgZMOpYmlsIGVudHJlIHBsYXpvcyBlIGluZnJhZXN0cnVjdHVyYSBldmlkZW5jaWEgcXVlIGVzdG9zIHByb3llY3RvcyB0aWVuZGVuIGEgYXNpZ25hcnNlIHBsYXpvcyBtw6FzIGNvcnRvcywgcG9zaWJsZW1lbnRlIHBvciBzdSB1cmdlbmNpYSB2aXNpYmxlLiBTaW4gZW1iYXJnbywgZXN0YSBhc2lnbmFjacOzbiBkZSBwbGF6b3MgY29ydG9zIHB1ZWRlIHNlciBtw6FzIHVuYSBkZWNsYXJhY2nDs24gZGUgaW50ZW5jaW9uZXMgcXVlIHVuIGNyb25vZ3JhbWEgcmVhbGlzdGEsIGNvbnRyaWJ1eWVuZG8gYWwgZXN0YW5jYW1pZW50byBwb3N0ZXJpb3IgZGUgZXN0b3MgcHJveWVjdG9zLg0KDQoNCiMjICoqRGVzY29uZXhpw7NuIEVzdHJ1Y3R1cmFsIGVudHJlIFBsYW5pZmljYWNpw7NuIHkgRWplY3VjacOzbioqDQoNCiAgRWwgaGFsbGF6Z28gbcOhcyBjcsOtdGljbyBkZSBlc3RlIGFuw6FsaXNpcyBubyByYWRpY2EgZW4gbGFzIGNvcnJlbGFjaW9uZXMgZnVlcnRlcyBxdWUgZW5jb250cmFtb3MsIHNpbm8gZW4gYXF1ZWxsYXMgcXVlIG5vIGVuY29udHJhbW9zLiBMYSB2YXJpYWJsZSBSYXRpbyBBQ0EsIHF1ZSBtaWRlIGxhIGVmZWN0aXZpZGFkIGVuIGN1bG1pbmFjacOzbiBkZSBwcm95ZWN0b3MsIG5vIHByZXNlbnRhIGNvcnJlbGFjaW9uZXMgZnVlcnRlcyBvIG1vZGVyYWRhcyBjb24gbmluZ3VuYSBvdHJhIHZhcmlhYmxlIGRlbCBzaXN0ZW1hLCBleGNlcHRvIHVuYSBjb3JyZWxhY2nDs24gZMOpYmlsIGNvbiBlbCBzZWN0b3IgdHJhbnNwb3J0ZS4NCg0KICBFc3RlIHJlc3VsdGFkbyBjdWFudGlmaWNhIGVtcMOtcmljYW1lbnRlIHVuYSBicmVjaGEgZXN0cnVjdHVyYWwgcXVlIGRlbm9taW5hbW9zICJMYSBHcmFuIERlc2NvbmV4acOzbiI6IGVsIHNpc3RlbWEgZGUgQUNBIGVzIGV4Y2VsZW50ZSBwYXJhIG1hcGVhciBwcm9ibGVtYXMgeSBhc2lnbmFybG9zIGluc3RpdHVjaW9uYWxtZW50ZSwgcGVybyBlc3RhIGVmaWNpZW5jaWEgZGlhZ27Ds3N0aWNhIG5vIHNlIHRyYWR1Y2UgZW4gY2FwYWNpZGFkIGRlIGVqZWN1Y2nDs24uDQoNCioqSW1wbGljYWNpb25lcyBkZSBsYSBEZXNjb25leGnDs24qKg0KDQoqUGFyYSBsYSBpbnZlc3RpZ2FjacOzbio6IEVzdGUgaGFsbGF6Z28gaW1wbGljYSBxdWUgbG9zIGZhY3RvcmVzIGRldGVybWluYW50ZXMgZGVsIMOpeGl0byBvIGZyYWNhc28gZW4gbGEgZWplY3VjacOzbiBkZSBwcm95ZWN0b3MgZXN0w6FuIGZ1ZXJhIGRlbCBtb2RlbG8gbWVkaWRvLiBWYXJpYWJsZXMgY29tbyBkaXNwb25pYmlsaWRhZCBwcmVzdXB1ZXN0YXJpYSwgdm9sdW50YWQgcG9sw610aWNhLCBjYXBhY2lkYWQgdMOpY25pY2EsIGNhbWJpb3MgYWRtaW5pc3RyYXRpdm9zIG8gZmFjdG9yZXMgY29udGV4dHVhbGVzIG5vIGNhcHR1cmFkb3Mgc29uIGxvcyB2ZXJkYWRlcm9zIHByZWRpY3RvcmVzIGRlIGxhIGN1bG1pbmFjacOzbi4NCg0KKlBhcmEgbGEgcG9sw610aWNhIHDDumJsaWNhKjogTGEgZGVzY29uZXhpw7NuIHJldmVsYSBxdWUgbWVqb3JhciBlbCBkaWFnbsOzc3RpY28gcGFydGljaXBhdGl2byAocXVlIHlhIGZ1bmNpb25hIGJpZW4pIG5vIHJlc29sdmVyw6EgZWwgcHJvYmxlbWEgZGUgZWplY3VjacOzbi4gU2UgcmVxdWllcmVuIGludGVydmVuY2lvbmVzIGVzcGVjw61maWNhcyBlbiBsYSBmYXNlIGRlIGltcGxlbWVudGFjacOzbjogZm9ydGFsZWNpbWllbnRvIGRlIGNhcGFjaWRhZGVzIHTDqWNuaWNhcywgbWVjYW5pc21vcyBkZSBzZWd1aW1pZW50byBlZmVjdGl2b3MsIGVzdGFiaWxpZGFkIGFkbWluaXN0cmF0aXZhIHkgZmluYW5jaWFtaWVudG8gcHJlZGVjaWJsZS4NCg0KKlBhcmEgbGEgdGVvcsOtYSBkZSBnb2Jlcm5hbnphKjogRXN0ZSBwYXRyw7NuIGRlc2Fmw61hIG1vZGVsb3MgcXVlIGFzdW1lbiBxdWUgdW5hIGJ1ZW5hIHBsYW5pZmljYWNpw7NuIHBhcnRpY2lwYXRpdmEgY29uZHVjZSBhdXRvbcOhdGljYW1lbnRlIGEgYnVlbm9zIHJlc3VsdGFkb3MuIExhIGV2aWRlbmNpYSBzdWdpZXJlIHF1ZSBwbGFuaWZpY2FjacOzbiB5IGVqZWN1Y2nDs24gb3BlcmFuIGVuIGzDs2dpY2FzIGluc3RpdHVjaW9uYWxlcyBkaXN0aW50YXMgcXVlIG5vIGVzdMOhbiBjb25lY3RhZGFzIG9yZ8OhbmljYW1lbnRlLg0KDQojIyoqVGFibGFzIFJlc3VtZW4gRWplY3V0aXZhcyoqDQoNCmBgYHtyfQ0KIyBUYWJsYSAxOiBEaXN0cmlidWNpw7NuIGRlIGNvcnJlbGFjaW9uZXMgcG9yIG1hZ25pdHVkDQpkaXN0cmlidWNpb25fY29yIDwtIGNvcl9kZiAlPiUNCiAgZmlsdGVyKFNpZ25pZmljYXRpdmEgPT0gIlPDrSIpICU+JQ0KICBncm91cF9ieShNYWduaXR1ZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBOX0NvcnJlbGFjaW9uZXMgPSBuKCksDQogICAgUmFuZ28gPSBwYXN0ZTAoIlsiLCByb3VuZChtaW4oYWJzKENvcnJlbGFjaW9uKSksIDIpLCANCiAgICAgICAgICAgICAgICAgICIgLSAiLCByb3VuZChtYXgoYWJzKENvcnJlbGFjaW9uKSksIDIpLCAiXSIpLA0KICAgIFBfdmFsb3JfcHJvbWVkaW8gPSByb3VuZChtZWFuKHBfdmFsb3IpLCA0KSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lDQogIGFycmFuZ2UobWF0Y2goTWFnbml0dWQsIGMoIk11eSBmdWVydGUiLCAiRnVlcnRlIiwgIk1vZGVyYWRhIiwgIkTDqWJpbCIpKSkNCg0KZGF0YXRhYmxlKGRpc3RyaWJ1Y2lvbl9jb3IsDQogICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSAxOiBEaXN0cmlidWNpw7NuIGRlIENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgcG9yIE1hZ25pdHVkIiwNCiAgICAgICAgICBvcHRpb25zID0gbGlzdCgNCiAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgIGRvbSA9ICd0JywNCiAgICAgICAgICAgIG9yZGVyaW5nID0gRkFMU0UNCiAgICAgICAgICApLA0KICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsDQogICAgICAgICAgY2xhc3MgPSAnY2VsbC1ib3JkZXIgc3RyaXBlJykgJT4lDQogIGZvcm1hdFN0eWxlKGNvbHVtbnMgPSBjKDE6NCksIGZvbnRTaXplID0gJzE0cHgnKSAlPiUNCiAgZm9ybWF0U3R5bGUoJ01hZ25pdHVkJywgDQogICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvciA9IHN0eWxlRXF1YWwoDQogICAgICAgICAgICAgICAgYygiTXV5IGZ1ZXJ0ZSIsICJGdWVydGUiLCAiTW9kZXJhZGEiLCAiRMOpYmlsIiksDQogICAgICAgICAgICAgICAgYygiI0U1NzM3MyIsICIjODFDNzg0IiwgIiNGRkYxNzYiLCAiI0UwRTBFMCIpDQogICAgICAgICAgICAgICkpDQoNCiMgVGFibGEgMjogVG9wIDEwIGNvcnJlbGFjaW9uZXMgbcOhcyBmdWVydGVzDQp0b3BfY29ycmVsYWNpb25lcyA8LSBjb3JfZGYgJT4lDQogIGZpbHRlcihTaWduaWZpY2F0aXZhID09ICJTw60iKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhDb3JyZWxhY2lvbikpKSAlPiUNCiAgaGVhZCgxMCkgJT4lDQogIHNlbGVjdChWYXJpYWJsZTEsIFZhcmlhYmxlMiwgQ29ycmVsYWNpb24sIHBfdmFsb3IsIE1hZ25pdHVkKQ0KDQpkYXRhdGFibGUodG9wX2NvcnJlbGFjaW9uZXMsDQogICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSAyOiBUb3AgMTAgQ29ycmVsYWNpb25lcyBNw6FzIEZ1ZXJ0ZXMiLA0KICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KA0KICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwLA0KICAgICAgICAgICAgZG9tID0gJ3QnDQogICAgICAgICAgKSwNCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLA0KICAgICAgICAgIGNsYXNzID0gJ2NlbGwtYm9yZGVyIHN0cmlwZScpICU+JQ0KICBmb3JtYXRTdHlsZShjb2x1bW5zID0gYygxOjUpLCBmb250U2l6ZSA9ICcxNHB4JykgJT4lDQogIGZvcm1hdFJvdW5kKCdDb3JyZWxhY2lvbicsIDMpICU+JQ0KICBmb3JtYXRTaWduaWYoJ3BfdmFsb3InLCAzKQ0KYGBgDQoNCg0KIyMgKipWaXN1YWxpemFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcyoqDQoNCmBgYHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBGVU5DScOTTiBQQVJBIExJTVBJQVIgRUwgRU5UT1JOTyAoT1BDSU9OQUwpDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpsaW1waWFyX29iamV0b3NfYW5hbGlzaXMgPC0gZnVuY3Rpb24oKSB7DQogIG9iamV0b3NfYV9saW1waWFyIDwtIGMoImRpdl9jb21iaW5hZGEiLCAidGlwb19jb211bmFfc3RhdHMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICJkaXZfY2ZnX2Nvbl90aXBvIiwgImRpdl9nb2JfY29uX3RpcG8iLCAiZGl2X3JhdGlvX2Nvbl90aXBvIikNCiAgb2JqZXRvc19leGlzdGVudGVzIDwtIG9iamV0b3NfYV9saW1waWFyW29iamV0b3NfYV9saW1waWFyICVpbiUgbHMoZW52aXIgPSAuR2xvYmFsRW52KV0NCiAgaWYobGVuZ3RoKG9iamV0b3NfZXhpc3RlbnRlcykgPiAwKSB7DQogICAgcm0obGlzdCA9IG9iamV0b3NfZXhpc3RlbnRlcywgZW52aXIgPSAuR2xvYmFsRW52KQ0KICAgIGNhdCgiTGltcGlhZG9zIG9iamV0b3M6IiwgcGFzdGUob2JqZXRvc19leGlzdGVudGVzLCBjb2xsYXBzZSA9ICIsICIpLCAiXG4iKQ0KICB9DQp9DQoNCiMgRWplY3V0YXIgc2kgcXVpZXJlcyBsaW1waWFyIChkZXNjb21lbnRhIGxhIHNpZ3VpZW50ZSBsw61uZWEpDQojIGxpbXBpYXJfb2JqZXRvc19hbmFsaXNpcygpDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgQ0xBU0lGSUNBQ0nDk04gQ09NUExFVEEgWSBDUkVBQ0nDk04gREVMIFRJUE8gREUgQ09NVU5BDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpjcmVhcl9tYXBhX2NvbXVuYXMgPC0gZnVuY3Rpb24oZGZfc291cmNlKSB7DQogICMgRXN0YSBmdW5jacOzbiBjcmVhIGVsIG1hcGEgZGUgY29tdW5hcyBkZSBmb3JtYSBsaW1waWEgY2FkYSB2ZXoNCiAgbWFwYSA8LSBkZl9zb3VyY2UgJT4lDQogICAgZGlzdGluY3QoSURfQ09NVU5BLCBDT01VTkEsIENPRF9DQykgJT4lDQogICAgbXV0YXRlKA0KICAgICAgQ09NVU5BID0gc3RyX3RyaW0oQ09NVU5BKSwNCiAgICAgIFRpcG9fQ29tdW5hID0gY2FzZV93aGVuKA0KICAgICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIkMtVVJCIikgfiAiVXJiYW5hIiwNCiAgICAgICAgc3RyX2RldGVjdChDT0RfQ0MsICJDLVJVUiIpIH4gIlJ1cmFsIiwgDQogICAgICAgIHN0cl9kZXRlY3QoQ09EX0NDLCAiQy1NSVgiKSB+ICJNaXh0YSIsDQogICAgICAgIHN0cl9kZXRlY3QoQ09EX0NDLCAiXlxcZHsyfS1cXGR7Mn0tXFxkezR9JCIpIH4gIkVuIGNvbnN0cnVjY2nDs24iLA0KICAgICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIl5cXGR7Mn0tXFxkezJ9LVxcZHsyfSIpIH4gIkVuIGNvbnN0cnVjY2nDs24iLA0KICAgICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIl5DRUMiKSB+ICJFbiBjb25zdHJ1Y2Npw7NuIiwNCiAgICAgICAgVFJVRSB+ICJObyBlc3BlY2lmaWNhZG8iDQogICAgICApDQogICAgKQ0KICANCiAgcmV0dXJuKG1hcGEpDQp9DQoNCiMgVmVyaWZpY2FyIGRpc3RyaWJ1Y2nDs24NCnRhYmxlKGNvbW11bmVfbWFwJFRpcG9fQ29tdW5hKQ0KDQojIENyZWFyIGVsIG1hcGEgZGUgY29tdW5hcyBmcmVzY28gY2FkYSB2ZXoNCmNvbW11bmVfbWFwIDwtIGNyZWFyX21hcGFfY29tdW5hcyhkZl9yYXcpDQoNCiMgVmVyaWZpY2FyIGRpc3RyaWJ1Y2nDs24NCmNhdCgiRGlzdHJpYnVjacOzbiBkZSB0aXBvcyBkZSBjb211bmE6XG4iKQ0KcHJpbnQodGFibGUoY29tbXVuZV9tYXAkVGlwb19Db211bmEpKQ0KDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgQU7DgUxJU0lTIElOVEVHUkFMIMONTkRJQ0UgU0hBTk5PTiAtIFBPTMONVElDQVMgUMOaQkxJQ0FTIEFDQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFBBTEVUQSBERSBDT0xPUkVTIFkgVEVNQSBDT03Dmk4NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmNvbG9yZXNfY29tdW5hIDwtIGMoDQogICJVcmJhbmEiID0gIiMyRTg2QUIiLCAgICAgICAgICAgIyBBenVsIC0gZGVuc2lkYWQgdXJiYW5hDQogICJSdXJhbCIgPSAiI0EyM0I3MiIsICAgICAgICAgICAgIyBNYWdlbnRhIC0gcnVyYWxpZGFkDQogICJNaXh0YSIgPSAiI0YxOEYwMSIsICAgICAgICAgICAgIyBOYXJhbmphIC0gY29tYmluYWNpw7NuDQogICJFbiBjb25zdHJ1Y2Npw7NuIiA9ICIjQzczRTFEIiwgICAjIFJvam8gLSBkZXNhcnJvbGxvDQogICJObyBlc3BlY2lmaWNhZG8iID0gIiM3RDg0OTEiICAgICMgR3JpcyAtIHNpbiBjbGFzaWZpY2FyDQopDQoNCnRlbWFfY29tdW4gPC0gdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYsIGhqdXN0ID0gMC41LCBjb2xvciA9ICIjMkU4NkFCIiksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXk0MCIsIGhqdXN0ID0gMC41KSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTApLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDExLCBjb2xvciA9ICIjMkU4NkFCIiksDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXk5NSIsIGNvbG9yID0gIndoaXRlIiksDQogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImdyYXk5MCIsIGZpbGwgPSBOQSksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpDQogICkNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBQUkVQQVJBQ0nDk04gREUgREFUT1MNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgQ3JlYXIgbWFwYSBkZSBjb211bmFzDQpjb21tdW5lX21hcCA8LSBkZl9yYXcgJT4lDQogIGRpc3RpbmN0KElEX0NPTVVOQSwgQ09NVU5BLCBDT0RfQ0MpICU+JQ0KICBtdXRhdGUoDQogICAgQ09NVU5BID0gc3RyX3RyaW0oQ09NVU5BKSwNCiAgICBUaXBvX0NvbXVuYSA9IGNhc2Vfd2hlbigNCiAgICAgIHN0cl9kZXRlY3QoQ09EX0NDLCAiQy1VUkIiKSB+ICJVcmJhbmEiLA0KICAgICAgc3RyX2RldGVjdChDT0RfQ0MsICJDLVJVUiIpIH4gIlJ1cmFsIiwgDQogICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIkMtTUlYIikgfiAiTWl4dGEiLA0KICAgICAgc3RyX2RldGVjdChDT0RfQ0MsICJeXFxkezJ9LVxcZHsyfS1cXGR7NH0kIikgfiAiRW4gY29uc3RydWNjacOzbiIsDQogICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIl5cXGR7Mn0tXFxkezJ9LVxcZHsyfSIpIH4gIkVuIGNvbnN0cnVjY2nDs24iLA0KICAgICAgc3RyX2RldGVjdChDT0RfQ0MsICJeQ0VDIikgfiAiRW4gY29uc3RydWNjacOzbiIsDQogICAgICBUUlVFIH4gIk5vIGVzcGVjaWZpY2FkbyINCiAgICApDQogICkNCg0KIyBBZ3JlZ2FyIHRpcG8gZGUgY29tdW5hIGEgY2FkYSBkYXRhc2V0DQpkaXZfY2ZnX2Nvbl90aXBvIDwtIGRpdl9jZmcgJT4lDQogIHNlbGVjdCgtY29udGFpbnMoIlRpcG9fQ29tdW5hIikpICU+JQ0KICBsZWZ0X2pvaW4oY29tbXVuZV9tYXAgJT4lIHNlbGVjdChJRF9DT01VTkEsIFRpcG9fQ29tdW5hKSwgYnkgPSAiSURfQ09NVU5BIikNCg0KZGl2X2dvYl9jb25fdGlwbyA8LSBkaXZfZ29iICU+JQ0KICBzZWxlY3QoLWNvbnRhaW5zKCJUaXBvX0NvbXVuYSIpKSAlPiUNCiAgbGVmdF9qb2luKGNvbW11bmVfbWFwICU+JSBzZWxlY3QoSURfQ09NVU5BLCBUaXBvX0NvbXVuYSksIGJ5ID0gIklEX0NPTVVOQSIpDQoNCmRpdl9yYXRpb19jb25fdGlwbyA8LSBkaXZfcmF0aW8gJT4lDQogIHNlbGVjdCgtY29udGFpbnMoIlRpcG9fQ29tdW5hIikpICU+JQ0KICBsZWZ0X2pvaW4oY29tbXVuZV9tYXAgJT4lIHNlbGVjdChJRF9DT01VTkEsIFRpcG9fQ29tdW5hKSwgYnkgPSAiSURfQ09NVU5BIikNCg0KIyBDb21iaW5hciBkYXRhc2V0cw0KZGl2X2NvbWJpbmFkYSA8LSBiaW5kX3Jvd3MoDQogIGRpdl9jZmdfY29uX3RpcG8gJT4lDQogICAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIG5fcHJveWVjdG9zLCBIX3NoYW5ub24sIHBpZWxvdSwgVGlwb19Db211bmEpICU+JQ0KICAgIG11dGF0ZShUaXBvX0FuYWxpc2lzID0gIkNGRyIpLA0KICANCiAgZGl2X2dvYl9jb25fdGlwbyAlPiUNCiAgICBzZWxlY3QoQ09NVU5BX0lEX05PTUJSRSwgbl9wcm95ZWN0b3MsIEhfc2hhbm5vbiwgcGllbG91LCBUaXBvX0NvbXVuYSkgJT4lDQogICAgbXV0YXRlKFRpcG9fQW5hbGlzaXMgPSAiR29iZXJuYWNpw7NuIiksDQogIA0KICBkaXZfcmF0aW9fY29uX3RpcG8gJT4lDQogICAgc2VsZWN0KENPTVVOQV9JRF9OT01CUkUsIG5fcHJveWVjdG9zID0gbl9wcm95ZWN0b3NfcmF0aW8sIEhfc2hhbm5vbiwgcGllbG91LCBUaXBvX0NvbXVuYSkgJT4lDQogICAgbXV0YXRlKFRpcG9fQW5hbGlzaXMgPSAiUmF0aW8gQUNBIikNCikgJT4lDQogIG11dGF0ZSgNCiAgICBTaGFubm9uX0NhdGVnb3JpYSA9IGNhc2Vfd2hlbigNCiAgICAgIEhfc2hhbm5vbiA8IDAuNSB+ICJNdXkgQmFqYSIsDQogICAgICBIX3NoYW5ub24gPCAxLjAgfiAiQmFqYSIsIA0KICAgICAgSF9zaGFubm9uIDwgMS41IH4gIk1lZGlhIiwNCiAgICAgIEhfc2hhbm5vbiA+PSAxLjUgfiAiQWx0YSINCiAgICApLA0KICAgIEVmaWNpZW5jaWEgPSBIX3NoYW5ub24gLyAobl9wcm95ZWN0b3MgKyAwLjEpDQogICkgJT4lDQogIGZpbHRlcighaXMubmEoSF9zaGFubm9uKSwgIWlzLm5hKFRpcG9fQ29tdW5hKSwgaXMuZmluaXRlKEhfc2hhbm5vbikpDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgRVNUQUTDjVNUSUNBUyBERVNDUklQVElWQVMNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnN0YXRzX3NoYW5ub24gPC0gZGl2X2NvbWJpbmFkYSAlPiUNCiAgZ3JvdXBfYnkoVGlwb19BbmFsaXNpcywgVGlwb19Db211bmEpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbiA9IG4oKSwNCiAgICBtZWFuX3NoYW5ub24gPSBtZWFuKEhfc2hhbm5vbiwgbmEucm0gPSBUUlVFKSwNCiAgICBzZF9zaGFubm9uID0gc2QoSF9zaGFubm9uLCBuYS5ybSA9IFRSVUUpLA0KICAgIG1lZGlhbl9zaGFubm9uID0gbWVkaWFuKEhfc2hhbm5vbiwgbmEucm0gPSBUUlVFKSwNCiAgICBzZSA9IHNkX3NoYW5ub24gLyBzcXJ0KG4pLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKSAlPiUNCiAgZmlsdGVyKG4gPj0gMikNCg0KIyBNb3N0cmFyIHRhYmxhIGRlIGVzdGFkw61zdGljYXMNCmthYmxlKHN0YXRzX3NoYW5ub24sDQogICAgICBjYXB0aW9uID0gIkVzdGFkw61zdGljYXMgZGVsIMONbmRpY2UgU2hhbm5vbiBwb3IgVGlwbyBkZSBDb211bmEgeSBBbsOhbGlzaXMiLA0KICAgICAgZGlnaXRzID0gMykgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgR1LDgUZJQ09TDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgMS4gRGlzdHJpYnVjacOzbiBTaGFubm9uDQpncmFmaWNvXzFfZGlzdHJpYnVjaW9uIDwtIGdncGxvdChkaXZfY29tYmluYWRhLCBhZXMoeCA9IFRpcG9fQ29tdW5hLCB5ID0gSF9zaGFubm9uLCBmaWxsID0gVGlwb19Db211bmEpKSArDQogIGdlb21fdmlvbGluKGFscGhhID0gMC43LCB0cmltID0gRkFMU0UsIGNvbG9yID0gIndoaXRlIiwgbGluZXdpZHRoID0gMC44KSArDQogIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMiwgZmlsbCA9ICJ3aGl0ZSIsIG91dGxpZXIuY29sb3VyID0gIiMyRTg2QUIiLCANCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZSA9IDIsIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC41KSArDQogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IFRpcG9fQ29tdW5hKSwgd2lkdGggPSAwLjE1LCBzaXplID0gMS44LCBhbHBoYSA9IDAuNikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcmVzX2NvbXVuYSwgbmFtZSA9ICJUaXBvIGRlIENvbXVuYSIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfY29tdW5hLCBuYW1lID0gIlRpcG8gZGUgQ29tdW5hIikgKw0KICBmYWNldF93cmFwKH4gVGlwb19BbmFsaXNpcywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIGRlbCDDjW5kaWNlIGRlIFNoYW5ub24gcG9yIFRpcG8gZGUgQ29tdW5hIiwNCiAgICBzdWJ0aXRsZSA9ICJBbsOhbGlzaXMgZGUgZGl2ZXJzaWRhZCBlbiBBZ2VuZGFzIENvbmNyZXRhcyBkZSBBY2Npw7NuIC0gTcOpcmlkYSwgVmVuZXp1ZWxhIiwNCiAgICB5ID0gIsONbmRpY2UgZGUgU2hhbm5vbiAoSCcpIiwgDQogICAgeCA9ICJUaXBvIGRlIENvbXVuYSIsDQogICAgY2FwdGlvbiA9ICJFbGFib3JhZG8gcG9yOiBXaWxsaWFtIEd1dGnDqXJyZXoiDQogICkgKw0KICB0ZW1hX2NvbXVuDQoNCnByaW50KGdyYWZpY29fMV9kaXN0cmlidWNpb24pDQoNCiMgMi4gUmVsYWNpw7NuIHByb3llY3Rvcy1TaGFubm9uDQpncmFmaWNvXzJfcmVsYWNpb24gPC0gZ2dwbG90KGRpdl9jb21iaW5hZGEsIGFlcyh4ID0gbl9wcm95ZWN0b3MsIHkgPSBIX3NoYW5ub24pKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gVGlwb19Db211bmEpLCBzaXplID0gMywgYWxwaGEgPSAwLjcpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBUUlVFLCBjb2xvciA9ICIjMkU4NkFCIiwgDQogICAgICAgICAgICAgIGZpbGwgPSAiIzJFODZBQiIsIGFscGhhID0gMC4yLCBsaW5ld2lkdGggPSAxLjIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfY29tdW5hLCBuYW1lID0gIlRpcG8gZGUgQ29tdW5hIikgKw0KICBmYWNldF93cmFwKH4gVGlwb19BbmFsaXNpcywgc2NhbGVzID0gImZyZWUiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUmVsYWNpw7NuIGVudHJlIE7Dum1lcm8gZGUgUHJveWVjdG9zIHkgRGl2ZXJzaWRhZCBTaGFubm9uIiwNCiAgICBzdWJ0aXRsZSA9ICJBbsOhbGlzaXMgZGUgY29ycmVsYWNpw7NuIGVuIHBvbMOtdGljYXMgQUNBIiwNCiAgICB4ID0gIk7Dum1lcm8gZGUgUHJveWVjdG9zIiwNCiAgICB5ID0gIsONbmRpY2UgZGUgU2hhbm5vbiAoSCcpIiwNCiAgICBjYXB0aW9uID0gIkVsYWJvcmFkbyBwb3I6IFdpbGxpYW0gR3V0acOpcnJleiINCiAgKSArDQogIHRlbWFfY29tdW4NCg0KcHJpbnQoZ3JhZmljb18yX3JlbGFjaW9uKQ0KDQojIDMuIENvbXBhcmF0aXZhIGRlIG1lZGlhcyBjb24gaW50ZXJ2YWxvcyBkZSBjb25maWFuemENCmdyYWZpY29fM19jb21wYXJhdGl2YSA8LSBnZ3Bsb3Qoc3RhdHNfc2hhbm5vbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSByZW9yZGVyKFRpcG9fQ29tdW5hLCBtZWFuX3NoYW5ub24pLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG1lYW5fc2hhbm5vbiwgZmlsbCA9IFRpcG9fQ29tdW5hKSkgKw0KICBnZW9tX2NvbChhbHBoYSA9IDAuOCwgY29sb3IgPSAid2hpdGUiLCBsaW5ld2lkdGggPSAwLjgpICsNCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IHBtYXgoMCwgbWVhbl9zaGFubm9uIC0gc2UpLCANCiAgICAgICAgICAgICAgICAgICAgeW1heCA9IG1lYW5fc2hhbm5vbiArIHNlKSwgDQogICAgICAgICAgICAgICAgd2lkdGggPSAwLjMsIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC44KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzcHJpbnRmKCIlLjJmIiwgbWVhbl9zaGFubm9uKSksIA0KICAgICAgICAgICAgdmp1c3QgPSAtMS41LCBzaXplID0gNCwgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIiMyRTg2QUIiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfY29tdW5hLCBuYW1lID0gIlRpcG8gZGUgQ29tdW5hIikgKw0KICBmYWNldF93cmFwKH4gVGlwb19BbmFsaXNpcywgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICLDjW5kaWNlIGRlIFNoYW5ub24gUHJvbWVkaW8gcG9yIFRpcG8gZGUgQ29tdW5hIiwNCiAgICBzdWJ0aXRsZSA9ICJCYXJyYXMgZGUgZXJyb3IgcmVwcmVzZW50YW4gZXJyb3IgZXN0w6FuZGFyIGRlIGxhIG1lZGlhIiwNCiAgICB4ID0gIlRpcG8gZGUgQ29tdW5hIiwNCiAgICB5ID0gIlNoYW5ub24gUHJvbWVkaW8gKEgnKSIsDQogICAgY2FwdGlvbiA9ICJFbGFib3JhZG8gcG9yOiBXaWxsaWFtIEd1dGnDqXJyZXoiDQogICkgKw0KICB0ZW1hX2NvbXVuDQoNCnByaW50KGdyYWZpY29fM19jb21wYXJhdGl2YSkNCg0KIyA0LiBIZWF0bWFwIGRlIGZyZWN1ZW5jaWFzDQpkYXRvc19oZWF0bWFwIDwtIGRpdl9jb21iaW5hZGEgJT4lDQogIGZpbHRlcihUaXBvX0FuYWxpc2lzICVpbiUgYygiQ0ZHIiwgIkdvYmVybmFjacOzbiIpKSAlPiUNCiAgY291bnQoVGlwb19BbmFsaXNpcywgVGlwb19Db211bmEsIFNoYW5ub25fQ2F0ZWdvcmlhKSAlPiUNCiAgY29tcGxldGUoVGlwb19BbmFsaXNpcywgVGlwb19Db211bmEsIFNoYW5ub25fQ2F0ZWdvcmlhLCBmaWxsID0gbGlzdChuID0gMCkpDQoNCmdyYWZpY29fNF9oZWF0bWFwIDwtIGdncGxvdChkYXRvc19oZWF0bWFwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gU2hhbm5vbl9DYXRlZ29yaWEsIHkgPSBUaXBvX0NvbXVuYSwgZmlsbCA9IG4pKSArDQogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIsIGxpbmV3aWR0aCA9IDAuOCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiwgDQogICAgICAgICAgICAgICAgY29sb3IgPSBpZmVsc2UobiA+PSBtYXgobikvMiwgIndoaXRlIiwgImJsYWNrIikpLCANCiAgICAgICAgICAgIGZvbnRmYWNlID0gImJvbGQiLCBzaXplID0gNCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KA0KICAgIGxvdyA9ICIjQzZEQkVGIiwgICAgIyBBenVsIGNsYXJvDQogICAgaGlnaCA9ICIjMDg1MTlDIiwgICAjIEF6dWwgb3NjdXJvDQogICAgbmFtZSA9ICJGcmVjdWVuY2lhIg0KICApICsNCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArDQogIGZhY2V0X3dyYXAofiBUaXBvX0FuYWxpc2lzKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBGcmVjdWVuY2lhczogVGlwbyBDb211bmEgdnMuIFNoYW5ub24iLA0KICAgIHN1YnRpdGxlID0gIk1hcGEgZGUgY2Fsb3IgcGFyYSBhbsOhbGlzaXMgQ0ZHIHkgR29iZXJuYWNpw7NuIiwNCiAgICB4ID0gIkNhdGVnb3LDrWEgU2hhbm5vbiIsDQogICAgeSA9ICJUaXBvIGRlIENvbXVuYSIsDQogICAgY2FwdGlvbiA9ICJFbGFib3JhZG8gcG9yOiBXaWxsaWFtIEd1dGnDqXJyZXoiDQogICkgKw0KICB0ZW1hX2NvbXVuDQoNCnByaW50KGdyYWZpY29fNF9oZWF0bWFwKQ0KDQojIDUuIMONbmRpY2UgZGUgUGllbG91IHZzIFNoYW5ub24NCmdyYWZpY29fNV9waWVsb3UgPC0gZ2dwbG90KGRpdl9jb21iaW5hZGEsIGFlcyh4ID0gbl9wcm95ZWN0b3MsIHkgPSBIX3NoYW5ub24pKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gVGlwb19Db211bmEpLCBzaXplID0gMywgYWxwaGEgPSAwLjcpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICIjMkU4NkFCIiwgDQogICAgICAgICAgICAgIGZpbGwgPSAiIzJFODZBQiIsIGFscGhhID0gMC4yLCBsaW5ld2lkdGggPSAxLjIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfY29tdW5hLCBuYW1lID0gIlRpcG8gZGUgQ29tdW5hIikgKw0KICBmYWNldF93cmFwKH4gVGlwb19BbmFsaXNpcykgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJlbGFjacOzbiBlbnRyZSBOw7ptZXJvIGRlIFByb3llY3RvcyB5IFNoYW5ub24iLA0KICAgIHN1YnRpdGxlID0gIkFuw6FsaXNpcyBkZSBwcm95ZWN0b3MgeSBkaXZlcnNpZGFkIGVuIEFDQSIsDQogICAgeCA9ICJOw7ptZXJvIGRlIFByb3llY3RvcyIsDQogICAgeSA9ICLDjW5kaWNlIGRlIFNoYW5ub24gKEgnKSIsDQogICAgY2FwdGlvbiA9ICJFbGFib3JhZG8gcG9yOiBXaWxsaWFtIEd1dGnDqXJyZXoiDQogICkgKw0KICB0ZW1hX2NvbXVuDQoNCnByaW50KGdyYWZpY29fNV9waWVsb3UpDQoNCmBgYA0KDQojIyoqNC44IE1vZGVsbyBkZSBDb3JyZWxhY2nDs24gcG9yIFRpcG8gZGUgQ29tdW5hKioNCg0KYGBge3J9DQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS1FU1RBRMONU1RJQ0FTIERFU0NSSVBUSVZBUyBQT1IgR1JVUE8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jDQp0aXBvX2NvbXVuYV9zdGF0cyA8LSBkaXZfY29tYmluYWRhICU+JQ0KICBncm91cF9ieShUaXBvX0FuYWxpc2lzLCBUaXBvX0NvbXVuYSkgJT4lICAjIENPUlJFQ0NJw5NOIFBSSU5DSVBBTCBBUVXDjQ0KICBzdW1tYXJpc2UoDQogICAgbl9jb211bmFzID0gbigpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIE7Dum1lcm8gZGUgb2JzZXJ2YWNpb25lcyBwb3IgZ3J1cG8NCiAgICBtZWFuX3NoYW5ub24gPSBtZWFuKEhfc2hhbm5vbiwgbmEucm0gPSBUUlVFKSwgICAgICAgICAgIyBNZWRpYSBkZWwgw61uZGljZSBTaGFubm9uDQogICAgc2Rfc2hhbm5vbiA9IHNkKEhfc2hhbm5vbiwgbmEucm0gPSBUUlVFKSwgICAgICAgICAgICAgICMgRGVzdmlhY2nDs24gZXN0w6FuZGFyIFNoYW5ub24NCiAgICBtZWFuX3BpZWxvdSA9IG1lYW4ocGllbG91LCBuYS5ybSA9IFRSVUUpLCAgICAgICAgICAgICAgIyBNZWRpYSBkZWwgw61uZGljZSBQaWVsb3UNCiAgICBzZF9waWVsb3UgPSBzZChwaWVsb3UsIG5hLnJtID0gVFJVRSksICAgICAgICAgICAgICAgICAgIyBEZXN2aWFjacOzbiBlc3TDoW5kYXIgUGllbG91DQogICAgbWVhbl9uX3Byb3llY3RvcyA9IG1lYW4obl9wcm95ZWN0b3MsIG5hLnJtID0gVFJVRSksICAgICMgTWVkaWEgbsO6bWVybyBkZSBwcm95ZWN0b3MNCiAgICBzZF9uX3Byb3llY3RvcyA9IHNkKG5fcHJveWVjdG9zLCBuYS5ybSA9IFRSVUUpLCAgICAgICAgIyBEZXN2aWFjacOzbiBlc3TDoW5kYXIgcHJveWVjdG9zDQogICAgLmdyb3VwcyA9ICJkcm9wIiAgIyBFbGltaW5hIGVsIGFncnVwYW1pZW50byBkZXNwdcOpcyBkZWwgY8OhbGN1bG8NCiAgKQ0KDQojIE1vc3RyYXIgcmVzdWx0YWRvcyBkZSBlc3RhZMOtc3RpY2FzIGRlc2NyaXB0aXZhcyBlbiBmb3JtYXRvIHRhYmxhDQpjYXQoIlxuPT09PSBFU1RBRMONU1RJQ0FTIERFU0NSSVBUSVZBUyBQT1IgVElQTyBERSBDT01VTkEgPT09PVxuIikNCmthYmxlKHRpcG9fY29tdW5hX3N0YXRzLCANCiAgICAgIGNhcHRpb24gPSAiRXN0YWTDrXN0aWNhcyBEZXNjcmlwdGl2YXMgcG9yIFRpcG8gZGUgQ29tdW5hIHkgVGlwbyBkZSBBbsOhbGlzaXMiLA0KICAgICAgZGlnaXRzID0gMykgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkNCg0KIyBQQVNPIDM6IFBSVUVCQVMgTk8gUEFSQU3DiVRSSUNBUyBLUlVTS0FMLVdBTExJUw0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBFc3RhcyBwcnVlYmFzIGV2YWzDumFuIHNpIGV4aXN0ZW4gZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXMgZW50cmUgZ3J1cG9zDQojIEgwOiBObyBoYXkgZGlmZXJlbmNpYXMgZW50cmUgdGlwb3MgZGUgY29tdW5hDQojIEgxOiBFeGlzdGVuIGRpZmVyZW5jaWFzIHNpZ25pZmljYXRpdmFzIGVudHJlIHRpcG9zIGRlIGNvbXVuYQ0KDQprcnVza2FsX3NoYW5ub24gPC0ga3J1c2thbC50ZXN0KEhfc2hhbm5vbiB+IFRpcG9fQ29tdW5hLCBkYXRhID0gZGl2X2NvbWJpbmFkYSkNCmtydXNrYWxfcGllbG91ICA8LSBrcnVza2FsLnRlc3QocGllbG91IH4gVGlwb19Db211bmEsIGRhdGEgPSBkaXZfY29tYmluYWRhKQ0Ka3J1c2thbF9ucHJveSAgIDwtIGtydXNrYWwudGVzdChuX3Byb3llY3RvcyB+IFRpcG9fQ29tdW5hLCBkYXRhID0gZGl2X2NvbWJpbmFkYSkNCg0KIyAgQ09SUkVMQUNJT05FUyBERSBTUEVBUk1BTiBQT1IgU1VCR1JVUE9TDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIENhbGN1bGFtb3MgY29ycmVsYWNpb25lcyBzZXBhcmFkYW1lbnRlIHBhcmEgY2FkYSBjb21iaW5hY2nDs24gZGUgdGlwbyBkZSBjb211bmENCiMgeSB0aXBvIGRlIGFuw6FsaXNpcywgbG8gcXVlIG5vcyBwZXJtaXRlIGlkZW50aWZpY2FyIHBhdHJvbmVzIGVzcGVjw61maWNvcw0KDQpjb3JyZWxhY2lvbmVzX3Bvcl90aXBvIDwtIGRpdl9jb21iaW5hZGEgJT4lDQogIGdyb3VwX2J5KFRpcG9fQ29tdW5hLCBUaXBvX0FuYWxpc2lzKSAlPiUgICMgQ09SUkVDQ0nDk04gUFJJTkNJUEFMIEFRVcONIFRBTUJJw4lODQogIHN1bW1hcmlzZSgNCiAgICAjIENvcnJlbGFjacOzbiBlbnRyZSBuw7ptZXJvIGRlIHByb3llY3RvcyB5IGRpdmVyc2lkYWQgU2hhbm5vbg0KICAgIGNvcl9uX3Byb3lfSCA9IGNvcihuX3Byb3llY3RvcywgSF9zaGFubm9uLCBtZXRob2QgPSAic3BlYXJtYW4iLCB1c2UgPSAiY29tcGxldGUub2JzIiksDQogICAgcF9uX3Byb3lfSCA9IHRyeUNhdGNoKHsNCiAgICAgIGNvci50ZXN0KG5fcHJveWVjdG9zLCBIX3NoYW5ub24sIG1ldGhvZCA9ICJzcGVhcm1hbiIsIGV4YWN0ID0gRkFMU0UpJHAudmFsdWUNCiAgICB9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIE5BKSwgICMgTWFuZWpvIGRlIGVycm9yZXMgcGFyYSBncnVwb3MgcGVxdWXDsW9zDQogICAgDQogICAgIyBDb3JyZWxhY2nDs24gZW50cmUgU2hhbm5vbiB5IFBpZWxvdSAoZGl2ZXJzaWRhZCB2cyBlcXVpZGFkKQ0KICAgIGNvcl9IX3BpZWxvdSA9IGNvcihIX3NoYW5ub24sIHBpZWxvdSwgbWV0aG9kID0gInNwZWFybWFuIiwgdXNlID0gImNvbXBsZXRlLm9icyIpLA0KICAgIHBfSF9waWVsb3UgPSB0cnlDYXRjaCh7DQogICAgICBjb3IudGVzdChIX3NoYW5ub24sIHBpZWxvdSwgbWV0aG9kID0gInNwZWFybWFuIiwgZXhhY3QgPSBGQUxTRSkkcC52YWx1ZQ0KICAgIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgTkEpLCAgIyBNYW5lam8gZGUgZXJyb3JlcyBwYXJhIGdydXBvcyBwZXF1ZcOxb3MNCiAgICANCiAgICBuID0gbigpLCAgIyBUYW1hw7FvIGRlIG11ZXN0cmEgcG9yIGdydXBvDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApICU+JQ0KICAjIEFncmVnYW1vcyBpbnRlcnByZXRhY2nDs24gZGUgbGEgc2lnbmlmaWNhbmNpYSBlc3RhZMOtc3RpY2ENCiAgbXV0YXRlKA0KICAgIHNpZ19uX3Byb3lfSCA9IGNhc2Vfd2hlbigNCiAgICAgIGlzLm5hKHBfbl9wcm95X0gpIH4gIk5vIGNhbGN1bGFibGUiLA0KICAgICAgcF9uX3Byb3lfSCA8IDAuMDAxIH4gIioqKiIsDQogICAgICBwX25fcHJveV9IIDwgMC4wMSB+ICIqKiIsIA0KICAgICAgcF9uX3Byb3lfSCA8IDAuMDUgfiAiKiIsDQogICAgICBUUlVFIH4gIm5zIg0KICAgICksDQogICAgc2lnX0hfcGllbG91ID0gY2FzZV93aGVuKA0KICAgICAgaXMubmEocF9IX3BpZWxvdSkgfiAiTm8gY2FsY3VsYWJsZSIsDQogICAgICBwX0hfcGllbG91IDwgMC4wMDEgfiAiKioqIiwNCiAgICAgIHBfSF9waWVsb3UgPCAwLjAxIH4gIioqIiwNCiAgICAgIHBfSF9waWVsb3UgPCAwLjA1IH4gIioiLCANCiAgICAgIFRSVUUgfiAibnMiDQogICAgKQ0KICApDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgQU7DgUxJU0lTIERFIENPUlJFTEFDScOTTiBQT1IgVElQTyBERSBDT01VTkENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyAgUHJlcGFyYXIgZGF0b3MgcG9yIHRpcG8gZGUgY29tdW5hDQphbmFsaXNpc19wb3JfdGlwbyA8LSBmdW5jdGlvbihkYXRhKSB7DQogICMgQ2FsY3VsYXIgY29ycmVsYWNpb25lcyBwYXJhIGNhZGEgdGlwbyBkZSBjb211bmEgeSBhbsOhbGlzaXMNCiAgdGlwb3NfY29ycmVsYWNpb24gPC0gZGF0YSAlPiUNCiAgICBncm91cF9ieShUaXBvX0NvbXVuYSwgVGlwb19BbmFsaXNpcykgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgbiA9IG4oKSwNCiAgICAgIGNvcl9wcm95ZWN0b3Nfc2hhbm5vbiA9IGNvcihuX3Byb3llY3RvcywgSF9zaGFubm9uLCBtZXRob2QgPSAic3BlYXJtYW4iLCB1c2UgPSAiY29tcGxldGUub2JzIiksDQogICAgICBwX3ZhbG9yID0gdHJ5Q2F0Y2goew0KICAgICAgICBjb3IudGVzdChuX3Byb3llY3RvcywgSF9zaGFubm9uLCBtZXRob2QgPSAic3BlYXJtYW4iKSRwLnZhbHVlDQogICAgICB9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIE5BKSwNCiAgICAgIC5ncm91cHMgPSAiZHJvcCINCiAgICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIHNpZ25pZmljYW5jaWEgPSBjYXNlX3doZW4oDQogICAgICAgIHBfdmFsb3IgPCAwLjAwMSB+ICIqKioiLA0KICAgICAgICBwX3ZhbG9yIDwgMC4wMSB+ICIqKiIsDQogICAgICAgIHBfdmFsb3IgPCAwLjA1IH4gIioiLA0KICAgICAgICBUUlVFIH4gIm5zIg0KICAgICAgKSwNCiAgICAgIG1hZ25pdHVkID0gY2FzZV93aGVuKA0KICAgICAgICBhYnMoY29yX3Byb3llY3Rvc19zaGFubm9uKSA+IDAuOCB+ICJNdXkgZnVlcnRlIiwNCiAgICAgICAgYWJzKGNvcl9wcm95ZWN0b3Nfc2hhbm5vbikgPiAwLjYgfiAiRnVlcnRlIiwNCiAgICAgICAgYWJzKGNvcl9wcm95ZWN0b3Nfc2hhbm5vbikgPiAwLjQgfiAiTW9kZXJhZGEiLA0KICAgICAgICBUUlVFIH4gIkTDqWJpbCINCiAgICAgICkNCiAgICApDQogIA0KICByZXR1cm4odGlwb3NfY29ycmVsYWNpb24pDQp9DQoNCiMgIEVqZWN1dGFyIGFuw6FsaXNpcw0KcmVzdWx0YWRvc190aXBvX2NvbXVuYSA8LSBhbmFsaXNpc19wb3JfdGlwbyhkaXZfY29tYmluYWRhKQ0KDQojICBDcmVhciB0YWJsYSBkZSByZXN1bHRhZG9zIGZvcm1hdGVhZGENCnRhYmxhX3Jlc3VsdGFkb3MgPC0gcmVzdWx0YWRvc190aXBvX2NvbXVuYSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhjb3JfcHJveWVjdG9zX3NoYW5ub24pKSkgJT4lDQogIHNlbGVjdCgNCiAgICBUaXBvX0NvbXVuYSwNCiAgICBUaXBvX0FuYWxpc2lzLA0KICAgIG4sDQogICAgcmhvID0gY29yX3Byb3llY3Rvc19zaGFubm9uLA0KICAgIHBfdmFsb3IsDQogICAgc2lnbmlmaWNhbmNpYSwNCiAgICBtYWduaXR1ZA0KICApDQoNCiMgTW9zdHJhciB0YWJsYSBjb24gZm9ybWF0bw0Ka2FibGUodGFibGFfcmVzdWx0YWRvcywNCiAgICAgIGNhcHRpb24gPSAiQ29ycmVsYWNpb25lcyBkZSBTcGVhcm1hbiBwb3IgVGlwbyBkZSBDb211bmEgeSBBbsOhbGlzaXMiLA0KICAgICAgY29sLm5hbWVzID0gYygiVGlwbyBDb211bmEiLCAiVGlwbyBBbsOhbGlzaXMiLCAibiIsICLPgSIsICJwLXZhbG9yIiwgIlNpZy4iLCAiTWFnbml0dWQiKSwNCiAgICAgIGRpZ2l0cyA9IDMpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRkFMU0UpICU+JQ0KICByb3dfc3BlYygwLCBib2xkID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKA0KICAgIHdoaWNoKHRhYmxhX3Jlc3VsdGFkb3MkbWFnbml0dWQgPT0gIk11eSBmdWVydGUiKSwgDQogICAgYm9sZCA9IFRSVUUsIA0KICAgIGNvbG9yID0gIndoaXRlIiwgDQogICAgYmFja2dyb3VuZCA9ICIjMWI5ZTc3Ig0KICApICU+JQ0KICByb3dfc3BlYygNCiAgICB3aGljaCh0YWJsYV9yZXN1bHRhZG9zJG1hZ25pdHVkID09ICJGdWVydGUiKSwgDQogICAgYm9sZCA9IFRSVUUsIA0KICAgIGNvbG9yID0gIndoaXRlIiwgDQogICAgYmFja2dyb3VuZCA9ICIjNjZhNjFlIg0KICApDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGTFVKTyBERSBUUkFCQUpPIElOVEVHUkFETzogQU7DgUxJU0lTIEdSw4FGSUNPIFBPUiBUSVBPIERFIENPTVVOQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCg0KIyBBY3RpdmFyIENhaXJvIGVuIFdpbmRvd3MgcGFyYSBzb3BvcnRlIFVuaWNvZGUgKGV2aXRhIHByb2JsZW1hcyBjb24gJ3InLCBzw61tYm9sb3MsIGV0Yy4pDQppZiAoLlBsYXRmb3JtJE9TLnR5cGUgPT0gIndpbmRvd3MiKSB7DQogIG9wdGlvbnMoYml0bWFwVHlwZSA9ICJjYWlybyIpDQp9DQoNCiMgUGFsZXRhIGRlIGNvbG9yZXMgbWVqb3JhZGEgcG9yIHRpcG8gZGUgY29tdW5hDQpjb2xvcmVzX2NvbXVuYV9tZWpvcmFkb3MgPC0gYygNCiAgIkVuIGNvbnN0cnVjY2nDs24iID0gIiNDNzNFMUQiLA0KICAiTWl4dGEiID0gIiNGMThGMDEiLA0KICAiUnVyYWwiID0gIiNBMjNCNzIiLA0KICAiVXJiYW5hIiA9ICIjMkU4NkFCIg0KKQ0KDQojIFRlbWEgYWNhZMOpbWljbyBwZXJzb25hbGl6YWRvDQp0ZW1hX2FjYWRlbWljbyA8LSB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiwgaGp1c3QgPSAwLjUsIG1hcmdpbiA9IG1hcmdpbihiID0gMTApKSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgaGp1c3QgPSAwLjUsIGNvbG9yID0gImdyYXkzMCIsIG1hcmdpbiA9IG1hcmdpbihiID0gMTUpKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSwgY29sb3IgPSAiIzJFODZBQiIpLA0KICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5OTUiLCBjb2xvciA9ICJ3aGl0ZSIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTUiLCBzaXplID0gMC41KSwNCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGNvbG9yID0gImdyYXk1MCIsIGhqdXN0ID0gMSkNCiAgKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDEuIEhFQVRNQVAgREUgQ09SUkVMQUNJT05FUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjcmVhcl9oZWF0bWFwIDwtIGZ1bmN0aW9uKGNvcnJlbGFjaW9uZXNfcG9yX3RpcG8pIHsNCiAgY29yX21lbHQgPC0gY29ycmVsYWNpb25lc19wb3JfdGlwbyAlPiUNCiAgICBzZWxlY3QoVGlwb19Db211bmEsIFRpcG9fQW5hbGlzaXMsIGNvcl9uX3Byb3lfSCwgbikgJT4lDQogICAgbXV0YXRlKA0KICAgICAgZXRpcXVldGEgPSBzcHJpbnRmKCJyPSUuMmZcbm49JWQiLCBjb3Jfbl9wcm95X0gsIG4pDQogICAgKQ0KICANCiAgZ2dwbG90KGNvcl9tZWx0LCBhZXMoeCA9IFRpcG9fQW5hbGlzaXMsIHkgPSBUaXBvX0NvbXVuYSwgZmlsbCA9IGNvcl9uX3Byb3lfSCkpICsNCiAgICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGV0aXF1ZXRhKSwgc2l6ZSA9IDMuNSkgKw0KICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKA0KICAgICAgbG93ID0gIiNkNzMwMjciLCANCiAgICAgIG1pZCA9ICIjZmZmZmJmIiwgDQogICAgICBoaWdoID0gIiMxYTk4NTAiLA0KICAgICAgbWlkcG9pbnQgPSAwLA0KICAgICAgbGltaXRzID0gYygtMSwgMSksDQogICAgICBuYW1lID0gIkNvcnJlbGFjacOzbiAocikiDQogICAgKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIkNvcnJlbGFjaW9uZXMgcG9yIFRpcG8gZGUgQ29tdW5hIHkgQW7DoWxpc2lzIiwNCiAgICAgIHN1YnRpdGxlID0gIkNvZWZpY2llbnRlIGRlIFNwZWFybWFuIGVudHJlIE7CsCBQcm95ZWN0b3MgZSDDjW5kaWNlIGRlIFNoYW5ub24iLA0KICAgICAgeCA9ICJUaXBvIGRlIEFuw6FsaXNpcyIsDQogICAgICB5ID0gIlRpcG8gZGUgQ29tdW5hIiwNCiAgICAgIGNhcHRpb24gPSAiRWxhYm9yYWNpw7NuIHByb3BpYTogV2lsbGlhbSBBLiBHdXRpw6lycmV6IFYuIHwgTW9ub2dyYWbDrWEgQUNBIC0gRXN0YWRvIE3DqXJpZGEiDQogICAgKSArDQogICAgdGVtYV9hY2FkZW1pY28gKw0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgMi4gR1LDgUZJQ08gREUgRElTUEVSU0nDk04NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY3JlYXJfZGlzcGVyc2lvbiA8LSBmdW5jdGlvbihkaXZfY29tYmluYWRhKSB7DQogIGdncGxvdChkaXZfY29tYmluYWRhLCBhZXMoeCA9IG5fcHJveWVjdG9zLCB5ID0gSF9zaGFubm9uLCBjb2xvciA9IFRpcG9fQ29tdW5hKSkgKw0KICAgIGdlb21fcG9pbnQoc2l6ZSA9IDIuNSwgYWxwaGEgPSAwLjcpICsNCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGFscGhhID0gMC4yLCBzaXplID0gMS4yKSArDQogICAgZmFjZXRfd3JhcCh+IFRpcG9fQW5hbGlzaXMsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDMpICsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3Jlc19jb211bmFfbWVqb3JhZG9zLCBuYW1lID0gIlRpcG8gZGUgQ29tdW5hIikgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICJSZWxhY2nDs24gZW50cmUgTsO6bWVybyBkZSBQcm95ZWN0b3MgeSBEaXZlcnNpZGFkIFNoYW5ub24iLA0KICAgICAgc3VidGl0bGUgPSAiTMOtbmVhcyBkZSB0ZW5kZW5jaWEgYWp1c3RhZGFzIHBvciByZWdyZXNpw7NuIGxpbmVhbCIsDQogICAgICB4ID0gIk7Dum1lcm8gZGUgUHJveWVjdG9zIHBvciBDb211bmEiLA0KICAgICAgeSA9ICLDjW5kaWNlIGRlIFNoYW5ub24gKEgnKSIsDQogICAgICBjYXB0aW9uID0gIkVsYWJvcmFjacOzbiBwcm9waWE6IFdpbGxpYW0gQS4gR3V0acOpcnJleiBWLiB8IE1vbm9ncmFmw61hIEFDQSAtIEVzdGFkbyBNw6lyaWRhIg0KICAgICkgKw0KICAgIHRlbWFfYWNhZGVtaWNvICsNCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAzLiBCQVJSQVMgREUgQ09SUkVMQUNJw5NOIENPTiBJTlRFUlZBTE9TIERFIENPTkZJQU5aQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjcmVhcl9iYXJyYXNfY29ycmVsYWNpb25faWMgPC0gZnVuY3Rpb24oY29ycmVsYWNpb25lc19wb3JfdGlwbykgew0KICBkYXRvc19iYXJyYXMgPC0gY29ycmVsYWNpb25lc19wb3JfdGlwbyAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKHBfbl9wcm95X0gpLCBwX25fcHJveV9IIDwgMC4wNSkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgc2VfYXByb3ggPSBzcXJ0KCgxIC0gY29yX25fcHJveV9IXjIpIC8gKG4gLSAyKSksDQogICAgICBpY19pbmZlcmlvciA9IHBtYXgoLTEsIGNvcl9uX3Byb3lfSCAtIDEuOTYgKiBzZV9hcHJveCksDQogICAgICBpY19zdXBlcmlvciA9IHBtaW4oMSwgY29yX25fcHJveV9IICsgMS45NiAqIHNlX2Fwcm94KSwNCiAgICAgIGV0aXF1ZXRhX2NvbXBsZXRhID0gc3ByaW50Zigicj0lLjNmXG4oSUM6ICUuMmYsICUuMmYpXG5uPSVkIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yX25fcHJveV9ILCBpY19pbmZlcmlvciwgaWNfc3VwZXJpb3IsIG4pLA0KICAgICAgT3JkZW4gPSBwYXN0ZShUaXBvX0NvbXVuYSwgVGlwb19BbmFsaXNpcywgc2VwID0gIiAtICIpDQogICAgKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MoYWJzKGNvcl9uX3Byb3lfSCkpKQ0KICANCiAgaWYgKG5yb3coZGF0b3NfYmFycmFzKSA9PSAwKSB7DQogICAgd2FybmluZygiTm8gaGF5IGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMgKHAgPCAwLjA1KSBwYXJhIG1vc3RyYXIuIikNCiAgICByZXR1cm4oTlVMTCkNCiAgfQ0KICANCiAgZ2dwbG90KGRhdG9zX2JhcnJhcywgYWVzKHggPSByZW9yZGVyKE9yZGVuLCBjb3Jfbl9wcm95X0gpLCB5ID0gY29yX25fcHJveV9ILCBmaWxsID0gVGlwb19Db211bmEpKSArDQogICAgZ2VvbV9jb2woYWxwaGEgPSAwLjgsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuMykgKw0KICAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBpY19pbmZlcmlvciwgeW1heCA9IGljX3N1cGVyaW9yKSwgDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMywgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC44KSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGV0aXF1ZXRhX2NvbXBsZXRhKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gaWZlbHNlKGRhdG9zX2JhcnJhcyRjb3Jfbl9wcm95X0ggPj0gMCwgLTAuMSwgMS4xKSwNCiAgICAgICAgICAgICAgc2l6ZSA9IDMuMiwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJzb2xpZCIsIGFscGhhID0gMC41KSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3Jlc19jb211bmFfbWVqb3JhZG9zLCBuYW1lID0gIlRpcG8gZGUgQ29tdW5hIikgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIkNvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgY29uIElDICg5NSUpIiwNCiAgICAgIHN1YnRpdGxlID0gIlNvbG8gcCA8IDAuMDUgfCBCYXJyYXMgbXVlc3RyYW4gaW5jZXJ0aWR1bWJyZSBlc3RhZMOtc3RpY2EiLA0KICAgICAgeCA9ICJUaXBvIGRlIENvbXVuYSAtIFRpcG8gZGUgQW7DoWxpc2lzIiwNCiAgICAgIHkgPSAiQ29lZmljaWVudGUgZGUgU3BlYXJtYW4gKHIpIiwNCiAgICAgIGNhcHRpb24gPSAiSUMgPSBJbnRlcnZhbG8gZGUgQ29uZmlhbnphIHwgRWxhYm9yYWNpw7NuIHByb3BpYTogV2lsbGlhbSBBLiBHdXRpw6lycmV6IFYuIg0KICAgICkgKw0KICAgIHRlbWFfYWNhZGVtaWNvICsNCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC0xLjIsIDEuMiksIGJyZWFrcyA9IHNlcSgtMSwgMSwgMC4yNSkpDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgNC4gUkVEIERFIENPUlJFTEFDSU9ORVMgU0lHTklGSUNBVElWQVMNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY3JlYXJfcmVkX2NvcnJlbGFjaW9uZXMgPC0gZnVuY3Rpb24oY29ycmVsYWNpb25lc19wb3JfdGlwbykgew0KICBkYXRvc19yZWQgPC0gY29ycmVsYWNpb25lc19wb3JfdGlwbyAlPiUNCiAgICBmaWx0ZXIoIWlzLm5hKHBfbl9wcm95X0gpLCBwX25fcHJveV9IIDwgMC4wMSwgYWJzKGNvcl9uX3Byb3lfSCkgPiAwLjUpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIE5vZG8gPSBwYXN0ZShUaXBvX0NvbXVuYSwgVGlwb19BbmFsaXNpcywgc2VwID0gIlxuIiksDQogICAgICBUYW1hw7FvID0gYWJzKGNvcl9uX3Byb3lfSCkgKiAyMA0KICAgICkNCiAgDQogIGlmIChucm93KGRhdG9zX3JlZCkgPT0gMCkgew0KICAgIHdhcm5pbmcoIk5vIGhheSBjb3JyZWxhY2lvbmVzIHNpZ25pZmljYXRpdmFzIChwIDwgMC4wMSwgfHJ8ID4gMC41KS4iKQ0KICAgIHJldHVybihOVUxMKQ0KICB9DQogIA0KICBuX25vZG9zIDwtIG5yb3coZGF0b3NfcmVkKQ0KICBhbmd1bG9zIDwtIHNlcSgwLCAyKnBpLCBsZW5ndGgub3V0ID0gbl9ub2RvcyArIDEpWzE6bl9ub2Rvc10NCiAgZGF0b3NfcmVkJHggPC0gY29zKGFuZ3Vsb3MpICogKDEgKyBhYnMoZGF0b3NfcmVkJGNvcl9uX3Byb3lfSCkpDQogIGRhdG9zX3JlZCR5IDwtIHNpbihhbmd1bG9zKSAqICgxICsgYWJzKGRhdG9zX3JlZCRjb3Jfbl9wcm95X0gpKQ0KICANCiAgY2VudHJvX3ggPC0gbWVhbihkYXRvc19yZWQkeCkNCiAgY2VudHJvX3kgPC0gbWVhbihkYXRvc19yZWQkeSkNCiAgDQogIGRhdG9zX2ZpbHRyYWRvcyA8LSBkYXRvc19yZWQgJT4lIGZpbHRlcihhYnMoY29yX25fcHJveV9IKSA+IDAuOCkNCiAgaWYgKG5yb3coZGF0b3NfZmlsdHJhZG9zKSA+IDApIHsNCiAgICBkYXRvc19maWx0cmFkb3MkeF9jZW50cm8gPC0gY2VudHJvX3gNCiAgICBkYXRvc19maWx0cmFkb3MkeV9jZW50cm8gPC0gY2VudHJvX3kNCiAgfSBlbHNlIHsNCiAgICBkYXRvc19maWx0cmFkb3MgPC0gZGF0b3NfcmVkWzAsIF0NCiAgfQ0KDQogIGdncGxvdChkYXRvc19yZWQsIGFlcyh4ID0geCwgeSA9IHkpKSArDQogICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IFRhbWHDsW8sIGNvbG9yID0gVGlwb19Db211bmEpLCBhbHBoYSA9IDAuOCkgKw0KICAgIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSBwYXN0ZTAoTm9kbywgIlxucj0iLCByb3VuZChjb3Jfbl9wcm95X0gsIDIpKSksDQogICAgICAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIGZvbnRmYWNlID0gImJvbGQiLA0KICAgICAgICAgICAgICAgICAgICBib3gucGFkZGluZyA9IDAuNSwgcG9pbnQucGFkZGluZyA9IDAuMykgKw0KICAgIGdlb21fc2VnbWVudChkYXRhID0gZGF0b3NfZmlsdHJhZG9zLA0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCB4ZW5kID0geF9jZW50cm8sIHllbmQgPSB5X2NlbnRybyksDQogICAgICAgICAgICAgICAgIGFscGhhID0gMC4zLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NTAiKSArDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfY29tdW5hX21lam9yYWRvcywgbmFtZSA9ICJUaXBvIGRlIENvbXVuYSIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDUsIDIwKSwgbmFtZSA9ICJGdWVyemEgZGVcbkNvcnJlbGFjacOzbiAofHJ8KSIpICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiUmVkIGRlIENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMgKHAgPCAwLjAxLCB8cnwgPiAwLjUpIiwNCiAgICAgIHN1YnRpdGxlID0gIlRhbWHDsW8gZGUgbm9kb3MgcHJvcG9yY2lvbmFsIGEgfHJ8IiwNCiAgICAgIGNhcHRpb24gPSAiTGF5b3V0IGNpcmN1bGFyIHwgRWxhYm9yYWNpw7NuIHByb3BpYTogV2lsbGlhbSBBLiBHdXRpw6lycmV6IFYuIHwgTW9ub2dyYWbDrWEgQUNBIg0KICAgICkgKw0KICAgIHRlbWFfYWNhZGVtaWNvICsNCiAgICB0aGVtZSgNCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iDQogICAgKSArDQogICAgY29vcmRfZXF1YWwoKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDUuIFBBTkVMIERFIFBSVUVCQVMgRVNUQUTDjVNUSUNBUyAoS1JVU0tBTC1XQUxMSVMpDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNyZWFyX3BhbmVsX3BydWViYXNfZXN0YWRpc3RpY2FzIDwtIGZ1bmN0aW9uKGRpdl9jb21iaW5hZGEpIHsNCiAgcHJ1ZWJhcyA8LSBsaXN0KA0KICAgIHNoYW5ub24gPSBrcnVza2FsLnRlc3QoSF9zaGFubm9uIH4gVGlwb19Db211bmEsIGRhdGEgPSBkaXZfY29tYmluYWRhKSwNCiAgICBwaWVsb3UgPSBrcnVza2FsLnRlc3QocGllbG91IH4gVGlwb19Db211bmEsIGRhdGEgPSBkaXZfY29tYmluYWRhKSwNCiAgICBuX3Byb3llY3RvcyA9IGtydXNrYWwudGVzdChuX3Byb3llY3RvcyB+IFRpcG9fQ29tdW5hLCBkYXRhID0gZGl2X2NvbWJpbmFkYSkNCiAgKQ0KICANCiAgcmVzdWx0YWRvc19wcnVlYmFzIDwtIGRhdGEuZnJhbWUoDQogICAgVmFyaWFibGUgPSBjKCJEaXZlcnNpZGFkIChTaGFubm9uKSIsICJFcXVpZGFkIChQaWVsb3UpIiwgIk7CsCBQcm95ZWN0b3MiKSwNCiAgICBIX2VzdGFkaXN0aWNvID0gc2FwcGx5KHBydWViYXMsIGZ1bmN0aW9uKHgpIHgkc3RhdGlzdGljKSwNCiAgICBwX3ZhbG9yID0gc2FwcGx5KHBydWViYXMsIGZ1bmN0aW9uKHgpIHgkcC52YWx1ZSksDQogICAgZ2wgPSBzYXBwbHkocHJ1ZWJhcywgZnVuY3Rpb24oeCkgeCRwYXJhbWV0ZXIpDQogICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgc2lnbmlmaWNhdGl2byA9IHBfdmFsb3IgPCAwLjA1LA0KICAgICAgZXRpcXVldGEgPSBwYXN0ZTAoIkggPSAiLCByb3VuZChIX2VzdGFkaXN0aWNvLCAyKSwgIlxucCA9ICIsIHJvdW5kKHBfdmFsb3IsIDQpKSwNCiAgICAgIGludGVycHJldGFjaW9uID0gaWZlbHNlKHNpZ25pZmljYXRpdm8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRGlmZXJlbmNpYXNcbnNpZ25pZmljYXRpdmFzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaW4gZGlmZXJlbmNpYXNcbnNpZ25pZmljYXRpdmFzIiksDQogICAgICBjb2xvcl9yZXN1bHRhZG8gPSBpZmVsc2Uoc2lnbmlmaWNhdGl2bywgIlNpZ25pZmljYXRpdm8iLCAiTm8gc2lnbmlmaWNhdGl2byIpDQogICAgKQ0KICANCiAgZ2dwbG90KHJlc3VsdGFkb3NfcHJ1ZWJhcywgYWVzKHggPSBWYXJpYWJsZSwgeSA9IEhfZXN0YWRpc3RpY28sIGZpbGwgPSBjb2xvcl9yZXN1bHRhZG8pKSArDQogICAgZ2VvbV9jb2woYWxwaGEgPSAwLjgsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBldGlxdWV0YSksIHZqdXN0ID0gLTAuMiwgc2l6ZSA9IDQsIGZvbnRmYWNlID0gImJvbGQiKSArDQogICAgZ2VvbV90ZXh0KGFlcyh5ID0gSF9lc3RhZGlzdGljby8yLCBsYWJlbCA9IGludGVycHJldGFjaW9uKSwgDQogICAgICAgICAgICAgIHNpemUgPSAzLjUsIGZvbnRmYWNlID0gImJvbGQiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJTaWduaWZpY2F0aXZvIiA9ICIjMWE5ODUwIiwgIk5vIHNpZ25pZmljYXRpdm8iID0gIiNkNzMwMjciKSwNCiAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlJlc3VsdGFkb1xuKM6xID0gMC4wNSkiKSArDQogICAgbGFicygNCiAgICAgIHRpdGxlID0gIlBydWViYXMgS3J1c2thbC1XYWxsaXMgcG9yIFRpcG8gZGUgQ29tdW5hIiwNCiAgICAgIHN1YnRpdGxlID0gIkV2YWx1YWNpw7NuIGRlIGRpZmVyZW5jaWFzIGVudHJlIGdydXBvcyAobm8gcGFyYW3DqXRyaWNvKSIsDQogICAgICB4ID0gIlZhcmlhYmxlIEFuYWxpemFkYSIsDQogICAgICB5ID0gIkVzdGFkw61zdGljbyBIIiwNCiAgICAgIGNhcHRpb24gPSAiSOKCgDogRGlzdHJpYnVjaW9uZXMgaWd1YWxlcyB8IEjigoE6IEFsIG1lbm9zIHVuYSBkaWZlcmVudGUgfCBXaWxsaWFtIEEuIEd1dGnDqXJyZXogVi4iDQogICAgKSArDQogICAgdGVtYV9hY2FkZW1pY28gKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMTUpKSkNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBFSkVDVUNJw5NOIERFTCBBTsOBTElTSVMgKFNPTE8gU0kgTE9TIERBVE9TIEVYSVNURU4pDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCmNhdCgiSU5JQ0lBTkRPIEFOw4FMSVNJUyBHUsOBRklDTyAtIFdJTExJQU0gQS4gR1VUScOJUlJFWiBWLlxuIikNCmNhdCgiTW9ub2dyYWbDrWE6IEFnZW5kYXMgQ29uY3JldGFzIGRlIEFjY2nDs24gLSBFc3RhZG8gTcOpcmlkYSwgVmVuZXp1ZWxhXG4iKQ0KY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KDQppZiAoIWV4aXN0cygiY29ycmVsYWNpb25lc19wb3JfdGlwbyIpIHx8ICFleGlzdHMoImRpdl9jb21iaW5hZGEiKSkgew0KICBzdG9wKCJFcnJvcjogRGViZXMgY2FyZ2FyIHByaW1lcm8gbG9zIG9iamV0b3MgJ2NvcnJlbGFjaW9uZXNfcG9yX3RpcG8nIHkgJ2Rpdl9jb21iaW5hZGEnLiIpDQp9DQoNCiMgR2VuZXJhciB5IG1vc3RyYXIgY2FkYSBncsOhZmljbw0KcHJpbnQoIj09PSAxLiBIRUFUTUFQIERFIENPUlJFTEFDSU9ORVMgPT09IikNCmdyYWZpY29fMSA8LSBjcmVhcl9oZWF0bWFwKGNvcnJlbGFjaW9uZXNfcG9yX3RpcG8pDQpwcmludChncmFmaWNvXzEpDQoNCnByaW50KCI9PT0gMi4gRElBR1JBTUEgREUgRElTUEVSU0nDk04gPT09IikNCmdyYWZpY29fMiA8LSBjcmVhcl9kaXNwZXJzaW9uKGRpdl9jb21iaW5hZGEpDQpwcmludChncmFmaWNvXzIpDQoNCnByaW50KCI9PT0gMy4gQkFSUkFTIENPTiBJTlRFUlZBTE9TIERFIENPTkZJQU5aQSA9PT0iKQ0KZ3JhZmljb18zIDwtIGNyZWFyX2JhcnJhc19jb3JyZWxhY2lvbl9pYyhjb3JyZWxhY2lvbmVzX3Bvcl90aXBvKQ0KaWYgKCFpcy5udWxsKGdyYWZpY29fMykpIHByaW50KGdyYWZpY29fMykNCg0KcHJpbnQoIj09PSA0LiBSRUQgREUgQ09SUkVMQUNJT05FUyA9PT0iKQ0KZ3JhZmljb180IDwtIGNyZWFyX3JlZF9jb3JyZWxhY2lvbmVzKGNvcnJlbGFjaW9uZXNfcG9yX3RpcG8pDQppZiAoIWlzLm51bGwoZ3JhZmljb180KSkgcHJpbnQoZ3JhZmljb180KQ0KDQpwcmludCgiPT09IDUuIFBSVUVCQVMgRVNUQUTDjVNUSUNBUyBLUlVTS0FMLVdBTExJUyA9PT0iKQ0KZ3JhZmljb181IDwtIGNyZWFyX3BhbmVsX3BydWViYXNfZXN0YWRpc3RpY2FzKGRpdl9jb21iaW5hZGEpDQpwcmludChncmFmaWNvXzUpDQoNCmNhdCgiXG7inIUgVG9kb3MgbG9zIGdyw6FmaWNvcyBnZW5lcmFkb3MgZXhpdG9zYW1lbnRlLlxuIikNCmNhdCgiRWxhYm9yYWNpw7NuOiBXaWxsaWFtIEEuIEd1dGnDqXJyZXogVi4gfCBNb25vZ3JhZsOtYSBBQ0EgLSBFc3RhZG8gTcOpcmlkYVxuIikNCg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBFdmFsdWFjacOzbiBkZSBsYXMgaGlww7N0ZXNpcyBwbGFudGVhZGFzIG1vZGVsbyBkZSBjb3JyZWxhY2nDs24gcG9yIHRpcG8gZGUgY29tdW5hDQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgUHJlcGFyYXIgZGF0b3MgcGFyYSBlbCBncsOhZmljbw0KZGF0b3NfaGlwb3Rlc2lzIDwtIGRhdGEuZnJhbWUoDQogIEhpcG90ZXNpcyA9IGMoIkhFMjogUnVyYWwgKEdPQikiLCAiSEU0OiBNaXh0YSAoR09CKSIsICJIRTM6IEVuIENvbnN0cnVjY2nDs24gKEdPQikiLCANCiAgICAgICAgICAgICAgICAiRW4gQ29uc3RydWNjacOzbiAoQ0ZHKSIsICJIRTE6IFJ1cmFsIChDRkcpIiwgIkhFNTogRW4gQ29uc3RydWNjacOzbiAoUmF0aW8gQUNBKSIsDQogICAgICAgICAgICAgICAgIk1peHRhIChDRkcpIiwgIk1peHRhIChSYXRpbyBBQ0EpIiwgIlJ1cmFsIChSYXRpbyBBQ0EpIiwNCiAgICAgICAgICAgICAgICAiVXJiYW5hIChDRkcpIiwgIlVyYmFuYSAoR09CKSIsICJVcmJhbmEgKFJhdGlvIEFDQSkiKSwNCiAgVGlwbyA9IGMoIkNvbmZpcm1hZGEiLCAiQ29uZmlybWFkYSIsICJDb25maXJtYWRhIiwgIkFkaWNpb25hbCIsICJDb25maXJtYWRhIiwgIkNvbmZpcm1hZGEiLA0KICAgICAgICAgICAiQWRpY2lvbmFsIiwgIkFkaWNpb25hbCIsICJBZGljaW9uYWwiLCAiQWRpY2lvbmFsIiwgIkFkaWNpb25hbCIsICJBZGljaW9uYWwiKSwNCiAgUmhvID0gYygxLjAwMCwgMC45OTksIDAuOTEwLCAwLjgyMCwgMC43NDIsIDAuNTQxLCAwLjQ3MSwgMC4zMTQsIDAuMTA1LCBOQSwgTkEsIE5BKSwNCiAgbiA9IGMoMTEsIDIzLCAyMywgMjMsIDExLCAyMywgMjMsIDIzLCAxMSwgNSwgNSwgNSksDQogIFNpZ25pZmljYW5jaWEgPSBjKCIqKioiLCAiKioqIiwgIioqKiIsICIqKioiLCAiKioiLCAiKioiLCAiKiIsICJucyIsICJucyIsICJucyIsICJucyIsICJucyIpDQopDQoNCiMgQ3JlYXIgZXRpcXVldGFzIGNvbWJpbmFkYXMNCmRhdG9zX2hpcG90ZXNpcyRldGlxdWV0YSA8LSB3aXRoKGRhdG9zX2hpcG90ZXNpcywgDQogIGlmZWxzZShpcy5uYShSaG8pLCAiTm8gc2lnbmlmaWNhdGl2YSIsIA0KICAgICAgICAgc3ByaW50Zigiz4E9JS4zZiAobj0lZCkiLCBSaG8sIG4pKSkNCg0KIyBEZWZpbmlyIGNvbG9yZXMgcG9yIG1hZ25pdHVkDQpkYXRvc19oaXBvdGVzaXMkY29sb3IgPC0gd2l0aChkYXRvc19oaXBvdGVzaXMsIA0KICBpZmVsc2UoaXMubmEoUmhvKSwgIiNlMGUwZTAiLA0KICAgICAgICAgaWZlbHNlKFJobyA+PSAwLjgsICIjMWE5ODUwIiwgDQogICAgICAgICAgICAgICAgaWZlbHNlKFJobyA+PSAwLjYsICIjNjZiZDYzIiwgDQogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSaG8gPj0gMC40LCAiI2E2ZDk2YSIsICIjZDllZjhiIikpKSkpDQoNCiMgQ3JlYXIgZWwgZ3LDoWZpY28gbWVqb3JhZG8NCmdyYWZpY29faGlwb3Rlc2lzIDwtIGdncGxvdChkYXRvc19oaXBvdGVzaXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHJlb3JkZXIoSGlwb3Rlc2lzLCBSaG8pLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBSaG8sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGNvbG9yKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuOCwgY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBldGlxdWV0YSksIA0KICAgICAgICAgICAgaGp1c3QgPSAtMC4xLCANCiAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgZ2VvbV9wb2ludChhZXMoeSA9IDAuMSwgc2l6ZSA9IFNpZ25pZmljYW5jaWEpLA0KICAgICAgICAgICAgIHNoYXBlID0gMTYsDQogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArDQogIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArDQogIHNjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IGMoIm5zIiA9IDAsICIqIiA9IDMsICIqKiIgPSA1LCAiKioqIiA9IDcpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuNCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiI2Q3MzAyNyIsIGFscGhhID0gMC43KSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuNiwgbGluZXR5cGUgPSAic29saWQiLCBjb2xvciA9ICIjZDczMDI3IiwgYWxwaGEgPSAwLjcpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJFdmFsdWFjacOzbiBFbXDDrXJpY2EgZGUgSGlww7N0ZXNpcyBkZSBJbnZlc3RpZ2FjacOzbiIsDQogICAgc3VidGl0bGUgPSAiTW9kZWxvIGRlIGNvcnJlbGFjacOzbiBkZSBTcGVhcm1hbiBwb3IgdGlwb2xvZ8OtYSBjb211bmFsIiwNCiAgICB4ID0gIiIsDQogICAgeSA9ICJDb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gKM+BKSIsDQogICAgY2FwdGlvbiA9ICJucyA9IG5vIHNpZ25pZmljYXRpdm8gKHA+MC4wNSk7ICogcDwwLjA1OyAqKiBwPDAuMDE7ICoqKiBwPDAuMDAxIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImdyYXk0MCIpLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJkb3R0ZWQiLCBjb2xvciA9ICJncmF5ODAiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDEsIDEsIDEsIDEsICJjbSIpDQogICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxLjA1KSwgDQogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgMC4yKSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHNwcmludGYoIiUuMWYiLCB4KSkNCg0KIyBNb3N0cmFyIGVsIGdyw6FmaWNvDQpwcmludChncmFmaWNvX2hpcG90ZXNpcykNCg0KIyAgUmVzdW1lbiBlc3RhZMOtc3RpY28gcG9yIHRpcG8gZGUgY29tdW5hDQpyZXN1bWVuX2VzdGFkaXN0aWNvIDwtIGRpdl9jb21iaW5hZGEgJT4lDQogIGdyb3VwX2J5KFRpcG9fQ29tdW5hLCBUaXBvX0FuYWxpc2lzKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG4gPSBuKCksDQogICAgbWVkaWFfc2hhbm5vbiA9IG1lYW4oSF9zaGFubm9uLCBuYS5ybSA9IFRSVUUpLA0KICAgIHNkX3NoYW5ub24gPSBzZChIX3NoYW5ub24sIG5hLnJtID0gVFJVRSksDQogICAgbWVkaWFfcHJveWVjdG9zID0gbWVhbihuX3Byb3llY3RvcywgbmEucm0gPSBUUlVFKSwNCiAgICBzZF9wcm95ZWN0b3MgPSBzZChuX3Byb3llY3RvcywgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyAgTW9zdHJhciByZXN1bWVuIGVzdGFkw61zdGljbw0Ka2FibGUocmVzdW1lbl9lc3RhZGlzdGljbywNCiAgICAgIGNhcHRpb24gPSAiRXN0YWTDrXN0aWNhcyBEZXNjcmlwdGl2YXMgcG9yIFRpcG8gZGUgQ29tdW5hIHkgQW7DoWxpc2lzIiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIlRpcG8gQ29tdW5hIiwgIlRpcG8gQW7DoWxpc2lzIiwgIm4iLCANCiAgICAgICAgICAgICAgICAgICAiTWVkaWEgU2hhbm5vbiIsICJERSBTaGFubm9uIiwgDQogICAgICAgICAgICAgICAgICAgIk1lZGlhIFByb3llY3RvcyIsICJERSBQcm95ZWN0b3MiKSwNCiAgICAgIGRpZ2l0cyA9IDMpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRkFMU0UpDQoNCiMgUHJ1ZWJhcyBLcnVza2FsLVdhbGxpcw0Ka3J1c2thbF90ZXN0X3NoYW5ub24gPC0ga3J1c2thbC50ZXN0KEhfc2hhbm5vbiB+IFRpcG9fQ29tdW5hLCBkYXRhID0gZGl2X2NvbWJpbmFkYSkNCmtydXNrYWxfdGVzdF9wcm95ZWN0b3MgPC0ga3J1c2thbC50ZXN0KG5fcHJveWVjdG9zIH4gVGlwb19Db211bmEsIGRhdGEgPSBkaXZfY29tYmluYWRhKQ0KDQojICBNb3N0cmFyIHJlc3VsdGFkb3MgZGUgcHJ1ZWJhcyBLcnVza2FsLVdhbGxpcw0KY2F0KCJcblJlc3VsdGFkb3MgcHJ1ZWJhIEtydXNrYWwtV2FsbGlzOlxuIikNCmNhdCgiXG5EaXZlcnNpZGFkIFNoYW5ub24gcG9yIFRpcG8gZGUgQ29tdW5hOlxuIikNCnByaW50KGtydXNrYWxfdGVzdF9zaGFubm9uKQ0KY2F0KCJcbk7Dum1lcm8gZGUgUHJveWVjdG9zIHBvciBUaXBvIGRlIENvbXVuYTpcbiIpDQpwcmludChrcnVza2FsX3Rlc3RfcHJveWVjdG9zKQ0KDQojIEludGVycHJldGFjacOzbiBkZSBjb3JyZWxhY2lvbmVzIHNpZ25pZmljYXRpdmFzDQpjb3JyZWxhY2lvbmVzX3NpZ25pZmljYXRpdmFzIDwtIGRhdGEuZnJhbWUoDQogIFRpcG9fQ29tdW5hID0gYygiTWl4dGEiLCAiTWl4dGEiLCAiUnVyYWwiLCAiUnVyYWwiLCAiUnVyYWwiLCAiVXJiYW5hIiwNCiAgICAgICAgICAgICAgICAgICJFbiBjb25zdHJ1Y2Npw7NuIiwgIkVuIGNvbnN0cnVjY2nDs24iKSwNCiAgVGlwb19BbmFsaXNpcyA9IGMoIkNGRyIsICJDRkciLCAiQ0ZHIiwgIkNGRyIsICJDRkciLCAiQ0ZHIiwgDQogICAgICAgICAgICAgICAgICAgICJDRkciLCAiQ0ZHIiksDQogIG4gPSBjKDIzLCAyMywgMTEsIDExLCAxMSwgNSwgMjMsIDIzKSwNCiAgcmhvID0gYygwLjQ3MSwgLTAuNzY1LCAxLjAwMCwgMC43NDIsIDAuNzQyLCAxLjAwMCwgMC44MjAsIDAuNDYxKSwNCiAgaW50ZXJwcmV0YWNpb24gPSBjKA0KICAgICJDb3JyZWxhY2nDs24gbW9kZXJhZGEgcG9zaXRpdmEgZW4gY29tdW5hcyBtaXh0YXMiLA0KICAgICJDb3JyZWxhY2nDs24gZnVlcnRlIG5lZ2F0aXZhIGVuIGNvbXVuYXMgbWl4dGFzIiwNCiAgICAiQ29ycmVsYWNpw7NuIHBlcmZlY3RhIGVuIGNvbXVuYXMgcnVyYWxlcyIsDQogICAgIkNvcnJlbGFjacOzbiBmdWVydGUgcG9zaXRpdmEgZW4gY29tdW5hcyBydXJhbGVzIiwNCiAgICAiQ29ycmVsYWNpw7NuIGZ1ZXJ0ZSBwb3NpdGl2YSBlbiBjb211bmFzIHJ1cmFsZXMiLA0KICAgICJDb3JyZWxhY2nDs24gcGVyZmVjdGEgZW4gY29tdW5hcyB1cmJhbmFzIiwNCiAgICAiQ29ycmVsYWNpw7NuIG11eSBmdWVydGUgZW4gY29tdW5hcyBlbiBjb25zdHJ1Y2Npw7NuIiwNCiAgICAiQ29ycmVsYWNpw7NuIG1vZGVyYWRhIGVuIGNvbXVuYXMgZW4gY29uc3RydWNjacOzbiINCiAgKQ0KKQ0KDQojIE1vc3RyYXIgdGFibGEgZGUgaW50ZXJwcmV0YWNpb25lcw0Ka2FibGUoY29ycmVsYWNpb25lc19zaWduaWZpY2F0aXZhcywNCiAgICAgIGNhcHRpb24gPSAiSW50ZXJwcmV0YWNpw7NuIGRlIENvcnJlbGFjaW9uZXMgU2lnbmlmaWNhdGl2YXMiLA0KICAgICAgY29sLm5hbWVzID0gYygiVGlwbyBDb211bmEiLCAiVGlwbyBBbsOhbGlzaXMiLCAibiIsICLPgSIsICJJbnRlcnByZXRhY2nDs24iKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBBTsOBTElTSVMgREUgQ09SUkVMQUNJw5NOIFBPUiBUSVBPIERFIENPTVVOQSBZIEtSVVNLQUwtV0FMTElTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyAxLiBGdW5jacOzbiBwYXJhIGNyZWFyIG1hdHJpeiBkZSBjb3JyZWxhY2nDs24gcG9yIGdydXBvDQpjcmVhcl9tYXRyaXpfY29ycmVsYWNpb25fZ3J1cG8gPC0gZnVuY3Rpb24oZGF0YSkgew0KICB2YXJzX2NvcnJlbGFjaW9uIDwtIGMoIm5fcHJveWVjdG9zIiwgIkhfc2hhbm5vbiIsICJwaWVsb3UiKQ0KICANCiAgIyBDYWxjdWxhciBjb3JyZWxhY2nDs24NCiAgY29yX21hdHJpeCA8LSBjb3IoZGF0YVssIHZhcnNfY29ycmVsYWNpb25dLCANCiAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAic3BlYXJtYW4iLCANCiAgICAgICAgICAgICAgICAgICB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikNCiAgDQogICMgQ2FsY3VsYXIgcC12YWxvcmVzDQogIHBfbWF0cml4IDwtIG1hdHJpeChOQSwgbnJvdyA9IG5jb2woY29yX21hdHJpeCksIG5jb2wgPSBuY29sKGNvcl9tYXRyaXgpKQ0KICBmb3IoaSBpbiAxOm5jb2woY29yX21hdHJpeCkpIHsNCiAgICBmb3IoaiBpbiAxOm5jb2woY29yX21hdHJpeCkpIHsNCiAgICAgIGlmKGkgIT0gaikgew0KICAgICAgICB0ZXN0IDwtIGNvci50ZXN0KGRhdGFbW3ZhcnNfY29ycmVsYWNpb25baV1dXSwgDQogICAgICAgICAgICAgICAgICAgICAgICBkYXRhW1t2YXJzX2NvcnJlbGFjaW9uW2pdXV0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInNwZWFybWFuIikNCiAgICAgICAgcF9tYXRyaXhbaSxqXSA8LSB0ZXN0JHAudmFsdWUNCiAgICAgIH0NCiAgICB9DQogIH0NCiAgDQogIHJldHVybihsaXN0KGNvciA9IGNvcl9tYXRyaXgsIHAgPSBwX21hdHJpeCkpDQp9DQoNCiMgMi4gQ2FsY3VsYXIgY29ycmVsYWNpb25lcyBwb3IgZ3J1cG8NCnJlc3VsdGFkb3NfcG9yX2dydXBvIDwtIGRpdl9jb21iaW5hZGEgJT4lDQogIGdyb3VwX2J5KFRpcG9fQ29tdW5hLCBUaXBvX0FuYWxpc2lzKSAlPiUNCiAgZ3JvdXBfbW9kaWZ5KH57DQogICAgY29yX3Jlc3VsdCA8LSBjcmVhcl9tYXRyaXpfY29ycmVsYWNpb25fZ3J1cG8oLngpDQogICAgZGF0YS5mcmFtZSgNCiAgICAgIG4gPSBucm93KC54KSwNCiAgICAgIGNvcl9wcm95X3NoYW5ub24gPSBjb3JfcmVzdWx0JGNvclsxLDJdLA0KICAgICAgcF9wcm95X3NoYW5ub24gPSBjb3JfcmVzdWx0JHBbMSwyXSwNCiAgICAgIGNvcl9zaGFubm9uX3BpZWxvdSA9IGNvcl9yZXN1bHQkY29yWzIsM10sDQogICAgICBwX3NoYW5ub25fcGllbG91ID0gY29yX3Jlc3VsdCRwWzIsM10NCiAgICApDQogIH0pICU+JQ0KICB1bmdyb3VwKCkgJT4lDQogIG11dGF0ZSgNCiAgICBzaWdfcHJveV9zaGFubm9uID0gY2FzZV93aGVuKA0KICAgICAgcF9wcm95X3NoYW5ub24gPCAwLjAwMSB+ICIqKioiLA0KICAgICAgcF9wcm95X3NoYW5ub24gPCAwLjAxIH4gIioqIiwNCiAgICAgIHBfcHJveV9zaGFubm9uIDwgMC4wNSB+ICIqIiwNCiAgICAgIFRSVUUgfiAibnMiDQogICAgKSwNCiAgICBzaWdfc2hhbm5vbl9waWVsb3UgPSBjYXNlX3doZW4oDQogICAgICBwX3NoYW5ub25fcGllbG91IDwgMC4wMDEgfiAiKioqIiwNCiAgICAgIHBfc2hhbm5vbl9waWVsb3UgPCAwLjAxIH4gIioqIiwNCiAgICAgIHBfc2hhbm5vbl9waWVsb3UgPCAwLjA1IH4gIioiLA0KICAgICAgVFJVRSB+ICJucyINCiAgICApDQogICkNCg0KIyAzLiBUYWJsYSBkZSBjb3JyZWxhY2lvbmVzIHBvciBncnVwbw0KdGFibGFfY29ycmVsYWNpb25lcyA8LSBrYWJsZShyZXN1bHRhZG9zX3Bvcl9ncnVwbywNCiAgY2FwdGlvbiA9ICJDb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIHBvciBUaXBvIGRlIENvbXVuYSB5IEFuw6FsaXNpcyIsDQogIGNvbC5uYW1lcyA9IGMoIlRpcG8gQ29tdW5hIiwgIlRpcG8gQW7DoWxpc2lzIiwgIm4iLCANCiAgICAgICAgICAgICAgICAiz4EgKFByb3ktU2hhbm5vbikiLCAicC12YWxvciIsICJTaWcuIiwNCiAgICAgICAgICAgICAgICAiz4EgKFNoYW5ub24tUGllbG91KSIsICJwLXZhbG9yIiwgIlNpZy4iKSwNCiAgZGlnaXRzID0gMykgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpICU+JQ0KICBjb2x1bW5fc3BlYygxOjIsIGJvbGQgPSBUUlVFKSAlPiUNCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDMsIA0KICAgICAgICAgICAgICAgICAgICAiUHJveWVjdG9zIHZzIFNoYW5ub24iID0gMywNCiAgICAgICAgICAgICAgICAgICAgIlNoYW5ub24gdnMgUGllbG91IiA9IDMpKQ0KDQoNCg0KIyA0LiBQcnVlYmFzIEtydXNrYWwtV2FsbGlzDQprcnVza2FsX3Rlc3RzIDwtIGxpc3QoDQogIFNoYW5ub24gPSBrcnVza2FsLnRlc3QoSF9zaGFubm9uIH4gVGlwb19Db211bmEsIGRhdGEgPSBkaXZfY29tYmluYWRhKSwNCiAgUGllbG91ID0ga3J1c2thbC50ZXN0KHBpZWxvdSB+IFRpcG9fQ29tdW5hLCBkYXRhID0gZGl2X2NvbWJpbmFkYSksDQogIFByb3llY3RvcyA9IGtydXNrYWwudGVzdChuX3Byb3llY3RvcyB+IFRpcG9fQ29tdW5hLCBkYXRhID0gZGl2X2NvbWJpbmFkYSkNCikNCg0KIyA1LiBUYWJsYSBkZSByZXN1bHRhZG9zIEtydXNrYWwtV2FsbGlzDQp0YWJsYV9rcnVza2FsIDwtIGRhdGEuZnJhbWUoDQogIFZhcmlhYmxlID0gYygiw41uZGljZSBTaGFubm9uIChIJykiLCAiw41uZGljZSBQaWVsb3UgKEonKSIsICJOwrAgUHJveWVjdG9zIiksDQogIEVzdGFkaXN0aWNvID0gc2FwcGx5KGtydXNrYWxfdGVzdHMsIGZ1bmN0aW9uKHgpIHJvdW5kKHgkc3RhdGlzdGljLCAzKSksDQogIFBfdmFsb3IgPSBzYXBwbHkoa3J1c2thbF90ZXN0cywgZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLCA0KSksDQogIEludGVycHJldGFjaW9uID0gc2FwcGx5KGtydXNrYWxfdGVzdHMsIGZ1bmN0aW9uKHgpIA0KICAgIGlmZWxzZSh4JHAudmFsdWUgPCAwLjA1LCANCiAgICAgICAgICAgIkhheSBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyIsIA0KICAgICAgICAgICAiTm8gaGF5IGRpZmVyZW5jaWFzIHNpZ25pZmljYXRpdmFzIikpDQopDQoNCmthYmxlKHRhYmxhX2tydXNrYWwsDQogICAgICBjYXB0aW9uID0gIlJlc3VsdGFkb3MgZGUgUHJ1ZWJhcyBLcnVza2FsLVdhbGxpcyBwb3IgVGlwbyBkZSBDb211bmEiLA0KICAgICAgY29sLm5hbWVzID0gYygiVmFyaWFibGUiLCAiRXN0YWTDrXN0aWNvIEgiLCAicC12YWxvciIsICJJbnRlcnByZXRhY2nDs24iKSwNCiAgICAgIGFsaWduID0gImMiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpICU+JQ0KICByb3dfc3BlYyh3aGljaCh0YWJsYV9rcnVza2FsJFBfdmFsb3IgPCAwLjA1KSwgDQogICAgICAgICAgIGJvbGQgPSBUUlVFLCANCiAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLCANCiAgICAgICAgICAgYmFja2dyb3VuZCA9ICIjMWI5ZTc3IikNCg0KIyA2LiBSZXN1bWVuIGVzdGFkw61zdGljbyBwb3IgdGlwbyBkZSBjb211bmENCnJlc3VtZW5fZXN0YWRpc3RpY28gPC0gZGl2X2NvbWJpbmFkYSAlPiUNCiAgZ3JvdXBfYnkoVGlwb19Db211bmEpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbiA9IG4oKSwNCiAgICBtZWRpYV9zaGFubm9uID0gbWVhbihIX3NoYW5ub24sIG5hLnJtID0gVFJVRSksDQogICAgZGVfc2hhbm5vbiA9IHNkKEhfc2hhbm5vbiwgbmEucm0gPSBUUlVFKSwNCiAgICBtZWRpYV9waWVsb3UgPSBtZWFuKHBpZWxvdSwgbmEucm0gPSBUUlVFKSwNCiAgICBkZV9waWVsb3UgPSBzZChwaWVsb3UsIG5hLnJtID0gVFJVRSksDQogICAgbWVkaWFfcHJveWVjdG9zID0gbWVhbihuX3Byb3llY3RvcywgbmEucm0gPSBUUlVFKSwNCiAgICBkZV9wcm95ZWN0b3MgPSBzZChuX3Byb3llY3RvcywgbmEucm0gPSBUUlVFKQ0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MobWVkaWFfc2hhbm5vbikpDQoNCmthYmxlKHJlc3VtZW5fZXN0YWRpc3RpY28sDQogICAgICBjYXB0aW9uID0gIkVzdGFkw61zdGljYXMgRGVzY3JpcHRpdmFzIHBvciBUaXBvIGRlIENvbXVuYSIsDQogICAgICBjb2wubmFtZXMgPSBjKCJUaXBvIENvbXVuYSIsICJuIiwgDQogICAgICAgICAgICAgICAgICAgICJNZWRpYSBIJyIsICJERSBIJyIsDQogICAgICAgICAgICAgICAgICAgICJNZWRpYSBKJyIsICJERSBKJyIsDQogICAgICAgICAgICAgICAgICAgICJNZWRpYSBQcm95ZWN0b3MiLCAiREUgUHJveWVjdG9zIiksDQogICAgICBkaWdpdHMgPSAzKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkNCg0KDQojIDUuIFJlcG9ydGUgZGUgY29ycmVsYWNpb25lcyB5IHBydWViYXMNCnByaW50KCI9PT09IEVzdGFkw61zdGljYXMgZGVzY3JpcHRpdmFzIHBvciB0aXBvIGRlIGNvbXVuYSA9PT09IikNCnByaW50KHRpcG9fY29tdW5hX3N0YXRzKQ0KDQpwcmludCgiPT09PSBDb3JyZWxhY2lvbmVzIGRlIFNwZWFybWFuIHBvciB0aXBvIGRlIGNvbXVuYSA9PT09IikNCnByaW50KGNvcnJlbGFjaW9uZXNfcG9yX3RpcG8pDQoNCnByaW50KCI9PT09IFBydWViYXMgS3J1c2thbC1XYWxsaXMgPT09PSIpDQpwcmludCgiU2hhbm5vbiBIIH4gVGlwb19Db211bmEiKQ0KcHJpbnQoa3J1c2thbF9zaGFubm9uKQ0KcHJpbnQoIlBpZWxvdSBKIH4gVGlwb19Db211bmEiKQ0KcHJpbnQoa3J1c2thbF9waWVsb3UpDQpwcmludCgiTsKwIFByb3llY3RvcyB+IFRpcG9fQ29tdW5hIikNCnByaW50KGtydXNrYWxfbnByb3kpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBJTlRFUlBSRVRBQ0nDk04gREUgQ09SUkVMQUNJT05FUyBTUEVBUk1BTiBZIFBSVUVCQVMgUE9SIFRJUE8gREUgQ09NVU5BDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KDQojIDEuIFRhYmxhIGRlIGNvcnJlbGFjaW9uZXMgcHJpbmNpcGFsZXMgcG9yIHRpcG8gZGUgY29tdW5hDQpjb3JyZWxhY2lvbmVzX2ludGVycHJldGFjaW9uIDwtIHRyaWJibGUoDQogIH5IYWxsYXpnbywNCiAgfkludGVycHJldGFjacOzbiwNCiAgfkltcGxpY2FjaW9uZXMsDQogIA0KICAjIENGRyAtIEVuIGNvbnN0cnVjY2nDs24NCiAgIkNvcnJlbGFjacOzbiBmdWVydGUgcG9zaXRpdmEgZW50cmUgbl9wcm95ZWN0b3MgeSBkaXZlcnNpZGFkIChTaGFubm9uKSBlbiBjb211bmFzICdFbiBjb25zdHJ1Y2Npw7NuJyAoQ0ZHKSwgz4E9MC44MiwgcDwwLjAwMSIsDQogICJBIG1heW9yIG7Dum1lcm8gZGUgcHJveWVjdG9zLCBtYXlvciBkaXZlcnNpZGFkIGVuIGNvbXVuYXMgZW4gY29uc3RydWNjacOzbiwgaW5kaWNhbmRvIHF1ZSBsYSB2YXJpZWRhZCBjcmVjZSBjb24gbGEgY2FudGlkYWQuIiwNCiAgIkZvY2FsaXphciBlbCBhdW1lbnRvIGRlIHByb3llY3RvcyBwdWVkZSBpbmNyZW1lbnRhciBsYSBkaXZlcnNpZGFkIGVuIGNvbXVuYXMgZGUgZXN0ZSB0aXBvLiIsDQogIA0KICAjIEdvYmVybmFjacOzbiAtIEVuIGNvbnN0cnVjY2nDs24NCiAgIkNvcnJlbGFjacOzbiBtdXkgZnVlcnRlIHBvc2l0aXZhIGVudHJlIG5fcHJveWVjdG9zIHkgZGl2ZXJzaWRhZCAoU2hhbm5vbikgZW4gY29tdW5hcyAnRW4gY29uc3RydWNjacOzbicgKEdvYmVybmFjacOzbiksIM+BPTAuOTEsIHA8MC4wMDEiLA0KICAiRWwgw6l4aXRvIGVuIGRpdmVyc2lkYWQgZGVwZW5kZSBmdWVydGVtZW50ZSBkZWwgbsO6bWVybyBkZSBwcm95ZWN0b3MgZ2VzdGlvbmFkb3MgcG9yIGdvYmVybmFjacOzbi4iLA0KICAiTGEgZ29iZXJuYWNpw7NuIGRlYmUgcHJpb3JpemFyIGVsIGRlc2Fycm9sbG8gZGUgbcO6bHRpcGxlcyBwcm95ZWN0b3MgcGFyYSBtYXhpbWl6YXIgbGEgZGl2ZXJzaWRhZC4iLA0KICANCiAgIyBSYXRpbyAtIEVuIGNvbnN0cnVjY2nDs24NCiAgIkNvcnJlbGFjacOzbiBtb2RlcmFkYSBwb3NpdGl2YSBlbnRyZSBuX3Byb3llY3RvcyB5IGRpdmVyc2lkYWQgKFNoYW5ub24pIGVuIGNvbXVuYXMgJ0VuIGNvbnN0cnVjY2nDs24nIChSYXRpbyksIM+BPTAuNTQsIHA9MC4wMDciLA0KICAiRWwgcmF0aW8gZGUgcHJveWVjdG9zIGN1bG1pbmFkb3Mgc2UgYXNvY2lhIGNvbiBtYXlvciBkaXZlcnNpZGFkLCBhdW5xdWUgZWwgZWZlY3RvIGVzIG1vZGVyYWRvLiIsDQogICJNb25pdG9yZWFyIGVsIHJhdGlvIGRlIGN1bG1pbmFjacOzbiBwdWVkZSBheXVkYXIgYSBpZGVudGlmaWNhciBjb211bmFzIGNvbiBwb3RlbmNpYWwgZGUgZGl2ZXJzaWRhZC4iLA0KICANCiAgIyBHb2Jlcm5hY2nDs24gLSBNaXh0YQ0KICAiQ29ycmVsYWNpw7NuIG11eSBmdWVydGUgcG9zaXRpdmEgbl9wcm95ZWN0b3MtZGl2ZXJzaWRhZCBlbiBjb211bmFzIG1peHRhcyAoR29iZXJuYWNpw7NuKSwgz4E9MC45OSwgcDwwLjAwMSIsDQogICJFbiBjb211bmFzIG1peHRhcywgZWwgbsO6bWVybyBkZSBwcm95ZWN0b3MgZXN0w6EgY2FzaSBwZXJmZWN0YW1lbnRlIGFzb2NpYWRvIGNvbiBsYSBkaXZlcnNpZGFkLiIsDQogICJMYSBwbGFuaWZpY2FjacOzbiBjb211bmFsIG1peHRhIHB1ZWRlIGJlbmVmaWNpYXJzZSBkZSBpbXB1bHNhciBsYSBjYW50aWRhZCBkZSBwcm95ZWN0b3MuIiwNCiAgDQogICMgQ0ZHIC0gUnVyYWwNCiAgIkNvcnJlbGFjacOzbiBtdXkgZnVlcnRlIHBvc2l0aXZhIGVudHJlIG5fcHJveWVjdG9zIHkgZGl2ZXJzaWRhZCAoU2hhbm5vbikgZW4gY29tdW5hcyBydXJhbGVzIChDRkcpLCDPgT0wLjkyLCBwPDAuMDAxIiwNCiAgIkVuIGNvbXVuYXMgcnVyYWxlcywgbGEgY2FudGlkYWQgZGUgcHJveWVjdG9zIGVzIGVsIHByaW5jaXBhbCBtb3RvciBkZSBkaXZlcnNpZGFkLiIsDQogICJJbXB1bHNhciBwcm95ZWN0b3MgcnVyYWxlcyBwdWVkZSBzZXIgY2xhdmUgcGFyYSBlbnJpcXVlY2VyIGxhIHZhcmllZGFkIGRlIGluaWNpYXRpdmFzLiIsDQogIA0KICAjIEdvYmVybmFjacOzbiAtIFJ1cmFsDQogICJDb3JyZWxhY2nDs24gcGVyZmVjdGEgcG9zaXRpdmEgbl9wcm95ZWN0b3MtZGl2ZXJzaWRhZCB5IHBlcmZlY3RhIG5lZ2F0aXZhIGRpdmVyc2lkYWQtZXF1aWRhZCBlbiBjb211bmFzIHJ1cmFsZXMgKEdvYmVybmFjacOzbiksIM+BPTEuMDAvLTEuMDAsIHDiiYgwIiwNCiAgIkVsIG7Dum1lcm8gZGUgcHJveWVjdG9zIGV4cGxpY2EgdG90YWxtZW50ZSBsYSBkaXZlcnNpZGFkLCBwZXJvIG1heW9yIGRpdmVyc2lkYWQgcmVkdWNlIGxhIGVxdWlkYWQuIiwNCiAgIlNlIHJlY29taWVuZGEgY29udHJvbGFyIGVsIGJhbGFuY2UgZW50cmUgZGl2ZXJzaWRhZCB5IGVxdWlkYWQgZW4gcHJveWVjdG9zIHJ1cmFsZXMuIiwNCiAgDQogICMgUmF0aW8gLSBSdXJhbA0KICAiQ29ycmVsYWNpw7NuIG1vZGVyYWRhIHBvc2l0aXZhIGVudHJlIG5fcHJveWVjdG9zIHkgZGl2ZXJzaWRhZCBlbiBjb211bmFzIHJ1cmFsZXMgKFJhdGlvKSwgz4E9MC41NSwgcD0wLjAyNiIsDQogICJFbCDDqXhpdG8gZGUgY3VsbWluYWNpw7NuIGRlIHByb3llY3RvcyBpbmNyZW1lbnRhIG1vZGVyYWRhbWVudGUgbGEgZGl2ZXJzaWRhZCBlbiBjb211bmFzIHJ1cmFsZXMuIiwNCiAgIk9wdGltaXphciBsYSBlamVjdWNpw7NuIGVuIHpvbmFzIHJ1cmFsZXMgcHVlZGUgbWVqb3JhciBsYSBkaXZlcnNpZGFkLiIsDQogIA0KICAjIENGRyAtIE1peHRhDQogICJDb3JyZWxhY2nDs24gbW9kZXJhZGEgcG9zaXRpdmEgbl9wcm95ZWN0b3MtZGl2ZXJzaWRhZCBlbiBjb211bmFzIG1peHRhcyAoQ0ZHKSwgz4E9MC41MywgcD0wLjAwMTciLA0KICAiTGEgcmVsYWNpw7NuIGVzIG1lbm9zIGZ1ZXJ0ZSBxdWUgZW4gcnVyYWxlcyB5IHVyYmFuYXMsIHBlcm8gYcO6biByZWxldmFudGUuIiwNCiAgIkxhIGdlc3Rpw7NuIGRlIHByb3llY3RvcyBtaXh0b3MgZGViZSBjb25zaWRlcmFyIGVzdHJhdGVnaWFzIGRlIGRpdmVyc2lkYWQuIiwNCiAgDQogICMgUmF0aW8gLSBNaXh0YQ0KICAiQ29ycmVsYWNpw7NuIGZ1ZXJ0ZSBwb3NpdGl2YSBlbnRyZSByYXRpbyB5IGRpdmVyc2lkYWQgZW4gY29tdW5hcyBtaXh0YXMgKFJhdGlvKSwgz4E9MC42MiwgcDwwLjAwMSIsDQogICJMYSBjdWxtaW5hY2nDs24gZGUgcHJveWVjdG9zIHRpZW5lIHVuIGltcGFjdG8gaW1wb3J0YW50ZSBlbiBsYSBkaXZlcnNpZGFkIGNvbXVuYWwuIiwNCiAgIk1vbml0b3JlYXIgZWwgcmF0aW8gZGUgY3VsbWluYWNpw7NuIGVzIMO6dGlsIHBhcmEgcHJldmVyIGRpdmVyc2lkYWQgZW4gbWl4dGFzLiINCikNCg0KIyAyLiBNb3N0cmFyIHRhYmxhIGNvbiBsZXllbmRhIGUgaW1wbGljYWNpb25lcw0Ka2FibGUoY29ycmVsYWNpb25lc19pbnRlcnByZXRhY2lvbiwgY2FwdGlvbiA9ICJJbnRlcnByZXRhY2nDs24gZGUgQ29ycmVsYWNpb25lcyBTaWduaWZpY2F0aXZhcyBwb3IgVGlwbyBkZSBDb211bmEiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQ0KDQojIDMuIEludGVycHJldGFjacOzbiBkZSBsYXMgcHJ1ZWJhcyBLcnVza2FsLVdhbGxpcw0KY2F0KCJcblxuKipJbnRlcnByZXRhY2nDs24gS3J1c2thbC1XYWxsaXM6KipcbiIpDQpjYXQoIi0gUGFyYSBTaGFubm9uIEgsIGVsIHAtdmFsb3IgPSAwLjAwMjgsIGxvIHF1ZSBpbmRpY2EgZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXMgZGUgZGl2ZXJzaWRhZCBlbnRyZSB0aXBvcyBkZSBjb211bmEuXG4iKQ0KY2F0KCItIFBhcmEgUGllbG91IEosIGVsIHAtdmFsb3IgPSAwLjg3LCBOTyBoYXkgZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXMgZW4gZXF1aWRhZCBlbnRyZSB0aXBvcyBkZSBjb211bmEuXG4iKQ0KY2F0KCItIFBhcmEgbsO6bWVybyBkZSBwcm95ZWN0b3MsIGVsIHAtdmFsb3IgPSAwLjAwMTQsIHNlIGNvbmZpcm1hbiBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyBlbnRyZSB0aXBvcyBkZSBjb211bmEuXG4iKQ0KDQpjYXQoIlxuKipJbXBsaWNhY2lvbmVzIGdlbmVyYWxlczoqKlxuIikNCmNhdCgiLSBMYSBkaXZlcnNpZGFkIHkgbGEgY2FudGlkYWQgZGUgcHJveWVjdG9zIHZhcsOtYW4gc2Vnw7puIGVsIHRpcG8gZGUgY29tdW5hLCBsbyBxdWUgZGViZSBzZXIgY29uc2lkZXJhZG8gZW4gbGEgcGxhbmlmaWNhY2nDs24gdGVycml0b3JpYWwuXG4iKQ0KY2F0KCItIExhIGVxdWlkYWQgZGUgbGEgZGlzdHJpYnVjacOzbiAoUGllbG91KSBubyB2YXLDrWEgc2lnbmlmaWNhdGl2YW1lbnRlIGVudHJlIGNvbXVuYXMsIHN1Z2lyaWVuZG8gcXVlIGxhIGRpdmVyc2lkYWQgZGVwZW5kZSBtw6FzIGRlIGxhIGNhbnRpZGFkIGRlIHByb3llY3RvcyBxdWUgZGUgc3UgZGlzdHJpYnVjacOzbi5cbiIpDQpjYXQoIi0gTGFzIGNvcnJlbGFjaW9uZXMgbcOhcyBmdWVydGVzIHN1Z2llcmVuIHByaW9yaXphciBlbCBhdW1lbnRvIHkgY3VsbWluYWNpw7NuIGRlIHByb3llY3RvcyBwYXJhIGluY3JlbWVudGFyIGxhIGRpdmVyc2lkYWQsIGVzcGVjaWFsbWVudGUgZW4gY29udGV4dG9zIHJ1cmFsZXMgeSBtaXh0b3MuXG4iKQ0KYGBgDQoNCiMjKipUYWJsYSBkZSBIaXDDs3Rlc2lzIGRlbCBNb2RlbG8gcG9yIFRpcG8gZGUgQ29tdW5hKioNCg0KICBFbCBhbsOhbGlzaXMgY29ycmVsYWNpb25hbCBhZ3JlZ2FkbyBwcmVzZW50YWRvIGVuIGxhIHNlY2Npw7NuIGFudGVyaW9yIHByb3BvcmNpb25hIHVuYSB2aXNpw7NuIHBhbm9yw6FtaWNhIGRlbCBzaXN0ZW1hIGRlIEFDQSwgcGVybyBlbm1hc2NhcmEgcG90ZW5jaWFsbWVudGUgcGF0cm9uZXMgZXNwZWPDrWZpY29zIHF1ZSBlbWVyZ2VuIGVuIGNvbnRleHRvcyB0ZXJyaXRvcmlhbGVzIGRpZmVyZW5jaWFkb3MuIExhcyBjb211bmFzIGRlbCBFc3RhZG8gTcOpcmlkYSBwcmVzZW50YW4gcmVhbGlkYWRlcyBzb2Npb2Vjb27Ds21pY2FzLCBnZW9ncsOhZmljYXMgeSBvcmdhbml6YXRpdmFzIGFsdGFtZW50ZSBoZXRlcm9nw6luZWFzIHF1ZSBpbmZsdXllbiBkaXJlY3RhbWVudGUgZW4gc3UgY2FwYWNpZGFkIHBhcmEgaWRlbnRpZmljYXIsIHByaW9yaXphciB5IHJlc29sdmVyIG51ZG9zIGNyw610aWNvcy4NCg0KICBFc3RhIHNlY2Npw7NuIGV4dGllbmRlIGVsIGFuw6FsaXNpcyBhbnRlcmlvciBtZWRpYW50ZSBsYSBzZWdtZW50YWNpw7NuIGRlIGxhIG11ZXN0cmEgZW4gc3ViZ3J1cG9zIGhvbW9nw6luZW9zIHBvciB0aXBvbG9nw61hIGNvbXVuYWw6IFVyYmFuYSwgUnVyYWwsIE1peHRhIHkgRW4gY29uc3RydWNjacOzbi4gRXN0YSBzZWdtZW50YWNpw7NuIG5vIGVzIGFyYml0cmFyaWEsIHNpbm8gcXVlIHJlc3BvbmRlIGEgZGlmZXJlbmNpYXMgZXN0cnVjdHVyYWxlcyBlbiBkZW5zaWRhZCBwb2JsYWNpb25hbCwgYWNjZXNvIGEgc2VydmljaW9zLCBtYWR1cmV6IGluc3RpdHVjaW9uYWwgeSBjYXBhY2lkYWQgb3JnYW5pemF0aXZhLiBBbCBhcGxpY2FyIGVsIGNvZWZpY2llbnRlIGRlIFNwZWFybWFuIGEgY2FkYSBzdWJncnVwbyBpbmRlcGVuZGllbnRlbWVudGUsIHBvZGVtb3MgaWRlbnRpZmljYXIgc2kgbG9zIG1lY2FuaXNtb3MgZGUgcGxhbmlmaWNhY2nDs24geSBlamVjdWNpw7NuIG9wZXJhbiBkZSBtYW5lcmEgdW5pZm9ybWUgbyBzaSwgcG9yIGVsIGNvbnRyYXJpbywgY2FkYSBjb250ZXh0byB0ZXJyaXRvcmlhbCBnZW5lcmEgZGluw6FtaWNhcyBjb3JyZWxhY2lvbmFsZXMgZXNwZWPDrWZpY2FzLg0KDQoNCmBgYHtyfQ0KaGlwb3Rlc2lzX3RpcG9fY29tdW5hIDwtIGRhdGEuZnJhbWUoDQogIEhpcMOzdGVzaXMgPSBjKA0KICAgICIqKkhpcMOzdGVzaXMgR2VuZXJhbCAoSEcpKioiLA0KICAgICJFeGlzdGUgdW5hIHJlbGFjacOzbiBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhIGVudHJlIGxvcyB0aXBvcyBkZSBjb211bmEgeSBsb3MgcGF0cm9uZXMgY29ycmVsYWNpb25hbGVzIGVudHJlIHZhcmlhYmxlcyBkZSBwbGFuaWZpY2FjacOzbiB5IGVqZWN1Y2nDs24sIGNvbiBwYXRyb25lcyBlc3BlY8OtZmljb3MgcXVlIHJlZmxlamFuIGxhcyBjYXBhY2lkYWRlcyBvcmdhbml6YXRpdmFzIHkgZGVzYWbDrW9zIGNvbnRleHR1YWxlcyBkZSBjYWRhIHRpcG9sb2fDrWEuIiwNCiAgICAiIiwNCiAgICAiKipIRTE6KiogRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEgZnVlcnRlICgwLjYwIOKJpCDPgSA8IDAuODApIGVudHJlIGVsIG7Dum1lcm8gZGUgcHJveWVjdG9zIHkgbGEgZGl2ZXJzaWRhZCBkZSBudWRvcyBjcsOtdGljb3MgKENGRykgZW4gY29tdW5hcyBydXJhbGVzLiIsDQogICAgIioqSEUyOioqIEV4aXN0ZSB1bmEgY29ycmVsYWNpw7NuIHBvc2l0aXZhIHBlcmZlY3RhICjPgSA9IDEuMDApIGVudHJlIG7Dum1lcm8gZGUgcHJveWVjdG9zIHkgZGl2ZXJzaWRhZCBpbnN0aXR1Y2lvbmFsIChHT0IpIGVuIGNvbXVuYXMgcnVyYWxlcywganVudG8gY29uIGNvcnJlbGFjacOzbiBuZWdhdGl2YSBwZXJmZWN0YSAoz4EgPSAtMS4wMCkgZW50cmUgZGl2ZXJzaWRhZCBpbnN0aXR1Y2lvbmFsIHkgZXF1aWRhZCAoUGllbG91KS4iLA0KICAgICIqKkhFMzoqKiBFeGlzdGUgdW5hIGNvcnJlbGFjacOzbiBwb3NpdGl2YSBtdXkgZnVlcnRlICjPgSDiiaUgMC45MCkgZW50cmUgbsO6bWVybyBkZSBwcm95ZWN0b3MgeSBkaXZlcnNpZGFkIGluc3RpdHVjaW9uYWwgKEdPQikgZW4gY29tdW5hcyBlbiBjb25zdHJ1Y2Npw7NuLiIsDQogICAgIioqSEU0OioqIEV4aXN0ZSB1bmEgY29ycmVsYWNpw7NuIHBvc2l0aXZhIHBlcmZlY3RhICjPgSDiiYggMS4wMCkgZW50cmUgbsO6bWVybyBkZSBwcm95ZWN0b3MgeSBkaXZlcnNpZGFkIGluc3RpdHVjaW9uYWwgKEdPQikgZW4gY29tdW5hcyBtaXh0YXMuIiwNCiAgICAiKipIRTU6KiogRXhpc3RlIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEgbW9kZXJhZGEgKDAuNDAg4omkIM+BIDwgMC42MCkgZW50cmUgUmF0aW8gQUNBIHkgbsO6bWVybyBkZSBwcm95ZWN0b3MgZW4gY29tdW5hcyBlbiBjb25zdHJ1Y2Npw7NuLiINCiAgKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCmthYmxlKGhpcG90ZXNpc190aXBvX2NvbXVuYSwgDQogICAgICBjb2wubmFtZXMgPSBOVUxMLA0KICAgICAgY2FwdGlvbiA9ICJIaXDDs3Rlc2lzIGRlIEludmVzdGlnYWNpw7NuIHNvYnJlIENvcnJlbGFjacOzbiBwb3IgVGlwb2xvZ8OtYSBDb211bmFsIiwNCiAgICAgIGZvcm1hdCA9ICJodG1sIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgd2lkdGggPSAiMTAwJSIpDQpgYGANCg0KIyMqKkhlYXRtYXAgQ29tcGFyYXRpdm8gcG9yIFRpcG8gZGUgQ29tdW5hKioNCg0KICBFbCBoZWF0bWFwIGNvbXBhcmF0aXZvIHJldmVsYSB1bmEgaGV0ZXJvZ2VuZWlkYWQgZnVuY2lvbmFsIHByb2Z1bmRhIHF1ZSBqdXN0aWZpY2EgcGxlbmFtZW50ZSBsYSBzZWdtZW50YWNpw7NuIHRlcnJpdG9yaWFsIGRlbCBhbsOhbGlzaXMuIExhcyBjb211bmFzIHJ1cmFsZXMgeSBtaXh0YXMgbXVlc3RyYW4gY2VsZGFzIGRlIGNvbG9yIGF6dWwgaW50ZW5zbywgaW5kaWNhbmRvIGNvcnJlbGFjaW9uZXMgcGVyZmVjdGFzIG8gY2FzaSBwZXJmZWN0YXMgZW50cmUgZWwgbsO6bWVybyBkZSBwcm95ZWN0b3MgeSBsYSBkaXZlcnNpZGFkIGluc3RpdHVjaW9uYWwuIEVzdGUgcGF0csOzbiBldmlkZW5jaWEgcXVlLCBlbiBlc3RvcyBjb250ZXh0b3MsIGV4aXN0ZSB1biBtZWNhbmlzbW8gZGUgZXNjYWxhbWllbnRvIGluc3RpdHVjaW9uYWwgYWx0YW1lbnRlIGVzdGFuZGFyaXphZG86IGNhZGEgcHJveWVjdG8gYWRpY2lvbmFsIHJlcXVpZXJlIHkgZ2VuZXJhIGxhIGluY29ycG9yYWNpw7NuIGRlIG51ZXZvcyBhY3RvcmVzIGd1YmVybmFtZW50YWxlcyBkZSBtYW5lcmEgcHJlZGVjaWJsZSB5IHNpc3RlbcOhdGljYS4NCg0KICBMYXMgY29tdW5hcyBlbiBjb25zdHJ1Y2Npw7NuIHByZXNlbnRhbiBjZWxkYXMgZGUgY29sb3IgYXp1bCBtb2RlcmFkbywgY29uIGNvcnJlbGFjaW9uZXMgbXV5IGZ1ZXJ0ZXMgcGVybyBubyBwZXJmZWN0YXMsIHN1Z2lyaWVuZG8gcXVlIGVzdMOhbiBlbiBwcm9jZXNvIGRlIGNvbnNvbGlkYWNpw7NuIGRlIGVzdG9zIG1lY2FuaXNtb3MgaW5zdGl0dWNpb25hbGVzLiBGaW5hbG1lbnRlLCBsYXMgY29tdW5hcyB1cmJhbmFzIG11ZXN0cmFuIGNlbGRhcyBibGFuY2FzIG8gdmFsb3JlcyBOQSwgaW5kaWNhbmRvIGF1c2VuY2lhIHRvdGFsIGRlIGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMuIEVzdGEgZGVzY29uZXhpw7NuIHVyYmFuYSBubyBlcyB1biBlcnJvciBlc3RhZMOtc3RpY28gc2lubyB1biBoYWxsYXpnbyBzdXN0YW50aXZvIHF1ZSByZXZlbGEgcHJvYmxlbWFzIGVzdHJ1Y3R1cmFsZXMgZW4gbGEgYXJ0aWN1bGFjacOzbiBlbnRyZSBwbGFuaWZpY2FjacOzbiB5IGVqZWN1Y2nDs24gZW4gY29udGV4dG9zIGRlIG1heW9yIGNvbXBsZWppZGFkIGluc3RpdHVjaW9uYWwuDQoNCg0KYGBge3J9DQoNCiMgUHJlcGFyYXIgZGF0b3MgcGFyYSB2aXN1YWxpemFjacOzbg0KaGVhdG1hcF90aXBvX2RhdGEgPC0gY29ycmVsYWNpb25lc19wb3JfdGlwbyAlPiUNCiAgbXV0YXRlKA0KICAgIEV0aXF1ZXRhID0gcGFzdGUwKFRpcG9fQ29tdW5hLCAiIC0gIiwgVGlwb19BbmFsaXNpcyksDQogICAgVGV4dG9fSG92ZXIgPSBwYXN0ZTAoDQogICAgICAiVGlwbyBDb211bmE6ICIsIFRpcG9fQ29tdW5hLCAiPGJyPiIsDQogICAgICAiQW7DoWxpc2lzOiAiLCBUaXBvX0FuYWxpc2lzLCAiPGJyPiIsDQogICAgICAiz4EgKFByb3llY3Rvcy1TaGFubm9uKTogIiwgcm91bmQoY29yX25fcHJveV9ILCAzKSwgIjxicj4iLA0KICAgICAgInAtdmFsb3I6ICIsIGZvcm1hdC5wdmFsKHBfbl9wcm95X0gsIGRpZ2l0cyA9IDMpLCAiPGJyPiIsDQogICAgICAibiA9ICIsIG4sICIgY29tdW5hcyINCiAgICApLA0KICAgIFNpZ25pZmljYW5jaWFfY29sb3IgPSBjYXNlX3doZW4oDQogICAgICBpcy5uYShwX25fcHJveV9IKSB+ICJObyBjYWxjdWxhYmxlIiwNCiAgICAgIHBfbl9wcm95X0ggPCAwLjAwMSB+ICJwIDwgMC4wMDEiLA0KICAgICAgcF9uX3Byb3lfSCA8IDAuMDEgfiAicCA8IDAuMDEiLA0KICAgICAgcF9uX3Byb3lfSCA8IDAuMDUgfiAicCA8IDAuMDUiLA0KICAgICAgVFJVRSB+ICJObyBzaWduaWZpY2F0aXZhIg0KICAgICkNCiAgKQ0KDQojIENyZWFyIG1hdHJpeiBwYXJhIGhlYXRtYXANCm1hdHJpel9oZWF0IDwtIGhlYXRtYXBfdGlwb19kYXRhICU+JQ0KICBzZWxlY3QoVGlwb19Db211bmEsIFRpcG9fQW5hbGlzaXMsIGNvcl9uX3Byb3lfSCkgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBUaXBvX0FuYWxpc2lzLCB2YWx1ZXNfZnJvbSA9IGNvcl9uX3Byb3lfSCkgJT4lDQogIGNvbHVtbl90b19yb3duYW1lcygiVGlwb19Db211bmEiKQ0KDQpwbG90X2x5KHogPSBhcy5tYXRyaXgobWF0cml6X2hlYXQpLA0KICAgICAgICB4ID0gY29sbmFtZXMobWF0cml6X2hlYXQpLA0KICAgICAgICB5ID0gcm93bmFtZXMobWF0cml6X2hlYXQpLA0KICAgICAgICB0eXBlID0gImhlYXRtYXAiLA0KICAgICAgICBjb2xvcnMgPSBjb2xvclJhbXAoYygiI2Q3MzAyNyIsICIjZmZmZmJmIiwgIiMxYTk4NTAiKSksDQogICAgICAgIHptaWQgPSAwLA0KICAgICAgICB6bWluID0gLTEsDQogICAgICAgIHptYXggPSAxLA0KICAgICAgICB0ZXh0ID0gaGVhdG1hcF90aXBvX2RhdGEgJT4lIA0KICAgICAgICAgIHNlbGVjdChUaXBvX0NvbXVuYSwgVGlwb19BbmFsaXNpcywgVGV4dG9fSG92ZXIpICU+JQ0KICAgICAgICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBUaXBvX0FuYWxpc2lzLCB2YWx1ZXNfZnJvbSA9IFRleHRvX0hvdmVyKSAlPiUNCiAgICAgICAgICBzZWxlY3QoLVRpcG9fQ29tdW5hKSAlPiUNCiAgICAgICAgICBhcy5tYXRyaXgoKSwNCiAgICAgICAgaG92ZXJpbmZvID0gInRleHQiLA0KICAgICAgICBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAiz4EiKSkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gIkNvcnJlbGFjaW9uZXMgcG9yIFRpcG8gZGUgQ29tdW5hIHkgVGlwbyBkZSBBbsOhbGlzaXM8YnI+PHN1Yj5Ow7ptZXJvIGRlIFByb3llY3RvcyB2cyDDjW5kaWNlIGRlIFNoYW5ub248L3N1Yj4iLA0KICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDE2KQ0KICAgICksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlRpcG8gZGUgQW7DoWxpc2lzIiksDQogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlRpcG8gZGUgQ29tdW5hIiksDQogICAgbWFyZ2luID0gbGlzdChsID0gMTUwLCByID0gMTAwLCB0ID0gMTAwLCBiID0gMTAwKQ0KICApDQpgYGANCg0KIyMqKkRpc3BlcnNpw7NuIHBvciBUaXBvIGRlIENvbXVuYSoqDQoNCiAgTG9zIHRyZXMgcGFuZWxlcyBkZSBkaXNwZXJzacOzbiByZXZlbGFuIHBhdHJvbmVzIGRpZmVyZW5jaWFkb3MgcXVlIHZhbGlkYW4gbGEgbmVjZXNpZGFkIGRlbCBhbsOhbGlzaXMgc2VnbWVudGFkby4gRW4gZWwgcGFuZWwgaXpxdWllcmRvIChDRkcpLCBvYnNlcnZhbW9zIHF1ZSBsYXMgY29tdW5hcyBydXJhbGVzIHkgZW4gY29uc3RydWNjacOzbiBtdWVzdHJhbiB1bmEgdGVuZGVuY2lhIGFzY2VuZGVudGUgY2xhcmE6IG1heW9yIG7Dum1lcm8gZGUgcHJveWVjdG9zIHNlIGFzb2NpYSBjb24gbWF5b3IgZGl2ZXJzaWRhZCBkZSBwcm9ibGVtYXMgaWRlbnRpZmljYWRvcy4gRXN0byBzdWdpZXJlIHVuIG1lY2FuaXNtbyBkZSBhcHJlbmRpemFqZSBvcmdhbml6YWNpb25hbCBkb25kZSBsYSBleHBlcmllbmNpYSBwcm95ZWN0dWFsIHBvdGVuY2lhIGxhIGNhcGFjaWRhZCBkaWFnbsOzc3RpY2EuDQoNCiAgRWwgcGFuZWwgY2VudHJhbCAoR29iZXJuYWNpw7NuKSBlcyBlbCBtw6FzIHJldmVsYWRvcjogbXVlc3RyYSB1bmEgcmVsYWNpw7NuIGNhc2kgcGVyZmVjdGFtZW50ZSBsaW5lYWwgZW4gY29tdW5hcyBydXJhbGVzIHkgbWl4dGFzLCBkb25kZSBjYWRhIHByb3llY3RvIGFkaWNpb25hbCBzZSB0cmFkdWNlIGVuIGxhIGluY29ycG9yYWNpw7NuIHByZWRlY2libGUgZGUgbnVldm9zIGFjdG9yZXMgaW5zdGl0dWNpb25hbGVzLg0KDQogIExhIGNvbmNlbnRyYWNpw7NuIGRlIHB1bnRvcyBlbiB0b3JubyBhIGxhIGzDrW5lYSBkZSB0ZW5kZW5jaWEsIHBhcnRpY3VsYXJtZW50ZSBlbiBjb211bmFzIHJ1cmFsZXMsIGV2aWRlbmNpYSBsYSBlc3RhbmRhcml6YWNpw7NuIGluc3RpdHVjaW9uYWwgcXVlIGNhcmFjdGVyaXphIGVzdG9zIGNvbnRleHRvcy4NCkVsIHBhbmVsIGRlcmVjaG8gKFJhdGlvIEFDQSkgbXVlc3RyYSBlbCBoYWxsYXpnbyBtw6FzIGNvbnRyYWludHVpdGl2bzogw7puaWNhbWVudGUgbGFzIGNvbXVuYXMgZW4gY29uc3RydWNjacOzbiBwcmVzZW50YW4gdW5hIHRlbmRlbmNpYSBwb3NpdGl2YSBzaWduaWZpY2F0aXZhLiBFc3RvIGV2aWRlbmNpYSBlbCAiY2ljbG8gdmlydHVvc28iIGRvbmRlLCBlbiBlc3RhcyBjb211bmFzIGVtZXJnZW50ZXMsIG1heW9yIGFjdGl2aWRhZCBwcm95ZWN0dWFsIG5vIGRpbHV5ZSBsYSBlZmVjdGl2aWRhZCBzaW5vIHF1ZSBsYSBwb3RlbmNpYSwgcG9zaWJsZW1lbnRlIHBvcnF1ZSBjYWRhIHByb3llY3RvIGV4aXRvc28gZm9ydGFsZWNlIGxhIGNhcGFjaWRhZCBvcmdhbml6YXRpdmEgeSBsYSBjcmVkaWJpbGlkYWQgYW50ZSBhY3RvcmVzIGluc3RpdHVjaW9uYWxlcy4NCg0KYGBge3J9DQoNCiMgUGFuZWwgMTogQ0ZHIChEaXZlcnNpZGFkIGRlIG51ZG9zIGNyw610aWNvcykNCnAxX2NmZyA8LSBwbG90X2x5KGRhdGEgPSBkaXZfY29tYmluYWRhICU+JSBmaWx0ZXIoVGlwb19BbmFsaXNpcyA9PSAiQ0ZHIiksDQogICAgICAgICAgICAgICAgICB4ID0gfm5fcHJveWVjdG9zLA0KICAgICAgICAgICAgICAgICAgeSA9IH5IX3NoYW5ub24sDQogICAgICAgICAgICAgICAgICBjb2xvciA9IH5UaXBvX0NvbXVuYSwNCiAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoIlVyYmFuYSIgPSAiIzJFODZBQiIsICJSdXJhbCIgPSAiI0EyM0I3MiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNaXh0YSIgPSAiI0YxOEYwMSIsICJFbiBjb25zdHJ1Y2Npw7NuIiA9ICIjQzczRTFEIiksDQogICAgICAgICAgICAgICAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgICAgICAgICAgICAgICAgbW9kZSA9ICdtYXJrZXJzJywNCiAgICAgICAgICAgICAgICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDEwLCBvcGFjaXR5ID0gMC43KSwNCiAgICAgICAgICAgICAgICAgIHRleHQgPSB+cGFzdGUwKCJDb211bmE6ICIsIENPTVVOQV9JRF9OT01CUkUsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb3llY3RvczogIiwgbl9wcm95ZWN0b3MsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNoYW5ub24gQ0ZHOiAiLCByb3VuZChIX3NoYW5ub24sIDMpKSwNCiAgICAgICAgICAgICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JykgJT4lDQogIGxheW91dCh0aXRsZSA9ICJDRkc6IERpdmVyc2lkYWQgZGUgTnVkb3MgQ3LDrXRpY29zIiwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJOw7ptZXJvIGRlIFByb3llY3RvcyIpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIsONbmRpY2UgU2hhbm5vbiAoSCcpIiksDQogICAgICAgICBzaG93bGVnZW5kID0gVFJVRSkNCg0KIyBQYW5lbCAyOiBHb2Jlcm5hY2nDs24gKERpdmVyc2lkYWQgaW5zdGl0dWNpb25hbCkNCnAyX2dvYiA8LSBwbG90X2x5KGRhdGEgPSBkaXZfY29tYmluYWRhICU+JSBmaWx0ZXIoVGlwb19BbmFsaXNpcyA9PSAiR29iZXJuYWNpw7NuIiksDQogICAgICAgICAgICAgICAgICB4ID0gfm5fcHJveWVjdG9zLA0KICAgICAgICAgICAgICAgICAgeSA9IH5IX3NoYW5ub24sDQogICAgICAgICAgICAgICAgICBjb2xvciA9IH5UaXBvX0NvbXVuYSwNCiAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoIlVyYmFuYSIgPSAiIzJFODZBQiIsICJSdXJhbCIgPSAiI0EyM0I3MiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1peHRhIiA9ICIjRjE4RjAxIiwgIkVuIGNvbnN0cnVjY2nDs24iID0gIiNDNzNFMUQiKSwNCiAgICAgICAgICAgICAgICAgIHR5cGUgPSAnc2NhdHRlcicsDQogICAgICAgICAgICAgICAgICBtb2RlID0gJ21hcmtlcnMnLA0KICAgICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChzaXplID0gMTAsIG9wYWNpdHkgPSAwLjcpLA0KICAgICAgICAgICAgICAgICAgdGV4dCA9IH5wYXN0ZTAoIkNvbXVuYTogIiwgQ09NVU5BX0lEX05PTUJSRSwgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHJveWVjdG9zOiAiLCBuX3Byb3llY3RvcywgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2hhbm5vbiBHT0I6ICIsIHJvdW5kKEhfc2hhbm5vbiwgMykpLA0KICAgICAgICAgICAgICAgICAgaG92ZXJpbmZvID0gJ3RleHQnKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIkdvYmVybmFjacOzbjogRGl2ZXJzaWRhZCBJbnN0aXR1Y2lvbmFsIiwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJOw7ptZXJvIGRlIFByb3llY3RvcyIpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIsONbmRpY2UgU2hhbm5vbiAoSCcpIiksDQogICAgICAgICBzaG93bGVnZW5kID0gVFJVRSkNCg0KIyBQYW5lbCAzOiBSYXRpbyBBQ0EgKEVmZWN0aXZpZGFkKQ0KcDNfcmF0aW8gPC0gcGxvdF9seShkYXRhID0gZGl2X2NvbWJpbmFkYSAlPiUgZmlsdGVyKFRpcG9fQW5hbGlzaXMgPT0gIlJhdGlvIEFDQSIpLA0KICAgICAgICAgICAgICAgICAgICB4ID0gfm5fcHJveWVjdG9zLA0KICAgICAgICAgICAgICAgICAgICB5ID0gfkhfc2hhbm5vbiwNCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+VGlwb19Db211bmEsDQogICAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoIlVyYmFuYSIgPSAiIzJFODZBQiIsICJSdXJhbCIgPSAiI0EyM0I3MiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWl4dGEiID0gIiNGMThGMDEiLCAiRW4gY29uc3RydWNjacOzbiIgPSAiI0M3M0UxRCIpLA0KICAgICAgICAgICAgICAgICAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgICAgICAgICAgICAgICAgICBtb2RlID0gJ21hcmtlcnMnLA0KICAgICAgICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KHNpemUgPSAxMCwgb3BhY2l0eSA9IDAuNyksDQogICAgICAgICAgICAgICAgICAgIHRleHQgPSB+cGFzdGUwKCJDb211bmE6ICIsIENPTVVOQV9JRF9OT01CUkUsICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHJveWVjdG9zOiAiLCBuX3Byb3llY3RvcywgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaGFubm9uIFJhdGlvOiAiLCByb3VuZChIX3NoYW5ub24sIDMpKSwNCiAgICAgICAgICAgICAgICAgICAgaG92ZXJpbmZvID0gJ3RleHQnKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIlJhdGlvIEFDQTogRWZlY3RpdmlkYWQgZGUgQ3VsbWluYWNpw7NuIiwNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJOw7ptZXJvIGRlIFByb3llY3RvcyIpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIsONbmRpY2UgU2hhbm5vbiAoSCcpIiksDQogICAgICAgICBzaG93bGVnZW5kID0gVFJVRSkNCg0KIyBDb21iaW5hciBsb3MgdHJlcyBwYW5lbGVzDQpzdWJwbG90KHAxX2NmZywgcDJfZ29iLCBwM19yYXRpbywgbnJvd3MgPSAxLCBzaGFyZVggPSBGQUxTRSwgc2hhcmVZID0gRkFMU0UsIA0KICAgICAgICB0aXRsZVggPSBUUlVFLCB0aXRsZVkgPSBUUlVFKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gbGlzdCh0ZXh0ID0gIlJlbGFjacOzbiBlbnRyZSBOw7ptZXJvIGRlIFByb3llY3RvcyB5IERpdmVyc2lkYWQgcG9yIFRpcG8gZGUgQ29tdW5hPGJyPjxzdWI+QW7DoWxpc2lzIG11bHRpLWVzY2FsYTogQ0ZHLCBHb2Jlcm5hY2nDs24geSBSYXRpbyBBQ0E8L3N1Yj4iLA0KICAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KHNpemUgPSAxNikpLA0KICAgICAgICAgc2hvd2xlZ2VuZCA9IFRSVUUsDQogICAgICAgICBsZWdlbmQgPSBsaXN0KG9yaWVudGF0aW9uID0gInYiLCB4ID0gMS4wNSwgeSA9IDAuNSkpDQpgYGANCg0KIyMqKkV2YWx1YWNpw7NuIGRlIEhpcMOzdGVzaXMgcG9yIFRpcG8gZGUgQ29tdW5hKioNCg0KICBFbCBncsOhZmljbyBkZSBldmFsdWFjacOzbiBkZSBoaXDDs3Rlc2lzIHJldmVsYSB0cmVzIHBhdHJvbmVzIHRlcnJpdG9yaWFsZXMgZGlzdGludGl2b3MgcXVlIGNvbmZpcm1hbiBxdWUgZWwgZnVuY2lvbmFtaWVudG8gZGVsIHNpc3RlbWEgZGUgQUNBIGVzdMOhIHByb2Z1bmRhbWVudGUgY29uZGljaW9uYWRvIHBvciBlbCBjb250ZXh0byBjb211bmFsLg0KDQoqKlByaW1lciBwYXRyw7NuKio6IEdlc3Rpw7NuIGluc3RpdHVjaW9uYWwgcGVyZmVjdGEgZW4gY29tdW5hcyBydXJhbGVzIHkgbWl4dGFzLiBMYXMgaGlww7N0ZXNpcyBIRTIgeSBIRTQgbXVlc3RyYW4gY29ycmVsYWNpb25lcyBwcsOhY3RpY2FtZW50ZSBwZXJmZWN0YXMgKM+BPTEuMDAwIHkgz4E9MC45OTkgcmVzcGVjdGl2YW1lbnRlKSwgZXZpZGVuY2lhbmRvIHF1ZSBlbiBlc3RvcyBjb250ZXh0b3MgZXhpc3RlIHVuIG1lY2FuaXNtbyBkZSBhc2lnbmFjacOzbiBpbnN0aXR1Y2lvbmFsIHF1ZSBvcGVyYSBjb24gcHJlY2lzacOzbiBtYXRlbcOhdGljYS4gRW4gbGFzIDExIGNvbXVuYXMgcnVyYWxlcyBhbmFsaXphZGFzLCBjYWRhIHByb3llY3RvIGFkaWNpb25hbCBzZSB0cmFkdWNlIGVuIHVuYSBleHBhbnNpw7NuIHByZWRlY2libGUgZGUgbGEgcmVkIGluc3RpdHVjaW9uYWwuIEVzdGUgcGF0csOzbiBubyBlcyBjYXN1YWwgc2lubyByZXN1bHRhZG8gZGUgcHJvdG9jb2xvcyBlc3RhbmRhcml6YWRvcyB5IHVuYSBjb21wcmVuc2nDs24gY29tcGFydGlkYSBlbnRyZSBjb211bmlkYWRlcyB5IEVzdGFkbyBzb2JyZSBxdcOpIGFjdG9yIGRlYmUgaW50ZXJ2ZW5pciBzZWfDum4gbGEgbmF0dXJhbGV6YSBkZWwgcHJvYmxlbWEuDQoNCioqU2VndW5kbyBwYXRyw7NuKio6IENpY2xvIHZpcnR1b3NvIGVuIGNvbXVuYXMgZW4gY29uc3RydWNjacOzbi4gTGFzIGhpcMOzdGVzaXMgSEUzIHkgSEU1IHJldmVsYW4gcXVlIGVzdGFzIDIzIGNvbXVuYXMgZW1lcmdlbnRlcyBvcGVyYW4gYmFqbyB1bmEgZGluw6FtaWNhIMO6bmljYS4gUG9yIHVuIGxhZG8sIG11ZXN0cmFuIGFsdGEgY2FwYWNpZGFkIGRlIGFydGljdWxhY2nDs24gaW5zdGl0dWNpb25hbCAoz4E9MC45MTApLCB5IHBvciBvdHJvLCBwcmVzZW50YW4gbGEgw7puaWNhIGNvcnJlbGFjacOzbiBwb3NpdGl2YSBzaWduaWZpY2F0aXZhIGVudHJlIG7Dum1lcm8gZGUgcHJveWVjdG9zIHkgZWZlY3RpdmlkYWQgKM+BPTAuNTQxKS4gRXN0ZSBoYWxsYXpnbyBjb250cmFkaWNlIGxhIGludHVpY2nDs24gZGUgcXVlIG1heW9yIGNhcmdhIHByb3llY3R1YWwgZGlsdXllIGxhIGNhcGFjaWRhZCBkZSBlamVjdWNpw7NuLiBFbiBjb211bmFzIGVuIGNvbnN0cnVjY2nDs24sIGNhZGEgcHJveWVjdG8gZXhpdG9zbyBwYXJlY2UgZm9ydGFsZWNlciBsYSBjYXBhY2lkYWQgb3JnYW5pemF0aXZhLCBjcmVhbmRvIHVuIGPDrXJjdWxvIHZpcnR1b3NvIGRvbmRlIGxhIGFjY2nDs24gcHJveWVjdHVhbCBjb25zdHJ1eWUgc2ltdWx0w6FuZWFtZW50ZSBvYnJhIGbDrXNpY2EgeSBjYXBpdGFsIGluc3RpdHVjaW9uYWwuDQoNCioqVGVyY2VyIHBhdHLDs24qKjogRGVzY29uZXhpw7NuIHVyYmFuYS4gTGEgYXVzZW5jaWEgZGUgaGlww7N0ZXNpcyBlc3BlY8OtZmljYXMgcGFyYSBjb211bmFzIHVyYmFuYXMgZW4gZXN0ZSBncsOhZmljbyBubyBlcyBvbWlzacOzbiBtZXRvZG9sw7NnaWNhIHNpbm8gcmVmbGVqbyBkZSB1biBoYWxsYXpnbyBzdXN0YW50aXZvOiBuaW5ndW5hIGNvcnJlbGFjacOzbiBhbGNhbnrDsyBzaWduaWZpY2FuY2lhIGVzdGFkw61zdGljYSBlbiBlc3RlIGdydXBvLiBFc3RhIGRlc2NvbmV4acOzbiBzdWdpZXJlIHF1ZSBsYXMgY29tdW5hcyB1cmJhbmFzIGVuZnJlbnRhbiBkaW7DoW1pY2FzIG3DoXMgY29tcGxlamFzIGRvbmRlIGxhIGNhbnRpZGFkIGRlIHByb3llY3RvcywgbGEgZGl2ZXJzaWRhZCBpbnN0aXR1Y2lvbmFsIG8gbGEgdGlwb2xvZ8OtYSBkZSBwcm9ibGVtYXMgbm8gcHJlZGljZW4gcGF0cm9uZXMgZGUgY29tcG9ydGFtaWVudG8uIFBvc2libGVtZW50ZSwgZmFjdG9yZXMgY29tbyBidXJvY3JhdGl6YWNpw7NuLCBmcmFnbWVudGFjacOzbiBvcmdhbml6YXRpdmEgbyBzYXR1cmFjacOzbiBkZSBkZW1hbmRhcyBnZW5lcmFuIHVuYSBhbGVhdG9yaWVkYWQgcXVlIGFudWxhIGxhcyByZWxhY2lvbmVzIHNpc3RlbcOhdGljYXMgb2JzZXJ2YWRhcyBlbiBvdHJvcyBjb250ZXh0b3MuDQoNCioqU8OtbnRlc2lzOiBUcmVzIE1vZGVsb3MgZGUgR29iZXJuYW56YSBDb211bmFsKioNCg0KICBFbCBhbsOhbGlzaXMgcG9yIHRpcG9sb2fDrWEgY29tdW5hbCByZXZlbGEgcXVlIG5vIGV4aXN0ZSB1biDDum5pY28gIm1vZGVsbyBBQ0EiIHNpbm8gYWwgbWVub3MgdHJlcyBsw7NnaWNhcyBkZSBmdW5jaW9uYW1pZW50byBkaXN0aW50YXM6DQpNb2RlbG8gUnVyYWw6IEVmaWNpZW5jaWEgaW5zdGl0dWNpb25hbCBjb24gZnJhZ2lsaWRhZCBlbiBlcXVpZGFkLiBMYXMgY29tdW5hcyBydXJhbGVzIG9wZXJhbiBjb24gbGEgbWF5b3IgZWZpY2llbmNpYSBlbiBhc2lnbmFjacOzbiBpbnN0aXR1Y2lvbmFsLiBMYSBjb3JyZWxhY2nDs24gcGVyZmVjdGEgZW50cmUgcHJveWVjdG9zIHkgZGl2ZXJzaWRhZCBpbnN0aXR1Y2lvbmFsICjPgT0xLjAwMCkgZXZpZGVuY2lhIHByb3RvY29sb3MgY2xhcm9zLiANCg0KICBTaW4gZW1iYXJnbywgbGEgY29ycmVsYWNpw7NuIG5lZ2F0aXZhIHBlcmZlY3RhIGVudHJlIGRpdmVyc2lkYWQgeSBlcXVpZGFkICjPgT0tMS4wMDApIHJldmVsYSB1bmEgdGVuc2nDs246IGEgbWF5b3IgZGl2ZXJzaWRhZCBpbnN0aXR1Y2lvbmFsLCBtZW5vciBlcXVpZGFkIGVuIGxhIGRpc3RyaWJ1Y2nDs24gZGUgcmVzcG9uc2FiaWxpZGFkZXMuIEVzdG8gc3VnaWVyZSBjb25jZW50cmFjacOzbiBleGNlc2l2YSBlbiBwb2NvcyBhY3RvcmVzIGNsYXZlLCBwb3NpYmxlbWVudGUgcG9yIGxpbWl0YWNpb25lcyBsb2fDrXN0aWNhcyBvIGRlIGNvb3JkaW5hY2nDs24gcHJvcGlhcyBkZWwgY29udGV4dG8gcnVyYWwuDQpNb2RlbG8gRW4gQ29uc3RydWNjacOzbjogQ3JlY2ltaWVudG8gdmlydHVvc28geSBhcHJlbmRpemFqZSBvcmdhbml6YWNpb25hbC4NCg0KICBFc3RhcyBjb211bmFzIGVtZXJnZW50ZXMgbXVlc3RyYW4gdW4gcGF0csOzbiDDum5pY28gZG9uZGUgbGEgZXNjYWxhYmlsaWRhZCBwcm95ZWN0dWFsIHBvdGVuY2lhIHRhbnRvIGxhIGFydGljdWxhY2nDs24gaW5zdGl0dWNpb25hbCAoz4E9MC45MTApIGNvbW8gbGEgZWZlY3RpdmlkYWQgKM+BPTAuNTQxKS4gRXN0ZSBtb2RlbG8gc3VnaWVyZSBxdWUsIGVuIGZhc2UgZGUgY29uc29saWRhY2nDs24gaW5zdGl0dWNpb25hbCwgY2FkYSBwcm95ZWN0byBleGl0b3NvIGdlbmVyYSBhcHJlbmRpemFqZSBhY3VtdWxhdGl2byBxdWUgZm9ydGFsZWNlIGxhIGNhcGFjaWRhZCBwYXJhIHByb3llY3RvcyBmdXR1cm9zLiBMYSBtb2RlcmFjacOzbiBkZSBsYXMgY29ycmVsYWNpb25lcyAoY29tcGFyYWRhcyBjb24gbGFzIHBlcmZlY3RhcyBlbiBydXJhbGVzKSBpbmRpY2EgcXVlIGVsIHByb2Nlc28gYcO6biBlc3TDoSBlbiBkZXNhcnJvbGxvLCBwZXJvIGxhIGRpcmVjY2nDs24gZXMgcG9zaXRpdmEuDQoNCioqTW9kZWxvIE1peHRvKio6IEdlc3Rpw7NuIHJlbGFjaW9uYWwgY29tbyBmYWN0b3IgZGV0ZXJtaW5hbnRlIGFic29sdXRvLiBDb24gdW5hIGNvcnJlbGFjacOzbiBkZSDPgT0wLjk5OSBlbnRyZSBwcm95ZWN0b3MgeSBkaXZlcnNpZGFkIGluc3RpdHVjaW9uYWwsIGxhcyBjb211bmFzIG1peHRhcyBldmlkZW5jaWFuIHF1ZSBzdSBjYXBhY2lkYWQgZGUgZ2VzdGnDs24gZGVwZW5kZSBjYXNpIGV4Y2x1c2l2YW1lbnRlIGRlIHN1IGhhYmlsaWRhZCBwYXJhIHRlamVyIHJlZGVzIGludGVyaW5zdGl0dWNpb25hbGVzIGNvbXBsZWphcy4gRXN0ZSBtb2RlbG8gc2l0w7phIGxhIGNvb3JkaW5hY2nDs24gcG9saWPDqW50cmljYSBjb21vIGNvbXBldGVuY2lhIGNlbnRyYWwuIEEgZGlmZXJlbmNpYSBkZSBsYXMgcnVyYWxlcywgZG9uZGUgbG9zIHByb3RvY29sb3MgZXN0w6FuIGVzdGFuZGFyaXphZG9zLCBsYXMgbWl4dGFzIHJlcXVpZXJlbiBuZWdvY2lhY2nDs24gY29uc3RhbnRlLg0KDQoqKk1vZGVsbyBVcmJhbm8qKjogQ29tcGxlamlkYWQgbm8gcmVzdWVsdGEuIExhIGF1c2VuY2lhIGRlIGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMgbm8gaW5kaWNhIGZhbHRhIGRlIGFjdGl2aWRhZCBzaW5vIGNvbXBsZWppZGFkIHNpc3TDqW1pY2Egbm8gY2FwdHVyYWRhIHBvciBsYXMgdmFyaWFibGVzIG1lZGlkYXMuIExhcyBjb211bmFzIHVyYmFuYXMgZW5mcmVudGFuIHByb2JhYmxlbWVudGUgZGluw6FtaWNhcyBkZSBzYXR1cmFjacOzbiBpbnN0aXR1Y2lvbmFsLCBidXJvY3JhdGl6YWNpw7NuIGV4Y2VzaXZhIG8gZnJhZ21lbnRhY2nDs24gb3JnYW5pemF0aXZhIHF1ZSByb21wZW4gbGFzIHJlbGFjaW9uZXMgbGluZWFsZXMgb2JzZXJ2YWRhcyBlbiBvdHJvcyBjb250ZXh0b3MuIEVzdGUgaGFsbGF6Z28gc2XDsWFsYSBsYSBuZWNlc2lkYWQgZGUgZXN0dWRpb3MgY3VhbGl0YXRpdm9zIHF1ZSBpZGVudGlmaXF1ZW4gbG9zIG1lY2FuaXNtb3MgZXNwZWPDrWZpY29zIHF1ZSBvcGVyYW4gZW4gZW50b3Jub3MgdXJiYW5vcy4NCg0KKipJbXBsaWNhY2lvbmVzIHBhcmEgUG9sw610aWNhIFDDumJsaWNhKioNCg0KTG9zIGhhbGxhemdvcyBkZWwgYW7DoWxpc2lzIHBvciB0aXBvIGRlIGNvbXVuYSBvYmxpZ2FuIGEgYWJhbmRvbmFyIGVsIGVuZm9xdWUgZGUgInRhbGxhIMO6bmljYSIgZW4gbGFzIHBvbMOtdGljYXMgZGUgYXBveW8gYSBjb211bmFzLiBDYWRhIGNvbnRleHRvIHRlcnJpdG9yaWFsIHJlcXVpZXJlIGVzdHJhdGVnaWFzIGRpZmVyZW5jaWFkYXM6DQoNCioqUGFyYSBjb211bmFzIHJ1cmFsZXMqKjogTWFudGVuZXIgbGEgZWZpY2llbmNpYSBpbnN0aXR1Y2lvbmFsIGlkZW50aWZpY2FkYSwgcGVybyBpbmNvcnBvcmFyIG1lY2FuaXNtb3MgcXVlIHByb211ZXZhbiBtYXlvciBlcXVpZGFkIGVuIGxhIGRpc3RyaWJ1Y2nDs24gZGUgcmVzcG9uc2FiaWxpZGFkZXMgZWplY3V0aXZhcy4gRXZpdGFyIGxhIHNvYnJlY2FyZ2EgZGUgcG9jb3MgYWN0b3JlcyBpbnN0aXR1Y2lvbmFsZXMgbWVkaWFudGUgZXNxdWVtYXMgZGUgY29ycmVzcG9uc2FiaWxpZGFkIHBsYW5pZmljYWRhLg0KDQoqKlBhcmEgY29tdW5hcyBlbiBjb25zdHJ1Y2Npw7NuKio6IFByaW9yaXphciBsYSBmYWNpbGl0YWNpw7NuIGRlIHByb3llY3RvcyBpbmljaWFsZXMsIHJlY29ub2NpZW5kbyBxdWUgY2FkYSBwcm95ZWN0byBleGl0b3NvIGdlbmVyYSBjYXBhY2lkYWRlcyBhY3VtdWxhdGl2YXMuIERpc2XDsWFyIGVzcXVlbWFzIGRlIGFjb21wYcOxYW1pZW50byB0w6ljbmljbyBpbnRlbnNpdm8gZW4gbGFzIHByaW1lcmFzIGV0YXBhcywgY29uIHJlZHVjY2nDs24gZ3JhZHVhbCBhIG1lZGlkYSBxdWUgbGEgY29tdW5hIGNvbnNvbGlkYSBzdSBjYXBhY2lkYWQgb3JnYW5pemF0aXZhLg0KDQoqKlBhcmEgY29tdW5hcyBtaXh0YXMqKjogSW52ZXJ0aXIgZW4gZWwgZGVzYXJyb2xsbyBkZSBjYXBhY2lkYWRlcyBkZSBnZXN0acOzbiByZWxhY2lvbmFsIHkgbmVnb2NpYWNpw7NuIGludGVyaW5zdGl0dWNpb25hbC4gQ3JlYXIgZXNwYWNpb3MgZGUgYXJ0aWN1bGFjacOzbiBxdWUgZmFjaWxpdGVuIGxhIGNvb3JkaW5hY2nDs24gcG9saWPDqW50cmljYS4gUmVjb25vY2VyIHF1ZSBlbiBlc3RvcyBjb250ZXh0b3MgZWwgw6l4aXRvIGRlcGVuZGUgbcOhcyBkZSBsYXMgaGFiaWxpZGFkZXMgcmVsYWNpb25hbGVzIHF1ZSBkZSBsb3MgcmVjdXJzb3MgdMOpY25pY29zIG8gZmluYW5jaWVyb3MuDQoNCioqUGFyYSBjb211bmFzIHVyYmFuYXMqKjogUmVhbGl6YXIgaW52ZXN0aWdhY2nDs24gY3VhbGl0YXRpdmEgdXJnZW50ZSBwYXJhIGlkZW50aWZpY2FyIGxvcyBmYWN0b3JlcyBlc3BlY8OtZmljb3MgcXVlIGdlbmVyYW4gZGVzY29uZXhpw7NuIGVudHJlIHBsYW5pZmljYWNpw7NuIHkgZWplY3VjacOzbi4gUG9zaWJsZW1lbnRlIHJlcXVpZXJlbiByZWZvcm1hcyBlc3RydWN0dXJhbGVzIGVuIGxvcyBtZWNhbmlzbW9zIGRlIGFydGljdWxhY2nDs24gaW5zdGl0dWNpb25hbCwgZGFkbyBxdWUgbG9zIHByb3RvY29sb3MgcXVlIGZ1bmNpb25hbiBlbiBvdHJvcyBjb250ZXh0b3Mgbm8gZ2VuZXJhbiBsb3MgbWlzbW9zIHJlc3VsdGFkb3MuDQoNCmBgYHtyfQ0KDQojI0V2YWx1YWNpw7NuIGRlIGxhcyBjb211bmFzDQoNCmV2YWx1YWNpb25fdGlwb19jb211bmEgPC0gZGF0YS5mcmFtZSgNCiAgSGlwb3Rlc2lzID0gYygNCiAgICAiSEUxOiBSdXJhbCAoQ0ZHKSIsDQogICAgIkhFMjogUnVyYWwgKEdPQikiLA0KICAgICJIRTM6IEVuIENvbnN0cnVjY2nDs24gKEdPQikiLA0KICAgICJIRTQ6IE1peHRhIChHT0IpIiwNCiAgICAiSEU1OiBFbiBDb25zdHJ1Y2Npw7NuIChSYXRpbyBBQ0EpIg0KICApLA0KICBSaG8gPSBjKDAuNzQyLCAxLjAwMCwgMC45MTAsIDAuOTk5LCAwLjU0MSksDQogIFBfdmFsb3IgPSBjKDAuMDA5LCAwLjAwMCwgMC4wMDAsIDAuMDAwLCAwLjAwOCksDQogIE5fY29tdW5hcyA9IGMoMTEsIDExLCAyMywgMjMsIDIzKSwNCiAgRXN0YWRvID0gYygiQ29uZmlybWFkYSIsICJDb25maXJtYWRhIiwgIkNvbmZpcm1hZGEiLCAiQ29uZmlybWFkYSIsICJDb25maXJtYWRhIiksDQogIENvbG9yID0gYygiIzI3YWU2MCIsICIjMjdhZTYwIiwgIiMyN2FlNjAiLCAiIzI3YWU2MCIsICIjMjdhZTYwIikNCikNCg0KcGxvdF9seSAoZXZhbHVhY2lvbl90aXBvX2NvbXVuYSwNCiAgICAgICAgeSA9IH5yZW9yZGVyKEhpcG90ZXNpcywgUmhvKSwNCiAgICAgICAgeCA9IH5SaG8sDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgb3JpZW50YXRpb24gPSAnaCcsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSB+Q29sb3IpLA0KICAgICAgICB0ZXh0ID0gfnBhc3RlMCgiz4EgPSAiLCByb3VuZChSaG8sIDMpLCAiPGJyPiIsInAtdmFsb3I6ICIsIGZvcm1hdC5wdmFsKFBfdmFsb3IsIGRpZ2l0cyA9IDMpLCAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgIm4gPSAiLCBOX2NvbXVuYXMsICIgY29tdW5hczxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICJFc3RhZG86ICIsIEVzdGFkbyksDQogICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JykgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gIkV2YWx1YWNpw7NuIEVtcMOtcmljYSBkZSBIaXDDs3Rlc2lzIHBvciBUaXBvIGRlIENvbXVuYTxicj48c3ViPk1hZ25pdHVkIGRlIGNvcnJlbGFjaW9uZXMgeSBuaXZlbCBkZSBjb25maXJtYWNpw7NuPC9zdWI+IiwNCiAgICAgIGZvbnQgPSBsaXN0KHNpemUgPSAxNikNCiAgICApLA0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJDb2VmaWNpZW50ZSBkZSBTcGVhcm1hbiAoz4EpIiwgcmFuZ2UgPSBjKDAsIDEuMSkpLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICIiKSwNCiAgICBtYXJnaW4gPSBsaXN0KGwgPSAyNTAsIHIgPSA1MCwgdCA9IDEwMCwgYiA9IDUwKSwNCiAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgKSAlPiUNCiAgYWRkX2Fubm90YXRpb25zKA0KICAgIHggPSB+UmhvICsgMC4wNSwNCiAgICB5ID0gfkhpcG90ZXNpcywNCiAgICB0ZXh0ID0gfnBhc3RlMCgiz4E9Iiwgcm91bmQoUmhvLCAzKSwgIlxubj0iLCBOX2NvbXVuYXMpLA0KICAgIHNob3dhcnJvdyA9IEZBTFNFLA0KICAgIHhhbmNob3IgPSAnbGVmdCcsDQogICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDEwLCBjb2xvciA9ICdibGFjaycpDQogICkNCmBgYA0KDQojIyAqKkJsb3F1ZSBkZSBQcmVwYXJhY2nDs24gZGUgVmFyaWFibGVzIGRlcml2YWRhcyBwYXJhIG90cm9zIGFuw6FsaXNpcyBwb3N0ZXJpb3JlcyoqDQoNCmBgYHtyfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEJMT1FVRSBERSBQUkVQQVJBQ0nDk04gREUgVkFSSUFCTEVTIERFUklWQURBUyBQQVJBIEFOw4FMSVNJUyBQT1NURVJJT1JFUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgUHJvcG9yY2nDs24gZGUgcHJveWVjdG9zIHBvciBlc3RhZG8gZGUgY3VsbWluYWNpw7NuIGRlIHByb3llY3RvcyAocG9yIGNvbXVuYSkNCmRmX2VzdGFkbyA8LSBkZl9yYXcgJT4lDQogIGdyb3VwX2J5KElEX0NPTVVOQSwgQ0xBU0lGSUNBQ0lPTl9ERUxfUFJPWUVDVE8pICU+JQ0KICBzdW1tYXJpc2Uobl9lc3RhZG8gPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQ0KICBncm91cF9ieShJRF9DT01VTkEpICU+JQ0KICBtdXRhdGUocHJvcF9lc3RhZG8gPSBuX2VzdGFkbyAvIHN1bShuX2VzdGFkbykpICU+JQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gQ0xBU0lGSUNBQ0lPTl9ERUxfUFJPWUVDVE8sIHZhbHVlc19mcm9tID0gcHJvcF9lc3RhZG8sIG5hbWVzX3ByZWZpeCA9ICJwcm9wX2VzdGFkb18iLCB2YWx1ZXNfZmlsbCA9IDApDQoNCiMgUHJvcG9yY2nDs24gZGUgcHJveWVjdG9zIHBvciBhY3RvciBpbnN0aXR1Y2lvbmFsIChwb3IgY29tdW5hKQ0KZGZfYWN0b3IgPC0gZGZfcmF3ICU+JQ0KICBncm91cF9ieShJRF9DT01VTkEsIENsYXNpZmljYWNpb25fQWN0b3Jlc19pbnN0aXR1Y2lvbmFsZXMpICU+JQ0KICBzdW1tYXJpc2Uobl9hY3RvciA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lDQogIGdyb3VwX2J5KElEX0NPTVVOQSkgJT4lDQogIG11dGF0ZShwcm9wX2FjdG9yID0gbl9hY3RvciAvIHN1bShuX2FjdG9yKSkgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBDbGFzaWZpY2FjaW9uX0FjdG9yZXNfaW5zdGl0dWNpb25hbGVzLCB2YWx1ZXNfZnJvbSA9IHByb3BfYWN0b3IsIG5hbWVzX3ByZWZpeCA9ICJwcm9wX2FjdG9yXyIsIHZhbHVlc19maWxsID0gMCkNCg0KIyAtLS0gMi4gRGl2ZXJzaWRhZCBkZSB0aXBvbG9nw61hcyB5IGFjdG9yZXMgKFNoYW5ub24vUGllbG91KSAtLS0NCg0KIyBEaXZlcnNpZGFkIGRlIHRpcG9sb2fDrWFzIChDRkcpIHBvciBjb211bmENCmNmZ19jb2xzIDwtIGdyZXAoIl5DTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkdfIiwgbmFtZXMoZGZfcmF3KSwgdmFsdWUgPSBUUlVFKQ0KZGl2X3RpcG9sb2dpYSA8LSBkZl9yYXcgJT4lDQogIGdyb3VwX2J5KElEX0NPTVVOQSkgJT4lDQogIHN1bW1hcmlzZShuX3Byb3llY3RvcyA9IG4oKSwgYWNyb3NzKGFsbF9vZihjZmdfY29scyksIH5zdW0oLngsIG5hLnJtID0gVFJVRSkpKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICB7DQogICAgY250cyA8LSBzZWxlY3QoLiwgYWxsX29mKGNmZ19jb2xzKSkNCiAgICB0aWIgPC0gc2VsZWN0KC4sIElEX0NPTVVOQSwgbl9wcm95ZWN0b3MpDQogICAgSF9jZmcgPC0gdmVnYW46OmRpdmVyc2l0eShjbnRzLCBpbmRleCA9ICJzaGFubm9uIikNCiAgICByaXF1ZXphX2NmZyA8LSByb3dTdW1zKGNudHMgPiAwKQ0KICAgIEpfY2ZnIDwtIGlmZWxzZShyaXF1ZXphX2NmZyA+IDAsIEhfY2ZnIC8gbG9nKHJpcXVlemFfY2ZnKSwgTkFfcmVhbF8pDQogICAgYmluZF9jb2xzKHRpYiwgSF9jZmcgPSBIX2NmZywgSl9jZmcgPSBKX2NmZykNCiAgfQ0KDQojIERpdmVyc2lkYWQgZGUgYWN0b3JlcyBpbnN0aXR1Y2lvbmFsZXMgcG9yIGNvbXVuYQ0KYWN0b3JfY29scyA8LSBncmVwKCJeQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19HT0JFUk5BQ0lPTl8iLCBuYW1lcyhkZl9yYXcpLCB2YWx1ZSA9IFRSVUUpDQpkaXZfYWN0b3IgPC0gZGZfcmF3ICU+JQ0KICBncm91cF9ieShJRF9DT01VTkEpICU+JQ0KICBzdW1tYXJpc2Uobl9wcm95ZWN0b3MgPSBuKCksIGFjcm9zcyhhbGxfb2YoYWN0b3JfY29scyksIH5zdW0oLngsIG5hLnJtID0gVFJVRSkpKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICB7DQogICAgY250cyA8LSBzZWxlY3QoLiwgYWxsX29mKGFjdG9yX2NvbHMpKQ0KICAgIHRpYiA8LSBzZWxlY3QoLiwgSURfQ09NVU5BLCBuX3Byb3llY3RvcykNCiAgICBIX2FjdG9yIDwtIHZlZ2FuOjpkaXZlcnNpdHkoY250cywgaW5kZXggPSAic2hhbm5vbiIpDQogICAgcmlxdWV6YV9hY3RvciA8LSByb3dTdW1zKGNudHMgPiAwKQ0KICAgIEpfYWN0b3IgPC0gaWZlbHNlKHJpcXVlemFfYWN0b3IgPiAwLCBIX2FjdG9yIC8gbG9nKHJpcXVlemFfYWN0b3IpLCBOQV9yZWFsXykNCiAgICBiaW5kX2NvbHModGliLCBIX2FjdG9yID0gSF9hY3RvciwgSl9hY3RvciA9IEpfYWN0b3IpDQogIH0NCg0KIyAtLS0gMy4gUmF0aW8gZGUgY3VsbWluYWNpw7NuIHZzIGRpdmVyc2lkYWQgLS0tDQoNCiMgQ2FsY3VsYSBlbCBwcm9tZWRpbyBkZSByYXRpbyBkZSBjdWxtaW5hY2nDs24gcG9yIGNvbXVuYQ0KZGZfcmF0aW8gPC0gZGZfcmF3ICU+JQ0KICBncm91cF9ieShJRF9DT01VTkEpICU+JQ0KICBzdW1tYXJpc2UocmF0aW9fbWVkaWEgPSBtZWFuKFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIG5hLnJtID0gVFJVRSkpDQoNCiMgLS0tIFVuaXIgdG9kb3MgbG9zIGluZGljYWRvcmVzIGVuIHVuYSB0YWJsYSBtYWVzdHJhIC0tLQ0KDQp0YWJsYV9tYWVzdHJhIDwtIGRpdl90aXBvbG9naWEgJT4lDQogIGxlZnRfam9pbihkaXZfYWN0b3IgJT4lIHNlbGVjdChJRF9DT01VTkEsIEhfYWN0b3IsIEpfYWN0b3IpLCBieSA9ICJJRF9DT01VTkEiKSAlPiUNCiAgbGVmdF9qb2luKGRmX2VzdGFkbywgYnkgPSAiSURfQ09NVU5BIikgJT4lDQogIGxlZnRfam9pbihkZl9hY3RvciwgYnkgPSAiSURfQ09NVU5BIikgJT4lDQogIGxlZnRfam9pbihkZl9yYXRpbywgYnkgPSAiSURfQ09NVU5BIikNCmBgYA0KDQojIyAqKkFuw6FsaXNpcyBkZSBQQ0EqKg0KDQogIEVsIEFuw6FsaXNpcyBkZSBDb21wb25lbnRlcyBQcmluY2lwYWxlcyAoUENBKSBzZSBoYSBpbXBsZW1lbnRhZG8gY29tbyB1bmEgdMOpY25pY2EgZXN0YWTDrXN0aWNhIG11bHRpdmFyaWFudGUgZnVuZGFtZW50YWwgZW4gZXN0YSBpbnZlc3RpZ2FjacOzbiBwYXJhIGlkZW50aWZpY2FyIHBhdHJvbmVzIHN1YnlhY2VudGVzIGVuIGxhIGdlc3Rpw7NuIGRlIHByb3llY3RvcyBjb211bml0YXJpb3MgQUNBIGVuIGVsIEVzdGFkbyBNw6lyaWRhLiBFc3RlIG3DqXRvZG8gcGVybWl0ZSByZWR1Y2lyIGxhIGRpbWVuc2lvbmFsaWRhZCBkZWwgY29uanVudG8gZGUgZGF0b3MgY29tcGxlam9zLCB0cmFuc2Zvcm1hbmRvIHZhcmlhYmxlcyBjb3JyZWxhY2lvbmFkYXMgZW4gdW4gY29uanVudG8gbWVub3IgZGUgdmFyaWFibGVzIG5vIGNvcnJlbGFjaW9uYWRhcyBsbGFtYWRhcyBjb21wb25lbnRlcyBwcmluY2lwYWxlcywgcXVlIGNvbnNlcnZhbiBsYSBtYXlvciBwYXJ0ZSBkZSBsYSBpbmZvcm1hY2nDs24gb3JpZ2luYWwuDQoNCmBgYHtyfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSAxOiBQUkVQQVJBQ0nDk04gWSBWQUxJREFDScOTTiBERSBEQVRPUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbi0tLSBGQVNFIDE6IFBSRVBBUkFDScOTTiBERSBEQVRPUyAtLS1cbiIpDQoNCiMgVmVyaWZpY2FyIHF1ZSB0YWJsYV9tYWVzdHJhIGV4aXN0ZSB5IHRpZW5lIGxhcyB2YXJpYWJsZXMgbmVjZXNhcmlhcw0KaWYoIWV4aXN0cygidGFibGFfbWFlc3RyYSIpKSB7DQogIHN0b3AoIkVSUk9SOiBObyBzZSBlbmN1ZW50cmEgZWwgb2JqZXRvICd0YWJsYV9tYWVzdHJhJy4gDQogICAgICAgRWplY3V0YXIgcHJpbWVybyBsb3MgYW7DoWxpc2lzIHByZXZpb3MgZGUgZGl2ZXJzaWRhZCBTaGFubm9uLiIpDQp9DQoNCiMgU2VsZWNjacOzbiBpbnRlbGlnZW50ZSBkZSB2YXJpYWJsZXMgcGFyYSBQQ0ENCiMgSW5jbHVpbW9zIHRvZGFzIGxhcyB2YXJpYWJsZXMgY3VhbnRpdGF0aXZhcyByZWxldmFudGVzIGRpc3BvbmlibGVzDQp2YXJpYWJsZXNfZGl2ZXJzaWRhZCA8LSBjKCJuX3Byb3llY3RvcyIsICJIX2NmZyIsICJKX2NmZyIsICJIX2FjdG9yIiwgIkpfYWN0b3IiKQ0KdmFyaWFibGVzX3Jlc3VsdGFkbyA8LSBjKCJyYXRpb19tZWRpYSIpDQp2YXJpYWJsZXNfZXN0YWRvIDwtIGdyZXAoIl5wcm9wX2VzdGFkb18iLCBuYW1lcyh0YWJsYV9tYWVzdHJhKSwgdmFsdWUgPSBUUlVFKQ0KdmFyaWFibGVzX2FjdG9yIDwtIGdyZXAoIl5wcm9wX2FjdG9yXyIsIG5hbWVzKHRhYmxhX21hZXN0cmEpLCB2YWx1ZSA9IFRSVUUpDQoNCiMgQ29tYmluYXIgdG9kYXMgbGFzIHZhcmlhYmxlcyBkaXNwb25pYmxlcw0KcGNhX3ZhcnMgPC0gYyh2YXJpYWJsZXNfZGl2ZXJzaWRhZCwgdmFyaWFibGVzX3Jlc3VsdGFkbywgDQogICAgICAgICAgICAgIHZhcmlhYmxlc19lc3RhZG8sIHZhcmlhYmxlc19hY3RvcikNCg0KIyBGaWx0cmFyIHNvbG8gbGFzIHZhcmlhYmxlcyBxdWUgcmVhbG1lbnRlIGV4aXN0ZW4gZW4gZWwgZGF0YXNldA0KcGNhX3ZhcnMgPC0gcGNhX3ZhcnNbcGNhX3ZhcnMgJWluJSBuYW1lcyh0YWJsYV9tYWVzdHJhKV0NCg0KY2F0KCJWYXJpYWJsZXMgc2VsZWNjaW9uYWRhcyBwYXJhIFBDQTpcbiIpDQpmb3IoaSBpbiAxOmxlbmd0aChwY2FfdmFycykpIHsNCiAgY2F0KHNwcmludGYoIiUyZC4gJXNcbiIsIGksIHBjYV92YXJzW2ldKSkNCn0NCmNhdCgiVG90YWwgZGUgdmFyaWFibGVzOiIsIGxlbmd0aChwY2FfdmFycyksICJcbiIpDQoNCiMgUHJlcGFyYXIgZGF0YXNldCBwYXJhIFBDQSBlbGltaW5hbmRvIHZhbG9yZXMgZmFsdGFudGVzDQpwY2FfZGF0YSA8LSB0YWJsYV9tYWVzdHJhICU+JSANCiAgc2VsZWN0KGFsbF9vZihwY2FfdmFycykpICU+JSANCiAgbmEub21pdCgpDQoNCiMgVmVyaWZpY2FyIGNhbGlkYWQgZGUgbG9zIGRhdG9zDQpjYXQoIlxuQ2FsaWRhZCBkZWwgZGF0YXNldDpcbiIpDQpjYXQoIi0gQ2Fzb3MgY29tcGxldG9zOiIsIG5yb3cocGNhX2RhdGEpLCAiY29tdW5hc1xuIikNCmNhdCgiLSBWYXJpYWJsZXMgaW5jbHVpZGFzOiIsIG5jb2wocGNhX2RhdGEpLCAiXG4iKQ0KY2F0KCItIENhc29zIGVsaW1pbmFkb3MgcG9yIE5BOiIsIG5yb3codGFibGFfbWFlc3RyYSkgLSBucm93KHBjYV9kYXRhKSwgIlxuIikNCg0KIyBDcmVhciBtYXBlbyBkZSB0aXBvIGRlIGNvbXVuYSBzaSBleGlzdGUNCmlmKCJUaXBvX0NvbXVuYSIgJWluJSBuYW1lcyh0YWJsYV9tYWVzdHJhKSkgew0KICBpbmRpY2VzX3ZhbGlkb3MgPC0gYXMubnVtZXJpYyhyb3duYW1lcyhwY2FfZGF0YSkpDQogIHRpcG9fY29tdW5hIDwtIHRhYmxhX21hZXN0cmEkVGlwb19Db211bmFbaW5kaWNlc192YWxpZG9zXQ0KICBjYXQoIi0gQWdydXBhY2nDs24gcG9yIFRpcG8gZGUgQ29tdW5hOiBESVNQT05JQkxFXG4iKQ0KICBjYXQoIi0gRGlzdHJpYnVjacOzbjoiLCB0YWJsZSh0aXBvX2NvbXVuYSksICJcbiIpDQp9IGVsc2Ugew0KICB0aXBvX2NvbXVuYSA8LSBOVUxMDQogIGNhdCgiLSBBZ3J1cGFjacOzbiBwb3IgVGlwbyBkZSBDb211bmE6IE5PIERJU1BPTklCTEVcbiIpDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFBBU08gMjogTUFUUklaIERFIENPVkFSSUFOWkFTIFkgQU7DgUxJU0lTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIj09PSBQQVNPIDI6IEFOw4FMSVNJUyBDT04gTUFUUklaIERFIENPVkFSSUFOWkFTID09PVxuIikNCg0KIyAyLjEgQ0FMQ1VMQVIgTUFUUklaIERFIENPVkFSSUFOWkFTDQptYXRyaXpfY292IDwtIGNvdihwY2FfZGF0YSkNCg0KIyBDcmVhciB0YWJsYSBkZSBtYXRyaXogZGUgY292YXJpYW56YXMNCnRhYmxhX2NvdiA8LSBrYWJsZShyb3VuZChtYXRyaXpfY292LCA0KSwgDQogICAgICAgICAgICAgICAgICAgZm9ybWF0ID0gImh0bWwiLA0KICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAiVGFibGEgWC4xOiBNYXRyaXogZGUgQ292YXJpYW56YXMgZGUgbGFzIFZhcmlhYmxlcyBPcmlnaW5hbGVzIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lDQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI0MDBweCIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIk1hdHJpeiBzaW3DqXRyaWNhIGRvbmRlIGVsZW1lbnRvcyBkaWFnb25hbGVzIHJlcHJlc2VudGFuIHZhcmlhbnphcyB5IG9mZi1kaWFnb25hbCByZXByZXNlbnRhbiBjb3ZhcmlhbnphcyIsDQogICAgICAgICAgIGdlbmVyYWxfdGl0bGUgPSAiTm90YToiKQ0KDQp0YWJsYV9jb3YNCg0KIyAyLjIgUENBIENPTiBNQVRSSVogREUgQ09WQVJJQU5aQVMNCnBjYV9jb3YgPC0gcHJjb21wKHBjYV9kYXRhLCBzY2FsZS4gPSBGQUxTRSkNCg0KIyAyLjMgQ0FMQ1VMQVIgRVNUQUTDjVNUSUNBUyBQQVJBIENPVkFSSUFOWkFTDQp2YXJpYW56YV9jb3YgPC0gKHBjYV9jb3Ykc2Rldl4yIC8gc3VtKHBjYV9jb3Ykc2Rldl4yKSkgKiAxMDANCmF1dG92YWxvcmVzX2NvdiA8LSBwY2FfY292JHNkZXZeMg0KbnVtX3ZhcnMgPC0gbmNvbChwY2FfZGF0YSkNCg0KIyAyLjQgVEFCTEEgREUgQVVUT1ZBTE9SRVMgLSBDT1ZBUklBTlpBUw0KdGFibGFfYXV0b3ZhbG9yZXNfY292IDwtIGRhdGEuZnJhbWUoDQogIENvbXBvbmVudGUgPSBwYXN0ZTAoIlBDIiwgMTpudW1fdmFycyksDQogIEF1dG92YWxvciA9IHJvdW5kKGF1dG92YWxvcmVzX2NvdiwgNCksDQogIERlc3ZpYWNpb25fU3RkID0gcm91bmQocGNhX2NvdiRzZGV2LCA0KSwNCiAgVmFyaWFuemFfRXhwbGljYWRhID0gcm91bmQodmFyaWFuemFfY292LCA0KSwNCiAgVmFyaWFuemFfQWN1bXVsYWRhID0gcm91bmQoY3Vtc3VtKHZhcmlhbnphX2NvdiksIDQpLA0KICBDcml0ZXJpb19LYWlzZXIgPSBpZmVsc2UoYXV0b3ZhbG9yZXNfY292ID4gMSwgIlPDjSIsICJOTyIpDQopDQoNCmthYmxlX2F1dG92YWxfY292IDwtIGthYmxlKHRhYmxhX2F1dG92YWxvcmVzX2NvdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdCA9ICJodG1sIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSBYLjI6IEFuw6FsaXNpcyBkZSBDb21wb25lbnRlcyBQcmluY2lwYWxlcyAtIE1hdHJpeiBkZSBDb3ZhcmlhbnphcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFKSAlPiUNCiAgcm93X3NwZWMod2hpY2goYXV0b3ZhbG9yZXNfY292ID4gMSksIGJvbGQgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiIzRDQUY1MCIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gYygiQ3JpdGVyaW8gZGUgS2Fpc2VyOiBSZXRlbmVyIGNvbXBvbmVudGVzIGNvbiBhdXRvdmFsb3JlcyA+IDEiLA0KICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJDb21wb25lbnRlcyByZXRlbmlkb3M6Iiwgc3VtKGF1dG92YWxvcmVzX2NvdiA+IDEpKSksDQogICAgICAgICAgIGdlbmVyYWxfdGl0bGUgPSAiTm90YToiKQ0KDQprYWJsZV9hdXRvdmFsX2Nvdg0KDQojIDIuNSBNQVRSSVogREUgUk9UQUNJw5NOIChMT0FESU5HUykgLSBDT1ZBUklBTlpBUw0KbG9hZGluZ3NfY292IDwtIGFzLmRhdGEuZnJhbWUocm91bmQocGNhX2NvdiRyb3RhdGlvbiwgNCkpDQoNCmthYmxlX2xvYWRpbmdzX2NvdiA8LSBrYWJsZShsb2FkaW5nc19jb3YsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0ID0gImh0bWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSBYLjM6IE1hdHJpeiBkZSBSb3RhY2nDs24gKExvYWRpbmdzKSAtIFBDQSBjb24gQ292YXJpYW56YXMiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpICU+JQ0KICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiNDAwcHgiKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9ICJDYXJnYXMgaW5kaWNhbiBsYSBjb250cmlidWNpw7NuIGRlIGNhZGEgdmFyaWFibGUgb3JpZ2luYWwgYSBjYWRhIGNvbXBvbmVudGUgcHJpbmNpcGFsIiwNCiAgICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICJJbnRlcnByZXRhY2nDs246IikNCg0Ka2FibGVfbG9hZGluZ3NfY292DQoNCiMgMi42IElOVEVSUFJFVEFDScOTTiBERSBSRVNVTFRBRE9TIC0gQ09WQVJJQU5aQVMNCmNhdCgiXG4tLS0gSU5URVJQUkVUQUNJw5NOIE1BVFJJWiBERSBDT1ZBUklBTlpBUyAtLS1cbiIpDQpjYXQoIkNvbXBvbmVudGVzIHF1ZSBjdW1wbGVuIGNyaXRlcmlvIEthaXNlciAozrsgPiAxKToiLCBzdW0oYXV0b3ZhbG9yZXNfY292ID4gMSksICJcbiIpDQpjYXQoIlZhcmlhbnphIGV4cGxpY2FkYSBwb3IgUEMxOiIsIHJvdW5kKHZhcmlhbnphX2NvdlsxXSwgMiksICIlXG4iKQ0KY2F0KCJWYXJpYW56YSBhY3VtdWxhZGEgcHJpbWVyb3MiLCBzdW0oYXV0b3ZhbG9yZXNfY292ID4gMSksICJjb21wb25lbnRlczoiLCANCiAgICByb3VuZChzdW0odmFyaWFuemFfY292W2F1dG92YWxvcmVzX2NvdiA+IDFdKSwgMiksICIlXG4iKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBQQVNPIDM6IE1BVFJJWiBERSBDT1JSRUxBQ0lPTkVTIFkgQU7DgUxJU0lTICANCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG49PT0gUEFTTyAzOiBBTsOBTElTSVMgQ09OIE1BVFJJWiBERSBDT1JSRUxBQ0lPTkVTID09PVxuIikNCg0KIyAzLjEgQ0FMQ1VMQVIgTUFUUklaIERFIENPUlJFTEFDSU9ORVMNCm1hdHJpel9jb3IgPC0gY29yKHBjYV9kYXRhKQ0KDQojIEZ1bmNpw7NuIHBhcmEgcmVzYWx0YXIgY29ycmVsYWNpb25lcyBmdWVydGVzDQpyZXNhbHRhcl9jb3JyZWxhY2lvbmVzIDwtIGZ1bmN0aW9uKG1hdHJpel9jb3IpIHsNCiAgbWF0X251bWVyaWMgPC0gcm91bmQobWF0cml6X2NvciwgNCkNCiAgbWF0X2Zvcm1hdHRlZCA8LSBtYXRfbnVtZXJpYyAgIyBDb3BpYSBwYXJhIG1vZGlmaWNhcg0KICANCiAgIyBDcmVhciBtYXRyaXogZGUgc2FsaWRhIGNvbiBmb3JtYXRvIEhUTUwNCiAgZm9yKGkgaW4gMTpucm93KG1hdF9udW1lcmljKSkgew0KICAgIGZvcihqIGluIDE6bmNvbChtYXRfbnVtZXJpYykpIHsNCiAgICAgIGlmKGkgIT0gaikgeyAgIyBObyByZXNhbHRhciBkaWFnb25hbA0KICAgICAgICB2YWxvcl9hYnMgPC0gYWJzKG1hdF9udW1lcmljW2ksIGpdKSAgIyBVc2FyIG1hdHJpeiBudW3DqXJpY2Egb3JpZ2luYWwNCiAgICAgICAgdmFsb3JfYWN0dWFsIDwtIG1hdF9udW1lcmljW2ksIGpdICAgICAjIFZhbG9yIGFjdHVhbCBudW3DqXJpY28NCiAgICAgICAgDQogICAgICAgIGlmKHZhbG9yX2FicyA+IDAuNykgew0KICAgICAgICAgICMgQ29ycmVsYWNpw7NuIG11eSBmdWVydGUNCiAgICAgICAgICBjb2xvcl9mb25kbyA8LSBpZmVsc2UodmFsb3JfYWN0dWFsID4gMCwgIiNGRjZCNkIiLCAiIzRFQ0RDNCIpDQogICAgICAgICAgbWF0X2Zvcm1hdHRlZFtpLCBqXSA8LSBjZWxsX3NwZWModmFsb3JfYWN0dWFsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZCA9IGNvbG9yX2ZvbmRvLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIGJvbGQgPSBUUlVFKQ0KICAgICAgICB9IGVsc2UgaWYodmFsb3JfYWJzID4gMC41KSB7DQogICAgICAgICAgIyBDb3JyZWxhY2nDs24gZnVlcnRlDQogICAgICAgICAgY29sb3JfZm9uZG8gPC0gaWZlbHNlKHZhbG9yX2FjdHVhbCA+IDAsICIjRkZFMDY2IiwgIiNBOEU2Q0YiKQ0KICAgICAgICAgIG1hdF9mb3JtYXR0ZWRbaSwgal0gPC0gY2VsbF9zcGVjKHZhbG9yX2FjdHVhbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQgPSBjb2xvcl9mb25kbywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKQ0KICAgICAgICB9DQogICAgICB9DQogICAgfQ0KICB9DQogIHJldHVybihtYXRfZm9ybWF0dGVkKQ0KfQ0KDQojIENyZWFyIHRhYmxhIGRlIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIGNvbiByZXNhbHRhZG8NCm1hdHJpel9jb3JfZm9ybWF0dGVkIDwtIHJlc2FsdGFyX2NvcnJlbGFjaW9uZXMobWF0cml6X2NvcikNCg0KdGFibGFfY29yIDwtIGthYmxlKG1hdHJpel9jb3JfZm9ybWF0dGVkLCANCiAgICAgICAgICAgICAgICAgICBmb3JtYXQgPSAiaHRtbCIsDQogICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSBYLjQ6IE1hdHJpeiBkZSBDb3JyZWxhY2lvbmVzIGNvbiBSZXNhbHRhZG8gZGUgQ29ycmVsYWNpb25lcyBGdWVydGVzIiwNCiAgICAgICAgICAgICAgICAgICBlc2NhcGUgPSBGQUxTRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lDQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI0MDBweCIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gYygiUm9qby9OYXJhbmphOiBDb3JyZWxhY2lvbmVzIHBvc2l0aXZhcyBmdWVydGVzICg+MC41KSIsDQogICAgICAgICAgICAgICAgICAgICAgIkF6dWwvVmVyZGU6IENvcnJlbGFjaW9uZXMgbmVnYXRpdmFzIGZ1ZXJ0ZXMgKDwtMC41KSIsDQogICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGFjaW9uZXMgPnwwLjd8IGVuIG5lZ3JpdGEiKSwNCiAgICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICJMZXllbmRhOiIpDQoNCnRhYmxhX2Nvcg0KDQojIDMuMiBQQ0EgQ09OIE1BVFJJWiBERSBDT1JSRUxBQ0lPTkVTIChWQVJJQUJMRVMgRVNUQU5EQVJJWkFEQVMpDQpwY2FfY29yIDwtIHByY29tcChwY2FfZGF0YSwgc2NhbGUuID0gVFJVRSkNCg0KIyAzLjMgQ0FMQ1VMQVIgRVNUQUTDjVNUSUNBUyBQQVJBIENPUlJFTEFDSU9ORVMgIA0KdmFyaWFuemFfY29yIDwtIChwY2FfY29yJHNkZXZeMiAvIHN1bShwY2FfY29yJHNkZXZeMikpICogMTAwDQphdXRvdmFsb3Jlc19jb3IgPC0gcGNhX2NvciRzZGV2XjINCg0KIyAzLjQgVEFCTEEgREUgQVVUT1ZBTE9SRVMgLSBDT1JSRUxBQ0lPTkVTDQp0YWJsYV9hdXRvdmFsb3Jlc19jb3IgPC0gZGF0YS5mcmFtZSgNCiAgQ29tcG9uZW50ZSA9IHBhc3RlMCgiUEMiLCAxOm51bV92YXJzKSwNCiAgQXV0b3ZhbG9yID0gcm91bmQoYXV0b3ZhbG9yZXNfY29yLCA0KSwNCiAgRGVzdmlhY2lvbl9TdGQgPSByb3VuZChwY2FfY29yJHNkZXYsIDQpLA0KICBWYXJpYW56YV9FeHBsaWNhZGEgPSByb3VuZCh2YXJpYW56YV9jb3IsIDQpLA0KICBWYXJpYW56YV9BY3VtdWxhZGEgPSByb3VuZChjdW1zdW0odmFyaWFuemFfY29yKSwgNCksDQogIENyaXRlcmlvX0thaXNlciA9IGlmZWxzZShhdXRvdmFsb3Jlc19jb3IgPiAxLCAiU8ONIiwgIk5PIikNCikNCg0Ka2FibGVfYXV0b3ZhbF9jb3IgPC0ga2FibGUodGFibGFfYXV0b3ZhbG9yZXNfY29yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0ID0gImh0bWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlRhYmxhIFguNTogQW7DoWxpc2lzIGRlIENvbXBvbmVudGVzIFByaW5jaXBhbGVzIC0gTWF0cml6IGRlIENvcnJlbGFjaW9uZXMiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lDQogIHJvd19zcGVjKHdoaWNoKGF1dG92YWxvcmVzX2NvciA+IDEpLCBib2xkID0gVFJVRSwgY29sb3IgPSAid2hpdGUiLCBiYWNrZ3JvdW5kID0gIiMyRTg2QUIiKSAlPiUNCiAgZm9vdG5vdGUoZ2VuZXJhbCA9IGMoIkNyaXRlcmlvIGRlIEthaXNlcjogUmV0ZW5lciBjb21wb25lbnRlcyBjb24gYXV0b3ZhbG9yZXMgPiAxIiwNCiAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiQ29tcG9uZW50ZXMgcmV0ZW5pZG9zOiIsIHN1bShhdXRvdmFsb3Jlc19jb3IgPiAxKSksDQogICAgICAgICAgICAgICAgICAgICAgIk3DqXRvZG8gcmVjb21lbmRhZG8gcGFyYSB2YXJpYWJsZXMgY29uIGRpZmVyZW50ZXMgZXNjYWxhcyIpLA0KICAgICAgICAgICBnZW5lcmFsX3RpdGxlID0gIk5vdGE6IikNCg0Ka2FibGVfYXV0b3ZhbF9jb3INCg0KIyAzLjUgTUFUUklaIERFIFJPVEFDScOTTiAoTE9BRElOR1MpIC0gQ09SUkVMQUNJT05FUw0KbG9hZGluZ3NfY29yIDwtIGFzLmRhdGEuZnJhbWUocm91bmQocGNhX2NvciRyb3RhdGlvbiwgNCkpDQoNCmthYmxlX2xvYWRpbmdzX2NvciA8LSBrYWJsZShsb2FkaW5nc19jb3IsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0ID0gImh0bWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSBYLjY6IE1hdHJpeiBkZSBSb3RhY2nDs24gKExvYWRpbmdzKSAtIFBDQSBjb24gQ29ycmVsYWNpb25lcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkgJT4lDQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI0MDBweCIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gYygiVmFyaWFibGVzIGVzdGFuZGFyaXphZGFzIChtZWRpYT0wLCBkZXN2aWFjacOzbj0xKSIsDQogICAgICAgICAgICAgICAgICAgICAgIkNhcmdhcyBtdWVzdHJhbiBjb3JyZWxhY2nDs24gZW50cmUgdmFyaWFibGVzIHkgY29tcG9uZW50ZXMiKSwNCiAgICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICJJbnRlcnByZXRhY2nDs246IikNCg0Ka2FibGVfbG9hZGluZ3NfY29yDQoNCiMgMy42IElOVEVSUFJFVEFDScOTTiBERSBSRVNVTFRBRE9TIC0gQ09SUkVMQUNJT05FUw0KY2F0KCJcbi0tLSBJTlRFUlBSRVRBQ0nDk04gTUFUUklaIERFIENPUlJFTEFDSU9ORVMgLS0tXG4iKQ0KY2F0KCJDb21wb25lbnRlcyBxdWUgY3VtcGxlbiBjcml0ZXJpbyBLYWlzZXIgKM67ID4gMSk6Iiwgc3VtKGF1dG92YWxvcmVzX2NvciA+IDEpLCAiXG4iKQ0KY2F0KCJWYXJpYW56YSBleHBsaWNhZGEgcG9yIFBDMToiLCByb3VuZCh2YXJpYW56YV9jb3JbMV0sIDIpLCAiJVxuIikNCmNhdCgiVmFyaWFuemEgZXhwbGljYWRhIHBvciBQQzI6Iiwgcm91bmQodmFyaWFuemFfY29yWzJdLCAyKSwgIiVcbiIpDQpjYXQoIlZhcmlhbnphIGFjdW11bGFkYSBwcmltZXJvcyIsIHN1bShhdXRvdmFsb3Jlc19jb3IgPiAxKSwgImNvbXBvbmVudGVzOiIsIA0KICAgIHJvdW5kKHN1bSh2YXJpYW56YV9jb3JbYXV0b3ZhbG9yZXNfY29yID4gMV0pLCAyKSwgIiVcbiIpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFBBU08gNDogRk9STVVMQUNJw5NOIERFIEhJUMOTVEVTSVMgS0FJU0VSDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuPT09IFBBU08gNDogRk9STVVMQUNJw5NOIERFIEhJUMOTVEVTSVMgU0VHw5pOIENSSVRFUklPIEtBSVNFUiA9PT1cbiIpDQoNCiMgQ3JlYXIgdGFibGEgZGUgaGlww7N0ZXNpcw0KaGlwb3Rlc2lzX2thaXNlciA8LSBkYXRhLmZyYW1lKA0KICBBc3BlY3RvID0gYygiSGlww7N0ZXNpcyBOdWxhIChI4oKAKSIsIA0KICAgICAgICAgICAgICAiSGlww7N0ZXNpcyBBbHRlcm5hdGl2YSAoSOKCgSkiLCANCiAgICAgICAgICAgICAgIlJlZ2xhIGRlIERlY2lzacOzbiIsDQogICAgICAgICAgICAgICJOaXZlbCBkZSBTaWduaWZpY2FuY2lhIiwNCiAgICAgICAgICAgICAgIkFwbGljYWNpw7NuIENvdmFyaWFuemFzIiwNCiAgICAgICAgICAgICAgIkFwbGljYWNpw7NuIENvcnJlbGFjaW9uZXMiKSwNCiAgRGVzY3JpcGNpw7NuID0gYygNCiAgICAiRWwgYXV0b3ZhbG9yIGRlbCBjb21wb25lbnRlIHByaW5jaXBhbCBlcyDiiaQgMSAobm8gZXhwbGljYSBtw6FzIHZhcmlhbnphIHF1ZSB2YXJpYWJsZSBpbmRpdmlkdWFsKSIsDQogICAgIkVsIGF1dG92YWxvciBkZWwgY29tcG9uZW50ZSBwcmluY2lwYWwgZXMgPiAxIChleHBsaWNhIG3DoXMgdmFyaWFuemEgcXVlIHZhcmlhYmxlIGluZGl2aWR1YWwpIiwNCiAgICAiUmVjaGF6YXIgSOKCgCBjdWFuZG8gzrsgPiAxLCBpbmRpY2FuZG8gY29tcG9uZW50ZSBzaWduaWZpY2F0aXZvIiwNCiAgICAizrEgPSAwLjA1IChjcml0ZXJpbyBlc3TDoW5kYXIgZGUgS2Fpc2VyLCAxOTYwKSIsDQogICAgcGFzdGUoc3VtKGF1dG92YWxvcmVzX2NvdiA+IDEpLCAiY29tcG9uZW50ZXMgcmV0ZW5pZG9zIiksDQogICAgcGFzdGUoc3VtKGF1dG92YWxvcmVzX2NvciA+IDEpLCAiY29tcG9uZW50ZXMgcmV0ZW5pZG9zIikNCiAgKQ0KKQ0KDQprYWJsZV9oaXBvdGVzaXMgPC0ga2FibGUoaGlwb3Rlc2lzX2thaXNlciwgDQogICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXQgPSAiaHRtbCIsDQogICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlRhYmxhIFguNzogRm9ybXVsYWNpw7NuIGRlIEhpcMOzdGVzaXMgcGFyYSBDcml0ZXJpbyBkZSBLYWlzZXIiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEZBTFNFKSAlPiUNCiAgcm93X3NwZWMoNTo2LCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjRThGNEY4IikgJT4lDQogIGZvb3Rub3RlKGdlbmVyYWwgPSAiUmVmZXJlbmNpYTogS2Fpc2VyLCBILkYuICgxOTYwKS4gVGhlIGFwcGxpY2F0aW9uIG9mIGVsZWN0cm9uaWMgY29tcHV0ZXJzIHRvIGZhY3RvciBhbmFseXNpcy4iLA0KICAgICAgICAgICBnZW5lcmFsX3RpdGxlID0gIkZ1ZW50ZToiKQ0KDQprYWJsZV9oaXBvdGVzaXMNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgUEFTTyA1OiBUQUJMQSBDT01QQVJBVElWQSBGSU5BTA0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbj09PSBQQVNPIDU6IENPTVBBUkFDScOTTiBNRVRPRE9Mw5NHSUNBIEZJTkFMID09PVxuIikNCg0KIyBDcmVhciB0YWJsYSBjb21wYXJhdGl2YSBkZSBhbWJvcyBtw6l0b2Rvcw0KY29tcGFyYWNpb25fbWV0b2RvcyA8LSBkYXRhLmZyYW1lKA0KICBBc3BlY3RvID0gYygiTWF0cml6IHV0aWxpemFkYSIsIA0KICAgICAgICAgICAgICAiVmFyaWFibGVzIGVzdGFuZGFyaXphZGFzIiwNCiAgICAgICAgICAgICAgIkNvbXBvbmVudGVzIHJldGVuaWRvcyAozrsgPiAxKSIsDQogICAgICAgICAgICAgICJWYXJpYW56YSBQQzEgKCUpIiwNCiAgICAgICAgICAgICAgIlZhcmlhbnphIFBDMiAoJSkiLCANCiAgICAgICAgICAgICAgIlZhcmlhbnphIHRvdGFsIGV4cGxpY2FkYSAoJSkiLA0KICAgICAgICAgICAgICAiRGlzdHJpYnVjacOzbiBkZSB2YXJpYW56YSIsDQogICAgICAgICAgICAgICJJbnRlcnByZXRhYmlsaWRhZCIsDQogICAgICAgICAgICAgICJSZWNvbWVuZGFjacOzbiIpLA0KICBDb3ZhcmlhbnphcyA9IGMoIkNvdmFyaWFuemFzIiwNCiAgICAgICAgICAgICAgICAgIk5vIiwNCiAgICAgICAgICAgICAgICAgc3VtKGF1dG92YWxvcmVzX2NvdiA+IDEpLA0KICAgICAgICAgICAgICAgICByb3VuZCh2YXJpYW56YV9jb3ZbMV0sIDIpLA0KICAgICAgICAgICAgICAgICBpZmVsc2UobGVuZ3RoKHZhcmlhbnphX2NvdikgPj0gMiwgcm91bmQodmFyaWFuemFfY292WzJdLCAyKSwgIk4vQSIpLA0KICAgICAgICAgICAgICAgICByb3VuZChzdW0odmFyaWFuemFfY292W2F1dG92YWxvcmVzX2NvdiA+IDFdKSwgMiksDQogICAgICAgICAgICAgICAgICJEZXNiYWxhbmNlYWRhIiwNCiAgICAgICAgICAgICAgICAgIkxpbWl0YWRhIiwNCiAgICAgICAgICAgICAgICAgIk5vIHJlY29tZW5kYWRvIiksDQogIENvcnJlbGFjaW9uZXMgPSBjKCJDb3JyZWxhY2lvbmVzIiwNCiAgICAgICAgICAgICAgICAgICAiU8OtIiwNCiAgICAgICAgICAgICAgICAgICBzdW0oYXV0b3ZhbG9yZXNfY29yID4gMSksDQogICAgICAgICAgICAgICAgICAgcm91bmQodmFyaWFuemFfY29yWzFdLCAyKSwNCiAgICAgICAgICAgICAgICAgICByb3VuZCh2YXJpYW56YV9jb3JbMl0sIDIpLA0KICAgICAgICAgICAgICAgICAgIHJvdW5kKHN1bSh2YXJpYW56YV9jb3JbYXV0b3ZhbG9yZXNfY29yID4gMV0pLCAyKSwNCiAgICAgICAgICAgICAgICAgICAiRXF1aWxpYnJhZGEiLA0KICAgICAgICAgICAgICAgICAgICJBbHRhIiwNCiAgICAgICAgICAgICAgICAgICAiUmVjb21lbmRhZG8g4pyTIikNCikNCg0Ka2FibGVfY29tcGFyYWNpb24gPC0ga2FibGUoY29tcGFyYWNpb25fbWV0b2RvcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdCA9ICJodG1sIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICJUYWJsYSBYLjg6IENvbXBhcmFjacOzbiBNZXRvZG9sw7NnaWNhIC0gQ292YXJpYW56YXMgdnMgQ29ycmVsYWNpb25lcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRkFMU0UpICU+JQ0KICBjb2x1bW5fc3BlYygzLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjQzhFNkM5IikgJT4lDQogIHJvd19zcGVjKDksIGJvbGQgPSBUUlVFLCBjb2xvciA9ICJ3aGl0ZSIsIGJhY2tncm91bmQgPSAiIzRDQUY1MCIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIlNlIHJlY29taWVuZGEgdXNhciBtYXRyaXogZGUgY29ycmVsYWNpb25lcyBwb3IgbWF5b3IgZXF1aWxpYnJpbyBlIGludGVycHJldGFiaWxpZGFkIiwNCiAgICAgICAgICAgZ2VuZXJhbF90aXRsZSA9ICJDb25jbHVzacOzbjoiKQ0KDQprYWJsZV9jb21wYXJhY2lvbg0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBQQVNPIDY6IFZJU1VBTElaQUNJw5NOIERFIE1BVFJJWiBERSBDT1JSRUxBQ0lPTkVTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuPT09IFBBU08gNjogVklTVUFMSVpBQ0nDk04gREUgQ09SUkVMQUNJT05FUyA9PT1cbiIpDQoNCiMgQ3JlYXIgY29ycnBsb3QNCmNvcnJwbG90KG1hdHJpel9jb3IsIA0KICAgICAgICAgbWV0aG9kID0gImNvbG9yIiwNCiAgICAgICAgIHR5cGUgPSAidXBwZXIiLCANCiAgICAgICAgIG9yZGVyID0gImhjbHVzdCIsIA0KICAgICAgICAgdGwuY29sID0gImJsYWNrIiwgDQogICAgICAgICB0bC5zcnQgPSA0NSwNCiAgICAgICAgIHRsLmNleCA9IDAuOCwNCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwNCiAgICAgICAgIG51bWJlci5jZXggPSAwLjYsDQogICAgICAgICB0aXRsZSA9ICJNYXRyaXogZGUgQ29ycmVsYWNpb25lcyAtIFZhcmlhYmxlcyBQQ0FcblByb3llY3RvcyBBQ0EgRXN0YWRvIE3DqXJpZGEiLA0KICAgICAgICAgbWFyID0gYygwLDAsNCwwKSkNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgUEFTTyA3OiBNRU5TQUpFIEZJTkFMIFkgUkVDT01FTkRBQ0lPTkVTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuPT09IENPTkNMVVNJT05FUyBNRVRPRE9Mw5NHSUNBUyA9PT1cbiIpDQpjYXQoIjEuIEpVU1RJRklDQUNJw5NOOlxuIikNCmNhdCgiICAgLSBNYXRyaXogZGUgY29ycmVsYWNpb25lcyBldml0YSBzZXNnbyBwb3IgZGlmZXJlbmNpYXMgZGUgZXNjYWxhXG4iKQ0KY2F0KCIgICAtIERpc3RyaWJ1Y2nDs24gbcOhcyBlcXVpbGlicmFkYSBkZSBsYSB2YXJpYW56YSBleHBsaWNhZGFcbiIpDQpjYXQoIiAgIC0gTWF5b3IgaW50ZXJwcmV0YWJpbGlkYWQgZGUgbG9zIGNvbXBvbmVudGVzXG5cbiIpDQoNCmNhdCgiMi4gUkVTVUxUQURPUyBDTEFWRTpcbiIpDQpjYXQoIiAgIC0gQ29tcG9uZW50ZXMgcmV0ZW5pZG9zIChjb3JyZWxhY2lvbmVzKToiLCBzdW0oYXV0b3ZhbG9yZXNfY29yID4gMSksICJcbiIpDQpjYXQoIiAgIC0gVmFyaWFuemEgdG90YWwgZXhwbGljYWRhOiIsIHJvdW5kKHN1bSh2YXJpYW56YV9jb3JbYXV0b3ZhbG9yZXNfY29yID4gMV0pLCAxKSwgIiVcbiIpDQpjYXQoIiAgIC0gUHJpbWVyIGNvbXBvbmVudGUgZXhwbGljYToiLCByb3VuZCh2YXJpYW56YV9jb3JbMV0sIDEpLCAiJSAoYmFsYW5jZWFkbylcblxuIikNCg0KY2F0KCIzLiBQQVJBIExBIE1PTk9HUkFGw41BOlxuIikNCmNhdCgiICAgLSBVc2FyIGFuw6FsaXNpcyBjb24gbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgY29tbyBwcmluY2lwYWxcbiIpDQpjYXQoIiAgIC0gSW5jbHVpciBjb21wYXJhY2nDs24gbWV0b2RvbMOzZ2ljYSBjb21vIGp1c3RpZmljYWNpw7NuXG4iKQ0KY2F0KCIgICAtIEludGVycHJldGFyIGNvbXBvbmVudGVzIGJhc8OhbmRvc2UgZW4gbG9hZGluZ3MgZGUgY29ycmVsYWNpb25lc1xuXG4iKQ0KDQpjYXQoIj09PT09PT0gQU7DgUxJU0lTIFBDQSBFU1RSVUNUVVJBRE8gQ09NUExFVEFETyA9PT09PT09XG4iKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBBTsOBTElTSVMgQ09NUExFVE8gREUgQ09NUE9ORU5URVMgUFJJTkNJUEFMRVMgKFBDQSkNCiMgUFJPWUVDVE9TIEFDQSAtIEVTVEFETyBNw4lSSURBDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIENvbmZpZ3VyYXIgdGVtYSB2aXN1YWwgY29uc2lzdGVudGUgcGFyYSB0b2RhcyBsYXMgdmlzdWFsaXphY2lvbmVzDQp0ZW1hX2FjYWRlbWljbyA8LSB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNCwgaGp1c3QgPSAwLjUpLA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICJncmF5NDAiLCBoanVzdCA9IDAuNSksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk5MCIsIGxpbmV3aWR0aCA9IDAuNSksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQ0KICApDQoNCiMgUGFsZXRhIGRlIGNvbG9yZXMgcGFyYSB0aXBvcyBkZSBjb211bmEgKHNpIGFwbGljYSkNCmNvbG9yZXNfY29tdW5hIDwtIGMoDQogICJVcmJhbmEiID0gIiMyRTg2QUIiLCAgICAgICAgICAgIyBBenVsIC0gZGVuc2lkYWQgdXJiYW5hDQogICJSdXJhbCIgPSAiI0EyM0I3MiIsICAgICAgICAgICAgIyBNYWdlbnRhIC0gcnVyYWxpZGFkDQogICJNaXh0YSIgPSAiI0YxOEYwMSIsICAgICAgICAgICAgIyBOYXJhbmphIC0gY29tYmluYWNpw7NuDQogICJFbiBjb25zdHJ1Y2Npw7NuIiA9ICIjQzczRTFEIiwgICAjIFJvam8gLSBkZXNhcnJvbGxvDQogICJObyBlc3BlY2lmaWNhZG8iID0gIiM3RDg0OTEiICAgICMgR3JpcyAtIHNpbiBjbGFzaWZpY2FyDQopDQoNCmNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCmNhdCgiSU5JQ0lBTkRPIEFOw4FMSVNJUyBERSBDT01QT05FTlRFUyBQUklOQ0lQQUxFUyAoUENBKSBST0JVU1RPXG4iKQ0KY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZBU0UgMjogQU7DgUxJU0lTIEVYUExPUkFUT1JJTyBQUkUtUENBDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuLS0tIEZBU0UgMjogQU7DgUxJU0lTIEVYUExPUkFUT1JJTyAtLS1cbiIpDQoNCiMgRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgYsOhc2ljYXMNCmNhdCgiRXN0YWTDrXN0aWNhcyBkZXNjcmlwdGl2YXMgZGUgbGFzIHZhcmlhYmxlczpcbiIpDQpkZXNjX3N0YXRzIDwtIHBjYV9kYXRhICU+JQ0KICBzdW1tYXJpc2VfYWxsKGxpc3QoDQogICAgTWVkaWEgPSB+IHJvdW5kKG1lYW4oLiwgbmEucm0gPSBUUlVFKSwgMyksDQogICAgRGVzdmlhY2lvbkVzdCA9IH4gcm91bmQoc2QoLiwgbmEucm0gPSBUUlVFKSwgMyksDQogICAgTWluaW1vID0gfiByb3VuZChtaW4oLiwgbmEucm0gPSBUUlVFKSwgMyksDQogICAgTWF4aW1vID0gfiByb3VuZChtYXgoLiwgbmEucm0gPSBUUlVFKSwgMykNCiAgKSkgJT4lDQogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gInZhcmlhYmxlX3N0YXQiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUNCiAgc2VwYXJhdGUodmFyaWFibGVfc3RhdCwgaW50byA9IGMoInZhcmlhYmxlIiwgInN0YXRpc3RpYyIpLCBzZXAgPSAiXyg/PVteX10qJCkiKSAlPiUNCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0YXRpc3RpYywgdmFsdWVzX2Zyb20gPSB2YWx1ZSkNCg0KcHJpbnQoZGVzY19zdGF0cykNCg0KIyBNYXRyaXogZGUgY29ycmVsYWNpb25lcyB5IHN1IGFuw6FsaXNpcw0KY29yX21hdHJpeCA8LSBjb3IocGNhX2RhdGEsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0KDQojIElkZW50aWZpY2FyIGNvcnJlbGFjaW9uZXMgc2lnbmlmaWNhdGl2YXMNCmNhdCgiXG5BbsOhbGlzaXMgZGUgY29ycmVsYWNpb25lczpcbiIpDQpjb3JfZmxhdCA8LSBjb3JfbWF0cml4ICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkgJT4lDQogIG11dGF0ZSh2YXIxID0gcm93bmFtZXMoLikpICU+JQ0KICBwaXZvdF9sb25nZXIoLXZhcjEsIG5hbWVzX3RvID0gInZhcjIiLCB2YWx1ZXNfdG8gPSAiY29ycmVsYXRpb24iKSAlPiUNCiAgZmlsdGVyKHZhcjEgIT0gdmFyMiwgYWJzKGNvcnJlbGF0aW9uKSA+IDAuMykgJT4lDQogIGFycmFuZ2UoZGVzYyhhYnMoY29ycmVsYXRpb24pKSkNCg0KY2F0KCJDb3JyZWxhY2lvbmVzIG1vZGVyYWRhcyBhIGZ1ZXJ0ZXMgKHxyfCA+IDAuMyk6IiwgbnJvdyhjb3JfZmxhdCksICJcbiIpDQppZihucm93KGNvcl9mbGF0KSA+IDApIHsNCiAgY2F0KCJMYXMgNSBjb3JyZWxhY2lvbmVzIG3DoXMgZnVlcnRlczpcbiIpDQogIHByaW50KGhlYWQoY29yX2ZsYXQsIDUpKQ0KfQ0KDQojIFZpc3VhbGl6YWNpw7NuIGRlIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzDQpjb3JycGxvdChjb3JfbWF0cml4LCANCiAgICAgICAgIG1ldGhvZCA9ICJjb2xvciIsDQogICAgICAgICB0eXBlID0gInVwcGVyIiwgDQogICAgICAgICBvcmRlciA9ICJoY2x1c3QiLCANCiAgICAgICAgIHRsLmNvbCA9ICJibGFjayIsIA0KICAgICAgICAgdGwuc3J0ID0gNDUsDQogICAgICAgICB0bC5jZXggPSAwLjgsDQogICAgICAgICBhZGRDb2VmLmNvbCA9ICJibGFjayIsDQogICAgICAgICBudW1iZXIuY2V4ID0gMC43LA0KICAgICAgICAgdGl0bGUgPSAiTWF0cml6IGRlIENvcnJlbGFjaW9uZXMgLSBWYXJpYWJsZXMgUENBXG5Qcm95ZWN0b3MgQUNBIEVzdGFkbyBNw6lyaWRhIiwNCiAgICAgICAgIG1hciA9IGMoMCwwLDMsMCkpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZBU0UgMzogRVZBTFVBQ0nDk04gREUgQURFQ1VBQ0nDk04gUEFSQSBQQ0ENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG4tLS0gRkFTRSAzOiBFVkFMVUFDScOTTiBERSBBREVDVUFDScOTTiAtLS1cbiIpDQoNCiMgVGVzdCBkZSBLYWlzZXItTWV5ZXItT2xraW4gKEtNTykNCiMgRnVuY2nDs24gcGFyYSBjYWxjdWxhciBLTU8gbWFudWFsbWVudGUNCmNhbGN1bGFyX2ttbyA8LSBmdW5jdGlvbihSKSB7DQogICMgUiBlcyBsYSBtYXRyaXogZGUgY29ycmVsYWNpb25lcw0KICBSX2ludiA8LSBzb2x2ZShSKQ0KICBSX3BhcmNpYWwgPC0gLWNvdjJjb3IoUl9pbnYpDQogIGRpYWcoUl9wYXJjaWFsKSA8LSAwDQogIA0KICBzdW1fcjIgPC0gc3VtKFJeMikgLSBzdW0oZGlhZyhSKV4yKQ0KICBzdW1fcGFyY2lhbDIgPC0gc3VtKFJfcGFyY2lhbF4yKQ0KICANCiAga21vIDwtIHN1bV9yMiAvIChzdW1fcjIgKyBzdW1fcGFyY2lhbDIpDQogIHJldHVybihrbW8pDQp9DQoNCmttb192YWx1ZSA8LSBjYWxjdWxhcl9rbW8oY29yX21hdHJpeCkNCmttb19pbnRlcnByZXRhdGlvbiA8LSBjYXNlX3doZW4oDQogIGttb192YWx1ZSA+PSAwLjkgfiAiRXhjZWxlbnRlIiwNCiAga21vX3ZhbHVlID49IDAuOCB+ICJNdXkgYnVlbm8iLCANCiAga21vX3ZhbHVlID49IDAuNyB+ICJCdWVubyIsDQogIGttb192YWx1ZSA+PSAwLjYgfiAiTWVkaW9jcmUiLA0KICBUUlVFIH4gIkluYWRlY3VhZG8iDQopDQoNCmNhdCgiw41uZGljZSBLYWlzZXItTWV5ZXItT2xraW4gKEtNTyk6Iiwgcm91bmQoa21vX3ZhbHVlLCAzKSwgIigiLCBrbW9faW50ZXJwcmV0YXRpb24sICIpXG4iKQ0KDQojIFRlc3QgZGUgZXNmZXJpY2lkYWQgZGUgQmFydGxldHQNCm4gPC0gbnJvdyhwY2FfZGF0YSkNCnAgPC0gbmNvbChwY2FfZGF0YSkNCmJhcnRsZXR0X2NoaTIgPC0gLShuIC0gMSAtICgyKnAgKyA1KS82KSAqIGxvZyhkZXQoY29yX21hdHJpeCkpDQpiYXJ0bGV0dF9kZiA8LSBwICogKHAgLSAxKSAvIDINCmJhcnRsZXR0X3AgPC0gMSAtIHBjaGlzcShiYXJ0bGV0dF9jaGkyLCBiYXJ0bGV0dF9kZikNCg0KY2F0KCJUZXN0IGRlIEVzZmVyaWNpZGFkIGRlIEJhcnRsZXR0OlxuIikNCmNhdCgiLSBDaGktY3VhZHJhZG86Iiwgcm91bmQoYmFydGxldHRfY2hpMiwgMiksICJcbiIpDQpjYXQoIi0gR3JhZG9zIGRlIGxpYmVydGFkOiIsIGJhcnRsZXR0X2RmLCAiXG4iKQ0KY2F0KCItIHAtdmFsb3I6IiwgZm9ybWF0LnB2YWwoYmFydGxldHRfcCwgZGlnaXRzID0gMyksICJcbiIpDQpjYXQoIi0gSW50ZXJwcmV0YWNpw7NuOiIsIGlmZWxzZShiYXJ0bGV0dF9wIDwgMC4wNSwgIlJlY2hhemFtb3MgSDA6IGxhcyB2YXJpYWJsZXMgZXN0w6FuIGNvcnJlbGFjaW9uYWRhcyIsICJObyByZWNoYXphbW9zIEgwIiksICJcbiIpDQoNCiMgRGVjaWRpciBzaSBwcm9jZWRlciBjb24gUENBDQppZihrbW9fdmFsdWUgPCAwLjYpIHsNCiAgd2FybmluZygiQURWRVJURU5DSUE6IEtNTyA8IDAuNiBzdWdpZXJlIHF1ZSBQQ0EgcHVlZGUgbm8gc2VyIGFwcm9waWFkbyIpDQp9DQppZihiYXJ0bGV0dF9wID4gMC4wNSkgew0KICB3YXJuaW5nKCJBRFZFUlRFTkNJQTogVGVzdCBkZSBCYXJ0bGV0dCBubyBzaWduaWZpY2F0aXZvIC0gdmFyaWFibGVzIHB1ZWRlbiBlc3RhciBpbmNvcnJlbGFjaW9uYWRhcyIpDQp9DQoNCmNhdCgiREVDSVNJw5NOOiBQcm9jZWRlciBjb24gUENBIC0iLCANCiAgICBpZmVsc2Uoa21vX3ZhbHVlID49IDAuNiAmJiBiYXJ0bGV0dF9wIDwgMC4wNSwgIkFQUk9QSUFETyIsICJDT04gUFJFQ0FVQ0nDk04iKSwgIlxuIikNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSA0OiBFSkVDVUNJw5NOIERFTCBQQ0ENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG4tLS0gRkFTRSA0OiBFSkVDVUNJw5NOIERFTCBQQ0EgLS0tXG4iKQ0KDQojIENvbXBhcmFjacOzbiBtZXRvZG9sw7NnaWNhOiBDb3ZhcmlhbnphcyB2cyBDb3JyZWxhY2lvbmVzDQpjYXQoIkNvbXBhcmFjacOzbiBtZXRvZG9sw7NnaWNhXG4iKQ0KDQojIFBDQSBjb24gbWF0cml6IGRlIGNvdmFyaWFuemFzICh2YXJpYWJsZXMgc2luIGVzdGFuZGFyaXphcikNCnBjYV9jb3YgPC0gcHJjb21wKHBjYV9kYXRhLCBzY2FsZS4gPSBGQUxTRSkNCmNhdCgiUHJpbWVyYXMgMyBkZXN2aWFjaW9uZXMgZXN0w6FuZGFyIChDb3Zhcmlhbnphcyk6Iiwgcm91bmQocGNhX2NvdiRzZGV2WzE6M10sIDQpLCAiXG4iKQ0KDQojIFBDQSBjb24gbWF0cml6IGRlIGNvcnJlbGFjaW9uZXMgKHZhcmlhYmxlcyBlc3RhbmRhcml6YWRhcykgLSBSRUNPTUVOREFETw0KcGNhX2NvciA8LSBwcmNvbXAocGNhX2RhdGEsIHNjYWxlLiA9IFRSVUUpDQpjYXQoIlByaW1lcmFzIDMgZGVzdmlhY2lvbmVzIGVzdMOhbmRhciAoQ29ycmVsYWNpb25lcyk6Iiwgcm91bmQocGNhX2NvciRzZGV2WzE6M10sIDQpLCAiXG4iKQ0KDQojIEV4cGxpY2FjacOzbiBkZSBwb3IgcXXDqSB1c2FyIGNvcnJlbGFjaW9uZXMNCmNhdCgiXG5KVVNUSUZJQ0FDScOTTiBNRVRPRE9Mw5NHSUNBOlxuIikNCmNhdCgiU2UgdXRpbGl6YSBQQ0EgYmFzYWRvIGVuIG1hdHJpeiBkZSBjb3JyZWxhY2lvbmVzIHBvcnF1ZTpcbiIpDQpjYXQoIjEuIExhcyB2YXJpYWJsZXMgdGllbmVuIGRpZmVyZW50ZXMgdW5pZGFkZXMgeSBlc2NhbGFzXG4iKQ0KY2F0KCIyLiBFdml0YSBlbCBzZXNnbyBoYWNpYSB2YXJpYWJsZXMgY29uIG1heW9yIHZhcmlhbnphXG4iKQ0KY2F0KCIzLiBQZXJtaXRlIGludGVycHJldGFjacOzbiBtw6FzIGVxdWlsaWJyYWRhIGRlIHRvZG9zIGxvcyBjb21wb25lbnRlc1xuIikNCg0KIyBVc2FyIFBDQSBkZSBjb3JyZWxhY2lvbmVzIHBhcmEgZWwgcmVzdG8gZGVsIGFuw6FsaXNpcw0KcmVzLnBjYSA8LSBwY2FfY29yDQoNCiMgQW7DoWxpc2lzIGRlIHZhcmlhbnphIGV4cGxpY2FkYQ0KZWlnLnZhbCA8LSBnZXRfZWlnZW52YWx1ZShyZXMucGNhKQ0KY2F0KCJcblZhcmlhbnphIGV4cGxpY2FkYSBwb3IgY29tcG9uZW50ZTpcbiIpDQpwcmludChlaWcudmFsWzE6bWluKDgsIG5yb3coZWlnLnZhbCkpLCBdKQ0KDQojIERldGVybWluYXIgbsO6bWVybyDDs3B0aW1vIGRlIGNvbXBvbmVudGVzIHVzYW5kbyBtw7psdGlwbGVzIGNyaXRlcmlvcw0KbnVtX2thaXNlciA8LSBzdW0oZWlnLnZhbCRlaWdlbnZhbHVlID4gMSkNCm51bV84MF9wY3QgPC0gd2hpY2goZWlnLnZhbCRjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnQgPj0gODApWzFdDQoNCmNhdCgiXG5Dcml0ZXJpb3MgcGFyYSBzZWxlY2Npw7NuIGRlIGNvbXBvbmVudGVzOlxuIikNCmNhdCgiLSBDcml0ZXJpbyBLYWlzZXIgKGVpZ2VudmFsdWUgPiAxKToiLCBudW1fa2Fpc2VyLCAiY29tcG9uZW50ZXNcbiIpDQpjYXQoIi0gQ3JpdGVyaW8gODAlIHZhcmlhbnphOiIsIG51bV84MF9wY3QsICJjb21wb25lbnRlc1xuIikNCg0KIyBTZWxlY2Npb25hciBuw7ptZXJvIGZpbmFsIGRlIGNvbXBvbmVudGVzICh1c2FyIGNyaXRlcmlvIEthaXNlciBjb21vIHByaW1hcmlvKQ0KbnVtX2NvbXBfZmluYWwgPC0gbnVtX2thaXNlcg0KY2F0KCItIFNFTEVDQ0nDk04gRklOQUw6IiwgbnVtX2NvbXBfZmluYWwsICJjb21wb25lbnRlcyBwcmluY2lwYWxlc1xuIikNCmNhdCgiLSBWYXJpYW56YSBleHBsaWNhZGEgdG90YWw6Iiwgcm91bmQoZWlnLnZhbCRjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnRbbnVtX2NvbXBfZmluYWxdLCAyKSwgIiVcbiIpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZBU0UgNTogVklTVUFMSVpBQ0lPTkVTIEFDQUTDiU1JQ0FTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuLS0tIEZBU0UgNTogQ1JFQUNJw5NOIERFIFZJU1VBTElaQUNJT05FUyAtLS1cbiIpDQoNCiMgMS4gU2NyZWUgUGxvdCBjb24gY3JpdGVyaW8gS2Fpc2VyDQpwMV9zY3JlZSA8LSBmdml6X3NjcmVlcGxvdChyZXMucGNhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmNwID0gbWluKDEwLCBucm93KGVpZy52YWwpKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNob2ljZSA9ICJlaWdlbnZhbHVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiU2NyZWUgUGxvdCAtIENyaXRlcmlvIGRlIFNlbGVjY2nDs24gZGUgQ29tcG9uZW50ZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gIkNvbXBvbmVudGVzIFByaW5jaXBhbGVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgeWxhYiA9ICJFaWdlbnZhbHVlIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiLCBsaW5ld2lkdGggPSAxLjIpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMywgY29sb3IgPSAiIzJFODZBQiIpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMywgeSA9IDEuMywgDQogICAgICAgICAgIGxhYmVsID0gIkNyaXRlcmlvIEthaXNlciAozrsgPiAxKSIsIA0KICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBmb250ZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDQpICsNCiAgdGVtYV9hY2FkZW1pY28gKw0KICBsYWJzKHN1YnRpdGxlID0gIk1ldG9kb2xvZ8OtYTogTWF0cml6IGRlIENvcnJlbGFjaW9uZXMgKFZhcmlhYmxlcyBFc3RhbmRhcml6YWRhcykiKQ0KDQpwcmludChwMV9zY3JlZSkNCg0KIyAyLiBQb3JjZW50YWplIGRlIHZhcmlhbnphIGV4cGxpY2FkYQ0KcDJfdmFyaWFuY2UgPC0gZnZpel9zY3JlZXBsb3QocmVzLnBjYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jcCA9IG1pbigxMCwgbnJvdyhlaWcudmFsKSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaG9pY2UgPSAidmFyaWFuY2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJQb3JjZW50YWplIGRlIFZhcmlhbnphIEV4cGxpY2FkYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhsYWIgPSAiQ29tcG9uZW50ZXMgUHJpbmNpcGFsZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5bGFiID0gIlBvcmNlbnRhamUgZGUgVmFyaWFuemEgKCUpIikgKw0KICBnZW9tX2xpbmUoY29sb3IgPSAiI0U3QjgwMCIsIGxpbmV3aWR0aCA9IDEuNSwgZ3JvdXAgPSAxKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yID0gIiNGQzRFMDciKSArDQogIHRlbWFfYWNhZGVtaWNvDQoNCnByaW50KHAyX3ZhcmlhbmNlKQ0KDQojIDMuIEPDrXJjdWxvIGRlIGNvcnJlbGFjaW9uZXMgKENvbnRyaWJ1Y2nDs24gZGUgdmFyaWFibGVzKQ0KcDNfY29udHJpYiA8LSBmdml6X3BjYV92YXIocmVzLnBjYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbC52YXIgPSAiY29udHJpYiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LmNvbHMgPSBjKCIjMDBBRkJCIiwgIiNFN0I4MDAiLCAiI0ZDNEUwNyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJDw61yY3VsbyBkZSBDb3JyZWxhY2lvbmVzIC0gQ29udHJpYnVjacOzbiBkZSBWYXJpYWJsZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByZXBlbCA9IFRSVUUpICsNCiAgdGVtYV9hY2FkZW1pY28gKw0KICBsYWJzKA0KICAgIHggPSBwYXN0ZTAoIlBDMSAoIiwgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzFdLCAxKSwgIiUpIiksDQogICAgeSA9IHBhc3RlMCgiUEMyICgiLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMl0sIDEpLCAiJSkiKSwNCiAgICBjb2xvciA9ICJDb250cmliICglKSINCiAgKSArDQogIGNvb3JkX2ZpeGVkKCkNCg0KcHJpbnQocDNfY29udHJpYikNCg0KIyA0LiBDw61yY3VsbyBkZSBjb3JyZWxhY2lvbmVzIChDYWxpZGFkIGRlIHJlcHJlc2VudGFjacOzbikNCnA0X2NvczIgPC0gZnZpel9wY2FfdmFyKHJlcy5wY2EsIA0KICAgICAgICAgICAgICAgICAgICAgICBjb2wudmFyID0gImNvczIiLA0KICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiI0ZGRkZGRiIsICIjMkU4NkFCIiwgIiMxQjM2NUQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAiQ2FsaWRhZCBkZSBSZXByZXNlbnRhY2nDs24gZGUgVmFyaWFibGVzIChDb3PCsikiLA0KICAgICAgICAgICAgICAgICAgICAgICByZXBlbCA9IFRSVUUpICsNCiAgdGVtYV9hY2FkZW1pY28gKw0KICBsYWJzKA0KICAgIHggPSBwYXN0ZTAoIlBDMSAoIiwgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzFdLCAxKSwgIiUpIiksDQogICAgeSA9IHBhc3RlMCgiUEMyICgiLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMl0sIDEpLCAiJSkiKSwNCiAgICBjb2xvciA9ICJDb3PCsiINCiAgKSArDQogIGNvb3JkX2ZpeGVkKCkgKw0KICAjIEPDrXJjdWxvIHVuaXRhcmlvIGRlIHJlZmVyZW5jaWENCiAgYW5ub3RhdGUoInBhdGgiLA0KICAgICAgICAgICB4ID0gY29zKHNlcSgwLCAyKnBpLCBsZW5ndGgub3V0ID0gMTAwKSksDQogICAgICAgICAgIHkgPSBzaW4oc2VxKDAsIDIqcGksIGxlbmd0aC5vdXQgPSAxMDApKSwNCiAgICAgICAgICAgY29sb3IgPSAiZ3JheTcwIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGluZXdpZHRoID0gMC44KQ0KDQpwcmludChwNF9jb3MyKQ0KDQojIDUuIEJpcGxvdCAodmFyaWFibGVzICsgaW5kaXZpZHVvcykNCmlmKCFpcy5udWxsKHRpcG9fY29tdW5hKSkgew0KICBwNV9iaXBsb3QgPC0gZnZpel9wY2FfYmlwbG90KHJlcy5wY2EsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbS5pbmQgPSAicG9pbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzaXplID0gMi41LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEuaW5kID0gMC43LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sLnZhciA9ICJibGFjayIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYS52YXIgPSAwLjgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBlbCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHNpemUgPSAzLjUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYWJpbGxhZ2UgPSB0aXBvX2NvbXVuYSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZEVsbGlwc2VzID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGxpcHNlLmxldmVsID0gMC45NSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsbGlwc2UuYWxwaGEgPSAwLjEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICJCaXBsb3QgUENBIC0gQ29tdW5hcyBwb3IgVGlwbyIpICsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3Jlc19jb211bmEsIG5hbWUgPSAiVGlwbyBDb211bmEiKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3Jlc19jb211bmEsIG5hbWUgPSAiVGlwbyBDb211bmEiKSArDQogICAgdGVtYV9hY2FkZW1pY28gKw0KICAgIGxhYnMoDQogICAgICB4ID0gcGFzdGUwKCJQQzEgKCIsIHJvdW5kKGVpZy52YWwkdmFyaWFuY2UucGVyY2VudFsxXSwgMSksICIlKSIpLA0KICAgICAgeSA9IHBhc3RlMCgiUEMyICgiLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMl0sIDEpLCAiJSkiKQ0KICAgICkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArDQogICAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDQpKSkNCn0gZWxzZSB7DQogIHA1X2JpcGxvdCA8LSBmdml6X3BjYV9iaXBsb3QocmVzLnBjYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tLmluZCA9ICJwb2ludCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2wudmFyID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhLmluZCA9IDAuNiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGVsID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIkJpcGxvdCBQQ0EgLSBWYXJpYWJsZXMgeSBDb211bmFzIikgKw0KICAgIHRlbWFfYWNhZGVtaWNvICsNCiAgICBsYWJzKA0KICAgICAgeCA9IHBhc3RlMCgiUEMxICgiLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMV0sIDEpLCAiJSkiKSwNCiAgICAgIHkgPSBwYXN0ZTAoIlBDMiAoIiwgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzJdLCAxKSwgIiUpIikNCiAgICApDQp9DQoNCnByaW50KHA1X2JpcGxvdCkNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSA2OiBBTsOBTElTSVMgREUgQ0xVU1RFUlMgUk9CVVNUTw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbi0tLSBGQVNFIDY6IEFOw4FMSVNJUyBERSBDTFVTVEVSUyAtLS1cbiIpDQoNCiMgUHJlcGFyYXIgZGF0b3MgcGFyYSBjbHVzdGVyaW5nICh1c2FyIGNvbXBvbmVudGVzIHByaW5jaXBhbGVzKQ0KcGNhX3Njb3JlcyA8LSByZXMucGNhJHhbLCAxOm1pbihudW1fY29tcF9maW5hbCwgNCldDQoNCiMgTcOJVE9ETyAxOiBEZXRlcm1pbmFyIG7Dum1lcm8gw7NwdGltbyB1c2FuZG8gbcO6bHRpcGxlcyBjcml0ZXJpb3MNCnNldC5zZWVkKDEyMykNCg0KIyBDcml0ZXJpbyAxOiBNw6l0b2RvIGRlbCBDb2RvIChXaXRoaW4gU3VtIG9mIFNxdWFyZXMpDQp3c3MgPC0gc2FwcGx5KDE6OCwgZnVuY3Rpb24oaykgew0KICBrbWVhbnMocGNhX3Njb3JlcywgaywgbnN0YXJ0ID0gMjUsIGl0ZXIubWF4ID0gMTAwKSR0b3Qud2l0aGluc3MNCn0pDQoNCiMgQ3JpdGVyaW8gMjogQ29lZmljaWVudGUgZGUgU2lsdWV0YSBwcm9tZWRpbw0KYXZnX3NpbCA8LSBzYXBwbHkoMjo4LCBmdW5jdGlvbihrKSB7DQogIGttX3RlbXAgPC0ga21lYW5zKHBjYV9zY29yZXMsIGssIG5zdGFydCA9IDI1KQ0KICBzaWxfdGVtcCA8LSBzaWxob3VldHRlKGttX3RlbXAkY2x1c3RlciwgZGlzdChwY2Ffc2NvcmVzKSkNCiAgbWVhbihzaWxfdGVtcFssIDNdKQ0KfSkNCg0KIyBDcml0ZXJpbyAzOiBHYXAgU3RhdGlzdGljDQpnYXBfc3RhdCA8LSBjbHVzR2FwKHBjYV9zY29yZXMsIEZVTiA9IGttZWFucywgbnN0YXJ0ID0gMjUsIEsubWF4ID0gOCwgQiA9IDUwKQ0KDQojIFZpc3VhbGl6YXIgbcOpdG9kb3MgZGUgc2VsZWNjacOzbg0KcF9lbGJvdyA8LSBkYXRhLmZyYW1lKGsgPSAxOjgsIHdzcyA9IHdzcykgJT4lDQogIGdncGxvdChhZXMoeCA9IGssIHkgPSB3c3MpKSArDQogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjIsIGNvbG9yID0gIiMyRTg2QUIiKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yID0gIiNGQzRFMDciKSArDQogIGxhYnModGl0bGUgPSAiTcOpdG9kbyBkZWwgQ29kbyIsDQogICAgICAgeCA9ICJOw7ptZXJvIGRlIENsdXN0ZXJzIChrKSIsIA0KICAgICAgIHkgPSAiV1NTIFRvdGFsIikgKw0KICB0ZW1hX2FjYWRlbWljbyArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjgpDQoNCnBfc2lsaG91ZXR0ZSA8LSBkYXRhLmZyYW1lKGsgPSAyOjgsIGF2Z19zaWwgPSBhdmdfc2lsKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gaywgeSA9IGF2Z19zaWwpKSArDQogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjIsIGNvbG9yID0gIiNFN0I4MDAiKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yID0gIiNGQzRFMDciKSArDQogIGxhYnModGl0bGUgPSAiTcOpdG9kbyBkZSBsYSBTaWx1ZXRhIiwNCiAgICAgICB4ID0gIk7Dum1lcm8gZGUgQ2x1c3RlcnMgKGspIiwgDQogICAgICAgeSA9ICJDb2VmaWNpZW50ZSBkZSBTaWx1ZXRhIFByb21lZGlvIikgKw0KICB0ZW1hX2FjYWRlbWljbyArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAyOjgpDQoNCnBfZ2FwIDwtIGZ2aXpfZ2FwX3N0YXQoZ2FwX3N0YXQpICsNCiAgbGFicyh0aXRsZSA9ICJHYXAgU3RhdGlzdGljIikgKw0KICB0ZW1hX2FjYWRlbWljbw0KDQojIENvbWJpbmFyIGdyw6FmaWNvcyBkZSBzZWxlY2Npw7NuDQpncmlkLmFycmFuZ2UocF9lbGJvdywgcF9zaWxob3VldHRlLCBwX2dhcCwgDQogICAgICAgICAgICAgbmNvbCA9IDMsIA0KICAgICAgICAgICAgIHRvcCA9IHRleHRHcm9iKCJNw6l0b2RvcyBkZSBTZWxlY2Npw7NuIGRlbCBOw7ptZXJvIMOTcHRpbW8gZGUgQ2x1c3RlcnMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGdwID0gZ3Bhcihmb250c2l6ZSA9IDE2LCBmb250ZmFjZSA9ICJib2xkIikpKQ0KDQojIERldGVybWluYXIgbsO6bWVybyDDs3B0aW1vDQprX2VsYm93IDwtIHdoaWNoLm1pbihkaWZmKGRpZmYod3NzKSkpICsgMQ0Ka19zaWxob3VldHRlIDwtIHdoaWNoLm1heChhdmdfc2lsKSArIDENCmtfZ2FwIDwtIG1heFNFKGdhcF9zdGF0JFRhYlssICJnYXAiXSwgZ2FwX3N0YXQkVGFiWywgIlNFLnNpbSJdKQ0KDQpjYXQoIlJlc3VsdGFkb3MgZGUgbcOpdG9kb3MgZGUgc2VsZWNjacOzbjpcbiIpDQpjYXQoIi0gTcOpdG9kbyBkZWwgQ29kbzoiLCBrX2VsYm93LCAiY2x1c3RlcnNcbiIpDQpjYXQoIi0gTcOpdG9kbyBTaWxob3VldHRlOiIsIGtfc2lsaG91ZXR0ZSwgImNsdXN0ZXJzXG4iKQ0KY2F0KCItIEdhcCBTdGF0aXN0aWM6Iiwga19nYXAsICJjbHVzdGVyc1xuIikNCg0KIyBTZWxlY2Npb25hciBuw7ptZXJvIGZpbmFsICh1c2FyIHNpbGhvdWV0dGUgY29tbyBjcml0ZXJpbyBwcmluY2lwYWwpDQpudW1fY2x1c3RlcnMgPC0ga19zaWxob3VldHRlDQpjYXQoIi0gU0VMRUNDScOTTiBGSU5BTDoiLCBudW1fY2x1c3RlcnMsICJjbHVzdGVyc1xuIikNCg0KIyBNw4lUT0RPIDI6IEVqZWN1dGFyIGNsdXN0ZXJpbmcgay1tZWFucyBkZWZpbml0aXZvDQprbV9maW5hbCA8LSBrbWVhbnMocGNhX3Njb3JlcywgY2VudGVycyA9IG51bV9jbHVzdGVycywgbnN0YXJ0ID0gNTAsIGl0ZXIubWF4ID0gMTAwKQ0KDQojIEV2YWx1YXIgY2FsaWRhZCBkZWwgY2x1c3RlcmluZw0KYmV0d2Vlbl9zc19wY3QgPC0gcm91bmQoa21fZmluYWwkYmV0d2VlbnNzIC8ga21fZmluYWwkdG90c3MgKiAxMDAsIDIpDQpzaWxfZmluYWwgPC0gc2lsaG91ZXR0ZShrbV9maW5hbCRjbHVzdGVyLCBkaXN0KHBjYV9zY29yZXMpKQ0Kc2lsX2F2Z19maW5hbCA8LSByb3VuZChtZWFuKHNpbF9maW5hbFssIDNdKSwgMykNCg0KY2F0KCJcbkNhbGlkYWQgZGVsIGNsdXN0ZXJpbmc6XG4iKQ0KY2F0KCItIFZhcmlhbnphIGV4cGxpY2FkYSBlbnRyZSBjbHVzdGVyczoiLCBiZXR3ZWVuX3NzX3BjdCwgIiVcbiIpDQpjYXQoIi0gQ29lZmljaWVudGUgZGUgc2lsdWV0YSBwcm9tZWRpbzoiLCBzaWxfYXZnX2ZpbmFsLCAiXG4iKQ0KY2F0KCItIEludGVycHJldGFjacOzbiBzaWx1ZXRhOiIsIA0KICAgIGNhc2Vfd2hlbigNCiAgICAgIHNpbF9hdmdfZmluYWwgPiAwLjcgfiAiRXN0cnVjdHVyYSBmdWVydGUiLA0KICAgICAgc2lsX2F2Z19maW5hbCA+IDAuNSB+ICJFc3RydWN0dXJhIG1vZGVyYWRhIiwNCiAgICAgIHNpbF9hdmdfZmluYWwgPiAwLjI1IH4gIkVzdHJ1Y3R1cmEgZMOpYmlsIiwNCiAgICAgIFRSVUUgfiAiU2luIGVzdHJ1Y3R1cmEgY2xhcmEiDQogICAgKSwgIlxuIikNCg0KIyBBZ3JlZ2FyIGNsdXN0ZXJzIGFsIGRhdGFzZXQgb3JpZ2luYWwNCmluZGljZXNfdmFsaWRvcyA8LSBhcy5udW1lcmljKHJvd25hbWVzKHBjYV9kYXRhKSkNCnRhYmxhX21hZXN0cmEkY2x1c3Rlcl9wY2EgPC0gTkENCnRhYmxhX21hZXN0cmEkY2x1c3Rlcl9wY2FbaW5kaWNlc192YWxpZG9zXSA8LSBhcy5mYWN0b3Ioa21fZmluYWwkY2x1c3RlcikNCg0KIyBNw4lUT0RPIDM6IFZpc3VhbGl6YWNpb25lcyBkZSBjbHVzdGVycw0KY2F0KCJcbkNyZWFuZG8gdmlzdWFsaXphY2lvbmVzIGRlIGNsdXN0ZXJzLi4uXG4iKQ0KDQojIEdyw6FmaWNvIHByaW5jaXBhbCBkZSBjbHVzdGVycw0KcF9jbHVzdGVycyA8LSBmdml6X2NsdXN0ZXIoa21fZmluYWwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gcGNhX3Njb3Jlc1ssIDE6Ml0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tID0gInBvaW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzaXplID0gMi41LA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlbGxpcHNlLnR5cGUgPSAiY29udmV4IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBjKCIjRTMxQTFDIiwgIiMxRjc4QjQiLCAiIzMzQTAyQyIsICIjRkY3RjAwIiwgIiM2QTNEOUEiKVsxOm51bV9jbHVzdGVyc10sDQogICAgICAgICAgICAgICAgICAgICAgICAgIGVsbGlwc2UuYWxwaGEgPSAwLjIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gIkNsdXN0ZXJzIGRlIENvbXVuYXMgZW4gRXNwYWNpbyBQQ0EiKSArDQogIHRlbWFfYWNhZGVtaWNvICsNCiAgbGFicygNCiAgICB4ID0gcGFzdGUwKCJQQzEgKCIsIHJvdW5kKGVpZy52YWwkdmFyaWFuY2UucGVyY2VudFsxXSwgMSksICIlKSIpLA0KICAgIHkgPSBwYXN0ZTAoIlBDMiAoIiwgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzJdLCAxKSwgIiUpIiksDQogICAgY29sb3IgPSAiQ2x1c3RlciIsIGZpbGwgPSAiQ2x1c3RlciINCiAgKQ0KDQpwcmludChwX2NsdXN0ZXJzKQ0KDQojIEFuw6FsaXNpcyBkZSBzaWx1ZXRhIGRldGFsbGFkbw0KcF9zaWxfZGV0YWlsIDwtIGZ2aXpfc2lsaG91ZXR0ZShzaWxfZmluYWwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBjKCIjRTMxQTFDIiwgIiMxRjc4QjQiLCAiIzMzQTAyQyIsICIjRkY3RjAwIiwgIiM2QTNEOUEiKVsxOm51bV9jbHVzdGVyc10pICsNCiAgbGFicyh0aXRsZSA9ICJBbsOhbGlzaXMgZGUgU2lsdWV0YSBwb3IgQ2x1c3RlciIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZSgiQ29lZmljaWVudGUgcHJvbWVkaW86Iiwgc2lsX2F2Z19maW5hbCkpICsNCiAgdGVtYV9hY2FkZW1pY28NCg0KcHJpbnQocF9zaWxfZGV0YWlsKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGQVNFIDc6IElOVEVSUFJFVEFDScOTTiBZIENBUkFDVEVSSVpBQ0nDk04NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG4tLS0gRkFTRSA3OiBDQVJBQ1RFUklaQUNJw5NOIERFIENMVVNURVJTIC0tLVxuIikNCg0KIyBBbsOhbGlzaXMgZXN0YWTDrXN0aWNvIHBvciBjbHVzdGVyDQpjbHVzdGVyX3N0YXRzIDwtIHRhYmxhX21hZXN0cmEgJT4lDQogIGZpbHRlcighaXMubmEoY2x1c3Rlcl9wY2EpKSAlPiUNCiAgZ3JvdXBfYnkoY2x1c3Rlcl9wY2EpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgbl9jb211bmFzID0gbigpLA0KICAgIGFjcm9zcyhhbnlfb2YocGNhX3ZhcnMpLCANCiAgICAgICAgICAgbGlzdChtZWRpYSA9IH4gcm91bmQobWVhbigueCwgbmEucm0gPSBUUlVFKSwgMyksDQogICAgICAgICAgICAgICAgbWVkaWFuYSA9IH4gcm91bmQobWVkaWFuKC54LCBuYS5ybSA9IFRSVUUpLCAzKSwNCiAgICAgICAgICAgICAgICBkZXN2X3N0ZCA9IH4gcm91bmQoc2QoLngsIG5hLnJtID0gVFJVRSksIDMpKSwgDQogICAgICAgICAgIC5uYW1lcyA9ICJ7LmNvbH1fey5mbn0iKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyBNb3N0cmFyIGNhcmFjdGVyaXphY2nDs24gYsOhc2ljYQ0KY2x1c3Rlcl9iYXNpY28gPC0gdGFibGFfbWFlc3RyYSAlPiUNCiAgZmlsdGVyKCFpcy5uYShjbHVzdGVyX3BjYSkpICU+JQ0KICBncm91cF9ieShjbHVzdGVyX3BjYSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBuX2NvbXVuYXMgPSBuKCksDQogICAgYWNyb3NzKGFueV9vZihjKCJuX3Byb3llY3RvcyIsICJIX2NmZyIsICJIX2FjdG9yIiwgInJhdGlvX21lZGlhIikpLCANCiAgICAgICAgICAgfiByb3VuZChtZWFuKC54LCBuYS5ybSA9IFRSVUUpLCAzKSwgLm5hbWVzID0gInByb21lZGlvX3suY29sfSIpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpjYXQoIkNhcmFjdGVyaXphY2nDs24gYsOhc2ljYSBwb3IgY2x1c3RlcjpcbiIpDQpwcmludChjbHVzdGVyX2Jhc2ljbykNCg0KIyBBbsOhbGlzaXMgZGUgc2NvcmVzIFBDQSBwb3IgY2x1c3Rlcg0KcGNhX3Bvcl9jbHVzdGVyIDwtIGRhdGEuZnJhbWUoDQogIGNsdXN0ZXIgPSBrbV9maW5hbCRjbHVzdGVyLA0KICBQQzEgPSBwY2Ffc2NvcmVzWywgMV0sDQogIFBDMiA9IHBjYV9zY29yZXNbLCAyXQ0KKSAlPiUNCiAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBuID0gbigpLA0KICAgIFBDMV9wcm9tZWRpbyA9IHJvdW5kKG1lYW4oUEMxKSwgMyksDQogICAgUEMyX3Byb21lZGlvID0gcm91bmQobWVhbihQQzIpLCAzKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KY2F0KCJcblBvc2ljaW9uYW1pZW50byBkZSBjbHVzdGVycyBlbiBlc3BhY2lvIFBDQTpcbiIpDQpwcmludChwY2FfcG9yX2NsdXN0ZXIpDQoNCiMgSW50ZXJwcmV0YWNpw7NuIGNvbmNlcHR1YWwNCmNhdCgiXG5JTlRFUlBSRVRBQ0nDk04gREUgQ0xVU1RFUlM6XG4iKQ0KZm9yKGkgaW4gMTpudW1fY2x1c3RlcnMpIHsNCiAgY2x1c3Rlcl9kYXRhIDwtIHRhYmxhX21hZXN0cmEgJT4lIGZpbHRlcihjbHVzdGVyX3BjYSA9PSBpKQ0KICBuX2NvbXVuYXMgPC0gbnJvdyhjbHVzdGVyX2RhdGEpDQogIHBjMV9wb3MgPC0gcGNhX3Bvcl9jbHVzdGVyJFBDMV9wcm9tZWRpb1tpXQ0KICBwYzJfcG9zIDwtIHBjYV9wb3JfY2x1c3RlciRQQzJfcHJvbWVkaW9baV0NCiAgDQogIGNhdCgiXG4tLS0gQ0xVU1RFUiIsIGksICItLS1cbiIpDQogIGNhdCgiVGFtYcOxbzoiLCBuX2NvbXVuYXMsICJjb211bmFzICgiLCANCiAgICAgIHJvdW5kKG5fY29tdW5hcy9zdW0oIWlzLm5hKHRhYmxhX21hZXN0cmEkY2x1c3Rlcl9wY2EpKSoxMDAsIDEpLCAiJSlcbiIpDQogIGNhdCgiUG9zaWNpw7NuIFBDMToiLCBwYzFfcG9zLCAiKCIsIA0KICAgICAgaWZlbHNlKHBjMV9wb3MgPiAwLCAidmFsb3JlcyBhbHRvcyIsICJ2YWxvcmVzIGJham9zIiksICIpXG4iKQ0KICBjYXQoIlBvc2ljacOzbiBQQzI6IiwgcGMyX3BvcywgIigiLCANCiAgICAgIGlmZWxzZShwYzJfcG9zID4gMCwgInZhbG9yZXMgYWx0b3MiLCAidmFsb3JlcyBiYWpvcyIpLCAiKVxuIikNCiAgDQogICMgQ2FyYWN0ZXLDrXN0aWNhcyBkaXN0aW50aXZhcyAoYWRhcHRhciBzZWfDum4gdmFyaWFibGVzIGRpc3BvbmlibGVzKQ0KICBpZigibl9wcm95ZWN0b3MiICVpbiUgbmFtZXMoY2x1c3Rlcl9kYXRhKSkgew0KICAgIHByb2pfcHJvbSA8LSByb3VuZChtZWFuKGNsdXN0ZXJfZGF0YSRuX3Byb3llY3RvcywgbmEucm0gPSBUUlVFKSwgMikNCiAgICBjYXQoIlByb21lZGlvIHByb3llY3RvczoiLCBwcm9qX3Byb20sICJcbiIpDQogIH0NCn0NCg0KIyBSZWxhY2nDs24gY29uIHRpcG8gZGUgY29tdW5hIChzaSBkaXNwb25pYmxlKQ0KaWYoIWlzLm51bGwodGlwb19jb211bmEpKSB7DQogIGNhdCgiXG4tLS0gUkVMQUNJw5NOIENPTiBUSVBPIERFIENPTVVOQSAtLS1cbiIpDQogIA0KICB0YWJsYV9jcnV6YWRhIDwtIHRhYmxhX21hZXN0cmEgJT4lDQogICAgZmlsdGVyKCFpcy5uYShjbHVzdGVyX3BjYSksICFpcy5uYShUaXBvX0NvbXVuYSkpICU+JQ0KICAgIGNvdW50KFRpcG9fQ29tdW5hLCBjbHVzdGVyX3BjYSkgJT4lDQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNsdXN0ZXJfcGNhLCB2YWx1ZXNfZnJvbSA9IG4sIA0KICAgICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCwgbmFtZXNfcHJlZml4ID0gIkNsdXN0ZXJfIikNCiAgDQogIHByaW50KHRhYmxhX2NydXphZGEpDQogIA0KICAjIFRlc3QgZGUgaW5kZXBlbmRlbmNpYQ0KICBpZihucm93KHRhYmxhX2NydXphZGEpID4gMSkgew0KICAgIGNoaV90ZXN0IDwtIGNoaXNxLnRlc3QoYXMubWF0cml4KHRhYmxhX2NydXphZGFbLCAtMV0pKQ0KICAgIGNhdCgiXG5UZXN0IENoaS1jdWFkcmFkbzpcbiIpDQogICAgY2F0KCJDaGnCsiA9Iiwgcm91bmQoY2hpX3Rlc3Qkc3RhdGlzdGljLCAzKSwgDQogICAgICAgICIsIHAtdmFsb3IgPSIsIGZvcm1hdC5wdmFsKGNoaV90ZXN0JHAudmFsdWUpLCAiXG4iKQ0KICAgIGNhdCgiQXNvY2lhY2nDs246IiwgaWZlbHNlKGNoaV90ZXN0JHAudmFsdWUgPCAwLjA1LCAiU0lHTklGSUNBVElWQSIsICJOTyBTSUdOSUZJQ0FUSVZBIiksICJcbiIpDQogIH0NCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSA4OiBBTsOBTElTSVMgREUgQ0FSR0FTIFkgQ09NUE9ORU5URVMNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG4tLS0gRkFTRSA4OiBJTlRFUlBSRVRBQ0nDk04gREUgQ09NUE9ORU5URVMgLS0tXG4iKQ0KDQojIEV4dHJhZXIgeSBhbmFsaXphciBjYXJnYXMgKGxvYWRpbmdzKQ0KbG9hZGluZ3NfbWF0cml4IDwtIHJlcy5wY2Ekcm90YXRpb25bLCAxOm51bV9jb21wX2ZpbmFsXQ0KDQpjYXQoIkNBUkdBUyBERSBWQVJJQUJMRVMgRU4gQ09NUE9ORU5URVMgUFJJTkNJUEFMRVM6XG4iKQ0KZm9yKGkgaW4gMTpudW1fY29tcF9maW5hbCkgew0KICBjYXQoIlxuLS0tIENPTVBPTkVOVEUgUFJJTkNJUEFMIiwgaSwgIi0tLVxuIikNCiAgY2F0KCJWYXJpYW56YSBleHBsaWNhZGE6Iiwgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50W2ldLCAyKSwgIiVcbiIpDQogIA0KICBjYXJnYXMgPC0gbG9hZGluZ3NfbWF0cml4WywgaV0NCiAgY2FyZ2FzX29yZGVuYWRhcyA8LSBzb3J0KGFicyhjYXJnYXMpLCBkZWNyZWFzaW5nID0gVFJVRSkNCiAgDQogICMgVmFyaWFibGVzIGNvbiBjYXJnYXMgbcOhcyBhbHRhcw0KICB2YXJzX2ltcG9ydGFudGVzIDwtIG5hbWVzKGNhcmdhc19vcmRlbmFkYXNbMTptaW4oNSwgbGVuZ3RoKGNhcmdhc19vcmRlbmFkYXMpKV0pDQogIA0KICBjYXQoIlZhcmlhYmxlcyBtw6FzIGluZmx1eWVudGVzOlxuIikNCiAgZm9yKHZhciBpbiB2YXJzX2ltcG9ydGFudGVzKSB7DQogICAgY2FyZ2FfdmFsIDwtIGNhcmdhc1t2YXJdDQogICAgY2F0KHNwcmludGYoIiAgJS0yNXM6ICU2LjNmICglcylcbiIsIA0KICAgICAgICAgICAgICAgIHZhciwgY2FyZ2FfdmFsLCANCiAgICAgICAgICAgICAgICBpZmVsc2UoY2FyZ2FfdmFsID4gMCwgInBvc2l0aXZhIiwgIm5lZ2F0aXZhIikpKQ0KICB9DQogIA0KICAjIEludGVycHJldGFjacOzbiBhdXRvbcOhdGljYSBiYXNhZGEgZW4gdmFyaWFibGVzIGRvbWluYW50ZXMNCiAgdmFyc19wb3NpdGl2YXMgPC0gbmFtZXMoY2FyZ2FzW2NhcmdhcyA+IDAuM10pDQogIHZhcnNfbmVnYXRpdmFzIDwtIG5hbWVzKGNhcmdhc1tjYXJnYXMgPCAtMC4zXSkNCiAgDQogIGNhdCgiSW50ZXJwcmV0YWNpw7NuIHN1Z2VyaWRhOlxuIikNCiAgaWYobGVuZ3RoKHZhcnNfcG9zaXRpdmFzKSA+IDApIHsNCiAgICBjYXQoIiAgRGltZW5zacOzbiBQT1NJVElWQToiLCBwYXN0ZSh2YXJzX3Bvc2l0aXZhc1sxOm1pbigzLCBsZW5ndGgodmFyc19wb3NpdGl2YXMpKV0sIGNvbGxhcHNlID0gIiwgIiksICJcbiIpDQogIH0NCiAgaWYobGVuZ3RoKHZhcnNfbmVnYXRpdmFzKSA+IDApIHsNCiAgICBjYXQoIiAgRGltZW5zacOzbiBORUdBVElWQToiLCBwYXN0ZSh2YXJzX25lZ2F0aXZhc1sxOm1pbigzLCBsZW5ndGgodmFyc19uZWdhdGl2YXMpKV0sIGNvbGxhcHNlID0gIiwgIiksICJcbiIpDQogIH0NCn0NCg0KIyBDcmVhciBoZWF0bWFwIGRlIGNhcmdhcw0KaWYobnVtX2NvbXBfZmluYWwgPj0gMikgew0KICBwaGVhdG1hcChsb2FkaW5nc19tYXRyaXgsIA0KICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLCANCiAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsDQogICAgICAgICAgIG1haW4gPSAiQ2FyZ2FzIGRlIFZhcmlhYmxlcyBlbiBDb21wb25lbnRlcyBQcmluY2lwYWxlc1xuUHJveWVjdG9zIEFDQSAtIEVzdGFkbyBNw6lyaWRhIiwNCiAgICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoIiMwNTMwNjEiLCAiIzIxNjZBQyIsICIjNDM5M0MzIiwgIiM5MkM1REUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIjRDFFNUYwIiwgIiNGRkZGRkYiLCAiI0ZEREJDNyIsICIjRjRBNTgyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiI0Q2NjA0RCIsICIjQjIxODJCIiwgIiM2NzAwMUYiKSkoMTAwKSwNCiAgICAgICAgICAgYnJlYWtzID0gc2VxKC0xLCAxLCBsZW5ndGgub3V0ID0gMTAxKSwNCiAgICAgICAgICAgZGlzcGxheV9udW1iZXJzID0gVFJVRSwNCiAgICAgICAgICAgbnVtYmVyX2Zvcm1hdCA9ICIlLjJmIiwNCiAgICAgICAgICAgZm9udHNpemUgPSAxMCwNCiAgICAgICAgICAgY2VsbHdpZHRoID0gNDAsDQogICAgICAgICAgIGNlbGxoZWlnaHQgPSAxNSkNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSA5OiBFWFBPUlRBQ0nDk04gWSBUQUJMQVMgQUNBRMOJTUlDQVMNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG4tLS0gRkFTRSA5OiBDUkVBQ0nDk04gREUgVEFCTEFTIFBBUkEgTU9OT0dSQUbDjUEgLS0tXG4iKQ0KDQojIFRBQkxBIDE6IFJlc3VtZW4gbWV0b2RvbMOzZ2ljbyBkZWwgUENBDQp0YWJsYV9tZXRvZG9sb2dpYSA8LSBkYXRhLmZyYW1lKA0KICBBc3BlY3RvID0gYygNCiAgICAiVmFyaWFibGVzIGFuYWxpemFkYXMiLA0KICAgICJDb211bmFzIGluY2x1aWRhcyIsDQogICAgIk3DqXRvZG8gUENBIiwNCiAgICAiTWF0cml6IHV0aWxpemFkYSIsIA0KICAgICJDcml0ZXJpbyBzZWxlY2Npw7NuIiwNCiAgICAiQ29tcG9uZW50ZXMgcmV0ZW5pZG9zIiwNCiAgICAiVmFyaWFuemEgUEMxICglKSIsDQogICAgIlZhcmlhbnphIFBDMiAoJSkiLA0KICAgICJWYXJpYW56YSBhY3VtdWxhZGEgKCUpIiwNCiAgICAiw41uZGljZSBLTU8iLA0KICAgICJUZXN0IEJhcnRsZXR0IChwLXZhbG9yKSIsDQogICAgIkNsdXN0ZXJzIGlkZW50aWZpY2Fkb3MiLA0KICAgICJNw6l0b2RvIGNsdXN0ZXJpbmciLA0KICAgICJDYWxpZGFkIGNsdXN0ZXJpbmcgKHNpbHVldGEpIg0KICApLA0KICBSZXN1bHRhZG8gPSBjKA0KICAgIGxlbmd0aChwY2FfdmFycyksDQogICAgbnJvdyhwY2FfZGF0YSksDQogICAgInByY29tcCgpIGNvbiBzY2FsZT1UUlVFIiwNCiAgICAiQ29ycmVsYWNpb25lcyAoZXN0YW5kYXJpemFkYSkiLA0KICAgICJLYWlzZXIgKGVpZ2VudmFsdWUgPiAxKSIsDQogICAgbnVtX2NvbXBfZmluYWwsDQogICAgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzFdLCAyKSwNCiAgICByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMl0sIDIpLA0KICAgIHJvdW5kKHN1bShlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMTpudW1fY29tcF9maW5hbF0pLCAyKSwNCiAgICBwYXN0ZTAocm91bmQoa21vX3ZhbHVlLCAzKSwgIiAoIiwga21vX2ludGVycHJldGF0aW9uLCAiKSIpLA0KICAgIGZvcm1hdC5wdmFsKGJhcnRsZXR0X3AsIGRpZ2l0cyA9IDMpLA0KICAgIG51bV9jbHVzdGVycywNCiAgICAiSy1tZWFucyArIGNyaXRlcmlvIHNpbHVldGEiLA0KICAgIHBhc3RlMChzaWxfYXZnX2ZpbmFsLCAiICgiLCANCiAgICAgICAgICAgY2FzZV93aGVuKHNpbF9hdmdfZmluYWwgPiAwLjUgfiAiTW9kZXJhZGEiLCANCiAgICAgICAgICAgICAgICAgICAgc2lsX2F2Z19maW5hbCA+IDAuMjUgfiAiRMOpYmlsIiwgDQogICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiUG9icmUiKSwgIikiKQ0KICApDQopDQoNCiMgQ3JlYXIgb2JqZXRvIGthYmxlIHBhcmEgVGFibGEgMQ0KdGFibGExX2thYmxlIDwtIGthYmxlKHRhYmxhX21ldG9kb2xvZ2lhLA0KICAgICAgY2FwdGlvbiA9ICJUYWJsYTogUmVzdW1lbiBNZXRvZG9sw7NnaWNvIGRlbCBBbsOhbGlzaXMgZGUgQ29tcG9uZW50ZXMgUHJpbmNpcGFsZXMiLA0KICAgICAgY29sLm5hbWVzID0gYygiQXNwZWN0byBNZXRvZG9sw7NnaWNvIiwgIlJlc3VsdGFkbyIpLA0KICAgICAgYWxpZ24gPSBjKCJsIiwgImMiKSkgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lDQogIHJvd19zcGVjKGMoNiwgOSwgMTIpLCBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjZTZmM2ZmIikNCg0KIyBUQUJMQSAyOiBWYXJpYW56YSBleHBsaWNhZGEgcG9yIGNvbXBvbmVudGVzDQp0YWJsYV92YXJpYW56YSA8LSBlaWcudmFsICU+JQ0KICBoZWFkKG1pbig4LCBucm93KGVpZy52YWwpKSkgJT4lDQogIG11dGF0ZSgNCiAgICBDb21wb25lbnRlID0gcGFzdGUoIlBDIiwgMTpucm93KC4pLCBzZXAgPSAiIiksDQogICAgQ3JpdGVyaW9fS2Fpc2VyID0gaWZlbHNlKGVpZ2VudmFsdWUgPiAxLCAiUkVURU5FUiIsICJkZXNjYXJ0YXIiKSwNCiAgICAuYmVmb3JlID0gMQ0KICApICU+JQ0KICBzZWxlY3QoQ29tcG9uZW50ZSwgZWlnZW52YWx1ZSwgdmFyaWFuY2UucGVyY2VudCwgDQogICAgICAgICBjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnQsIENyaXRlcmlvX0thaXNlcikNCg0KIyBDcmVhciBvYmpldG8ga2FibGUgcGFyYSBUYWJsYSAyDQp0YWJsYTJfa2FibGUgPC0ga2FibGUodGFibGFfdmFyaWFuemEsDQogICAgICBjYXB0aW9uID0gIlRhYmxhOiBWYXJpYW56YSBFeHBsaWNhZGEgcG9yIENvbXBvbmVudGVzIFByaW5jaXBhbGVzIiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIkNvbXBvbmVudGUiLCAiRWlnZW52YWx1ZSIsICIlIFZhcmlhbnphIiwgDQogICAgICAgICAgICAgICAgICAgIiUgQWN1bXVsYWRvIiwgIkNyaXRlcmlvIEthaXNlciIpLA0KICAgICAgZGlnaXRzID0gMykgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpICU+JQ0KICByb3dfc3BlYyh3aGljaCh0YWJsYV92YXJpYW56YSRDcml0ZXJpb19LYWlzZXIgPT0gIlJFVEVORVIiKSwgDQogICAgICAgICAgIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNlNmYyZTYiKQ0KDQojIFRBQkxBIDM6IENhcmdhcyBwcmluY2lwYWxlcyBkZSB2YXJpYWJsZXMNCnRhYmxhX2NhcmdhcyA8LSBsb2FkaW5nc19tYXRyaXggJT4lDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUNCiAgbXV0YXRlKFZhcmlhYmxlID0gcm93bmFtZXMoLiksIC5iZWZvcmUgPSAxKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFicyhQQzEpKSkgJT4lDQogIG11dGF0ZSgNCiAgICBhY3Jvc3Moc3RhcnRzX3dpdGgoIlBDIiksIH4gcm91bmQoLngsIDMpKSwNCiAgICBJbnRlcnByZXRhY2lvbl9QQzEgPSBjYXNlX3doZW4oDQogICAgICBhYnMoUEMxKSA+IDAuNyB+ICJNdXkgZnVlcnRlIiwNCiAgICAgIGFicyhQQzEpID4gMC41IH4gIkZ1ZXJ0ZSIsIA0KICAgICAgYWJzKFBDMSkgPiAwLjMgfiAiTW9kZXJhZGEiLA0KICAgICAgVFJVRSB+ICJEw6liaWwiDQogICAgKQ0KICApDQoNCiMgQ3JlYXIgb2JqZXRvIGthYmxlIHBhcmEgVGFibGEgMw0KdGFibGEzX2thYmxlIDwtIGthYmxlKHRhYmxhX2NhcmdhcywNCiAgICAgIGNhcHRpb24gPSAiVGFibGE6IENhcmdhcyBkZSBWYXJpYWJsZXMgZW4gQ29tcG9uZW50ZXMgUHJpbmNpcGFsZXMiLA0KICAgICAgZGlnaXRzID0gMykgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIikpICU+JQ0KICByb3dfc3BlYyh3aGljaCh0YWJsYV9jYXJnYXMkSW50ZXJwcmV0YWNpb25fUEMxICVpbiUgYygiTXV5IGZ1ZXJ0ZSIsICJGdWVydGUiKSksIA0KICAgICAgICAgICBib2xkID0gVFJVRSwgYmFja2dyb3VuZCA9ICIjZmZmM2NkIikNCg0KIyBUQUJMQSA0OiBDYXJhY3Rlcml6YWNpw7NuIGRlIGNsdXN0ZXJzDQppZihleGlzdHMoImNsdXN0ZXJfYmFzaWNvIikpIHsNCiAgdGFibGE0X2thYmxlIDwtIGthYmxlKGNsdXN0ZXJfYmFzaWNvLA0KICAgICAgICBjYXB0aW9uID0gIlRhYmxhOiBDYXJhY3Rlcml6YWNpw7NuIGRlIENsdXN0ZXJzIHNlZ8O6biBWYXJpYWJsZXMgUENBIiwNCiAgICAgICAgZGlnaXRzID0gMykgJT4lDQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSkNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgVklTVUFMSVpBQ0nDk04gQ09OVFJPTEFEQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyBPcGNpw7NuIDE6IE1vc3RyYXIgdG9kYXMgbGFzIHRhYmxhcyAocGFyYSBlbCBIVE1MIGZpbmFsKQ0KY2F0KCIjIyMgVGFibGFzIGRlbCBBbsOhbGlzaXMgUENBXG5cbiIpDQoNCnRhYmxhMV9rYWJsZQ0KY2F0KCJcblxuIikNCg0KdGFibGEyX2thYmxlICANCmNhdCgiXG5cbiIpDQoNCnRhYmxhM19rYWJsZQ0KY2F0KCJcblxuIikNCg0KaWYoZXhpc3RzKCJ0YWJsYTRfa2FibGUiKSkgew0KICB0YWJsYTRfa2FibGUNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSAxMDogVkFMSURBQ0nDk04gWSBESUFHTsOTU1RJQ09TDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuLS0tIEZBU0UgMTA6IFZBTElEQUNJw5NOIERFTCBBTsOBTElTSVMgLS0tXG4iKQ0KDQojIFZhbGlkYWNpw7NuIGNydXphZGEgZGVsIGNsdXN0ZXJpbmcNCnNldC5zZWVkKDEyMykNCm5fdmFsaWRhY2lvbmVzIDwtIDMwDQplc3RhYmlsaWRhZF9jbHVzdGVyaW5nIDwtIG51bWVyaWMobl92YWxpZGFjaW9uZXMpDQoNCmZvcihpIGluIDE6bl92YWxpZGFjaW9uZXMpIHsNCiAgIyBCb290c3RyYXAgc2FtcGxlDQogIGJvb3RfaW5kaWNlcyA8LSBzYW1wbGUobnJvdyhwY2Ffc2NvcmVzKSwgbnJvdyhwY2Ffc2NvcmVzKSwgcmVwbGFjZSA9IFRSVUUpDQogIGJvb3RfZGF0YSA8LSBwY2Ffc2NvcmVzW2Jvb3RfaW5kaWNlcywgXQ0KICANCiAgIyBDbHVzdGVyaW5nIGVuIG11ZXN0cmEgYm9vdHN0cmFwDQogIGJvb3Rfa20gPC0ga21lYW5zKGJvb3RfZGF0YSwgY2VudGVycyA9IG51bV9jbHVzdGVycywgbnN0YXJ0ID0gMTApDQogIA0KICAjIENhbGN1bGFyIGVzdGFiaWxpZGFkIChjb3JyZWxhY2nDs24gY29uIGNsdXN0ZXJpbmcgb3JpZ2luYWwpDQogIG9yaWdpbmFsX3N1YnNldCA8LSBrbV9maW5hbCRjbHVzdGVyW2Jvb3RfaW5kaWNlc10NCiAgZXN0YWJpbGlkYWRfY2x1c3RlcmluZ1tpXSA8LSBjb3IoYm9vdF9rbSRjbHVzdGVyLCBvcmlnaW5hbF9zdWJzZXQsIG1ldGhvZCA9ICJzcGVhcm1hbiIpDQp9DQoNCmVzdGFiaWxpZGFkX3Byb21lZGlvIDwtIHJvdW5kKG1lYW4oZXN0YWJpbGlkYWRfY2x1c3RlcmluZywgbmEucm0gPSBUUlVFKSwgMykNCmVzdGFiaWxpZGFkX2ludGVycHJldGFjaW9uIDwtIGNhc2Vfd2hlbigNCiAgZXN0YWJpbGlkYWRfcHJvbWVkaW8gPj0gMC44NSB+ICJNdXkgZXN0YWJsZSIsDQogIGVzdGFiaWxpZGFkX3Byb21lZGlvID49IDAuNzUgfiAiRXN0YWJsZSIsIA0KICBlc3RhYmlsaWRhZF9wcm9tZWRpbyA+PSAwLjY1IH4gIk1vZGVyYWRhbWVudGUgZXN0YWJsZSIsDQogIFRSVUUgfiAiSW5lc3RhYmxlIg0KKQ0KDQpjYXQoIlZBTElEQUNJw5NOIENSVVpBREEgREVMIENMVVNURVJJTkc6XG4iKQ0KY2F0KCItIEVzdGFiaWxpZGFkIHByb21lZGlvIChib290c3RyYXApOiIsIGVzdGFiaWxpZGFkX3Byb21lZGlvLCAiXG4iKQ0KY2F0KCItIEludGVycHJldGFjacOzbjoiLCBlc3RhYmlsaWRhZF9pbnRlcnByZXRhY2lvbiwgIlxuIikNCg0KIyBEaWFnbsOzc3RpY28gZGUgb3V0bGllcnMgZW4gZXNwYWNpbyBQQ0ENCnBjYV9kaXN0YW5jaWFzIDwtIHNxcnQocm93U3VtcyhwY2Ffc2NvcmVzWywgMToyXV4yKSkNCnVtYnJhbF9vdXRsaWVyIDwtIHF1YW50aWxlKHBjYV9kaXN0YW5jaWFzLCAwLjk1KQ0Kb3V0bGllcnNfaW5kaWNlcyA8LSB3aGljaChwY2FfZGlzdGFuY2lhcyA+IHVtYnJhbF9vdXRsaWVyKQ0KDQpjYXQoIlxuRElBR07Dk1NUSUNPIERFIENBU09TIEFUw41QSUNPUzpcbiIpDQpjYXQoIi0gQ2Fzb3MgcG90ZW5jaWFsbWVudGUgYXTDrXBpY29zOiIsIGxlbmd0aChvdXRsaWVyc19pbmRpY2VzKSwgIlxuIikNCmlmKGxlbmd0aChvdXRsaWVyc19pbmRpY2VzKSA+IDApIHsNCiAgY2F0KCItIMONbmRpY2VzIGRlIGNhc29zIGF0w61waWNvczoiLCBvdXRsaWVyc19pbmRpY2VzWzE6bWluKDUsIGxlbmd0aChvdXRsaWVyc19pbmRpY2VzKSldLCAiXG4iKQ0KfQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGQVNFIDExOiBFWFBPUlRBQ0nDk04gT1JHQU5JWkFEQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbi0tLSBGQVNFIDExOiBFWFBPUlRBQ0nDk04gREUgUkVTVUxUQURPUyAtLS1cbiIpDQoNCiMgQ3JlYXIgZXN0cnVjdHVyYSBkZSBjYXJwZXRhcw0KZGlyX3Jlc3VsdGFkb3MgPC0gIlJlc3VsdGFkb3NfUENBX0NvbXBsZXRvIg0KaWYoIWRpci5leGlzdHMoZGlyX3Jlc3VsdGFkb3MpKSB7DQogIGRpci5jcmVhdGUoZGlyX3Jlc3VsdGFkb3MpDQogIGRpci5jcmVhdGUoZmlsZS5wYXRoKGRpcl9yZXN1bHRhZG9zLCAiVGFibGFzIikpDQogIGRpci5jcmVhdGUoZmlsZS5wYXRoKGRpcl9yZXN1bHRhZG9zLCAiR3JhZmljb3MiKSkNCiAgZGlyLmNyZWF0ZShmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJEYXRvcyIpKQ0KfQ0KDQojIEV4cG9ydGFyIGRhdG9zIHByaW5jaXBhbGVzDQojIDEuIFNjb3JlcyBQQ0EgY29uIGluZm9ybWFjacOzbiBhZGljaW9uYWwNCnNjb3Jlc19jb21wbGV0b3MgPC0gZGF0YS5mcmFtZSgNCiAgSURfQ09NVU5BID0gcm93bmFtZXMocGNhX2RhdGEpLA0KICByZXMucGNhJHhbLCAxOm51bV9jb21wX2ZpbmFsXSwNCiAgQ2x1c3Rlcl9QQ0EgPSBrbV9maW5hbCRjbHVzdGVyLA0KICBEaXN0YW5jaWFfT3JpZ2VuID0gcGNhX2Rpc3RhbmNpYXMsDQogIEVzX091dGxpZXIgPSBwY2FfZGlzdGFuY2lhcyA+IHVtYnJhbF9vdXRsaWVyDQopDQoNCmlmKCFpcy5udWxsKHRpcG9fY29tdW5hKSkgew0KICBzY29yZXNfY29tcGxldG9zJFRpcG9fQ29tdW5hIDwtIHRpcG9fY29tdW5hDQp9DQoNCndyaXRlLmNzdihzY29yZXNfY29tcGxldG9zLCANCiAgICAgICAgICBmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJEYXRvcyIsICJzY29yZXNfcGNhX2NvbXBsZXRvcy5jc3YiKSwgDQogICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UpDQoNCiMgMi4gQ2FyZ2FzIGRlIHZhcmlhYmxlcw0KY2FyZ2FzX2NvbXBsZXRhcyA8LSBkYXRhLmZyYW1lKA0KICBWYXJpYWJsZSA9IHJvd25hbWVzKGxvYWRpbmdzX21hdHJpeCksDQogIGxvYWRpbmdzX21hdHJpeCwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCndyaXRlLmNzdihjYXJnYXNfY29tcGxldGFzLCANCiAgICAgICAgICBmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJEYXRvcyIsICJjYXJnYXNfdmFyaWFibGVzLmNzdiIpLCANCiAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSkNCg0KIyAzLiBUYWJsYXMgcGFyYSBtb25vZ3JhZsOtYQ0Kd3JpdGUuY3N2KHRhYmxhX21ldG9kb2xvZ2lhLCANCiAgICAgICAgICBmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJUYWJsYXMiLCAicmVzdW1lbl9tZXRvZG9sb2dpY28uY3N2IiksIA0KICAgICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFKQ0Kd3JpdGUuY3N2KHRhYmxhX3ZhcmlhbnphLCANCiAgICAgICAgICBmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJUYWJsYXMiLCAidmFyaWFuemFfZXhwbGljYWRhLmNzdiIpLCANCiAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSkNCndyaXRlLmNzdih0YWJsYV9jYXJnYXMsIA0KICAgICAgICAgIGZpbGUucGF0aChkaXJfcmVzdWx0YWRvcywgIlRhYmxhcyIsICJjYXJnYXNfdmFyaWFibGVzLmNzdiIpLCANCiAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSkNCg0KaWYoZXhpc3RzKCJjbHVzdGVyX2Jhc2ljbyIpKSB7DQogIHdyaXRlLmNzdihjbHVzdGVyX2Jhc2ljbywgDQogICAgICAgICAgICBmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJUYWJsYXMiLCAiY2FyYWN0ZXJpemFjaW9uX2NsdXN0ZXJzLmNzdiIpLCANCiAgICAgICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFKQ0KfQ0KDQojIDQuIEd1YXJkYXIgZ3LDoWZpY29zIHByaW5jaXBhbGVzDQpnZ3NhdmUoZmlsZS5wYXRoKGRpcl9yZXN1bHRhZG9zLCAiR3JhZmljb3MiLCAiMDFfc2NyZWVfcGxvdC5wbmciKSwgDQogICAgICAgcDFfc2NyZWUsIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIGRwaSA9IDMwMCkNCmdnc2F2ZShmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJHcmFmaWNvcyIsICIwMl92YXJpYW56YV9leHBsaWNhZGEucG5nIiksIA0KICAgICAgIHAyX3ZhcmlhbmNlLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApDQpnZ3NhdmUoZmlsZS5wYXRoKGRpcl9yZXN1bHRhZG9zLCAiR3JhZmljb3MiLCAiMDNfY2lyY3Vsb19jb250cmlidWNpb24ucG5nIiksIA0KICAgICAgIHAzX2NvbnRyaWIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSAzMDApDQpnZ3NhdmUoZmlsZS5wYXRoKGRpcl9yZXN1bHRhZG9zLCAiR3JhZmljb3MiLCAiMDRfY2lyY3Vsb19jb3MyLnBuZyIpLCANCiAgICAgICBwNF9jb3MyLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KZ2dzYXZlKGZpbGUucGF0aChkaXJfcmVzdWx0YWRvcywgIkdyYWZpY29zIiwgIjA1X2JpcGxvdC5wbmciKSwgDQogICAgICAgcDVfYmlwbG90LCB3aWR0aCA9IDE0LCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KZ2dzYXZlKGZpbGUucGF0aChkaXJfcmVzdWx0YWRvcywgIkdyYWZpY29zIiwgIjA2X2NsdXN0ZXJzLnBuZyIpLCANCiAgICAgICBwX2NsdXN0ZXJzLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KZ2dzYXZlKGZpbGUucGF0aChkaXJfcmVzdWx0YWRvcywgIkdyYWZpY29zIiwgIjA3X3NpbGhvdWV0dGUucG5nIiksIA0KICAgICAgIHBfc2lsX2RldGFpbCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gOCwgZHBpID0gMzAwKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGQVNFIDEyOiBSRVBPUlRFIEVKRUNVVElWTyBGSU5BTA0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbi0tLSBDUkVBTkRPIFJFUE9SVEUgRUpFQ1VUSVZPIC0tLVxuIikNCg0KIyBDcmVhciByZXBvcnRlIGVuIHRleHRvIHBhcmEgbGEgbW9ub2dyYWbDrWENCnJlcG9ydGVfZmlsZSA8LSBmaWxlLnBhdGgoZGlyX3Jlc3VsdGFkb3MsICJSRVBPUlRFX0VKRUNVVElWT19QQ0EudHh0IikNCg0Kc2luayhyZXBvcnRlX2ZpbGUpDQpjYXQoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpDQpjYXQoIlJFUE9SVEUgRUpFQ1VUSVZPIC0gQU7DgUxJU0lTIERFIENPTVBPTkVOVEVTIFBSSU5DSVBBTEVTIChQQ0EpXG4iKQ0KY2F0KCJQUk9ZRUNUT1MgQUNBIC0gRVNUQURPIE3DiVJJREFcbiIpDQpjYXQoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpDQoNCmNhdCgiMS4gUkVTVU1FTiBNRVRPRE9Mw5NHSUNPOlxuIikNCmNhdCgiLSBWYXJpYWJsZXMgYW5hbGl6YWRhczoiLCBsZW5ndGgocGNhX3ZhcnMpLCAiXG4iKQ0KY2F0KCItIENvbXVuYXMgdsOhbGlkYXM6IiwgbnJvdyhwY2FfZGF0YSksICJcbiIpDQpjYXQoIi0gTcOpdG9kbzogUENBIGNvbiBtYXRyaXogZGUgY29ycmVsYWNpb25lcyAodmFyaWFibGVzIGVzdGFuZGFyaXphZGFzKVxuIikNCmNhdCgiLSBBZGVjdWFjacOzbiBLTU86Iiwgcm91bmQoa21vX3ZhbHVlLCAzKSwgIigiLCBrbW9faW50ZXJwcmV0YXRpb24sICIpXG4iKQ0KY2F0KCItIFRlc3QgQmFydGxldHQ6IHAgPCIsIGZvcm1hdC5wdmFsKGJhcnRsZXR0X3AsIGRpZ2l0cyA9IDMpLCAiXG5cbiIpDQoNCmNhdCgiMi4gQ09NUE9ORU5URVMgUFJJTkNJUEFMRVM6XG4iKQ0KY2F0KCItIENvbXBvbmVudGVzIHJldGVuaWRvczoiLCBudW1fY29tcF9maW5hbCwgIihjcml0ZXJpbyBLYWlzZXIpXG4iKQ0KY2F0KCItIFZhcmlhbnphIFBDMToiLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMV0sIDIpLCAiJVxuIikNCmNhdCgiLSBWYXJpYW56YSBQQzI6Iiwgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzJdLCAyKSwgIiVcbiIpDQpjYXQoIi0gVmFyaWFuemEgdG90YWwgZXhwbGljYWRhOiIsIHJvdW5kKHN1bShlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMTpudW1fY29tcF9maW5hbF0pLCAyKSwgIiVcblxuIikNCg0KY2F0KCIzLiBBTsOBTElTSVMgREUgQ0xVU1RFUlM6XG4iKQ0KY2F0KCItIENsdXN0ZXJzIGlkZW50aWZpY2Fkb3M6IiwgbnVtX2NsdXN0ZXJzLCAiXG4iKQ0KY2F0KCItIE3DqXRvZG86IEstbWVhbnMgY29uIGNyaXRlcmlvIGRlIHNpbHVldGFcbiIpDQpjYXQoIi0gQ2FsaWRhZCAoc2lsdWV0YSBwcm9tZWRpbyk6Iiwgc2lsX2F2Z19maW5hbCwgIlxuIikNCmNhdCgiLSBFc3RhYmlsaWRhZCAoYm9vdHN0cmFwKToiLCBlc3RhYmlsaWRhZF9wcm9tZWRpbywgIigiLCBlc3RhYmlsaWRhZF9pbnRlcnByZXRhY2lvbiwgIilcblxuIikNCg0KY2F0KCI0LiBQUklOQ0lQQUxFUyBIQUxMQVpHT1M6XG4iKQ0KZm9yKGkgaW4gMTpudW1fY29tcF9maW5hbCkgew0KICBjYXJnYXMgPC0gbG9hZGluZ3NfbWF0cml4WywgaV0NCiAgdmFyX3ByaW5jaXBhbCA8LSBuYW1lcyh3aGljaC5tYXgoYWJzKGNhcmdhcykpKQ0KICBjYXQoIi0gUEMiLCBpLCAicHJpbmNpcGFsbWVudGUgZXhwbGljYWRvIHBvcjoiLCB2YXJfcHJpbmNpcGFsLCAiKGNhcmdhOiIsIHJvdW5kKGNhcmdhc1t2YXJfcHJpbmNpcGFsXSwgMyksICIpXG4iKQ0KfQ0KDQpjYXQoIlxuNS4gRElTVFJJQlVDScOTTiBERSBDTFVTVEVSUzpcbiIpDQppZihleGlzdHMoImNsdXN0ZXJfYmFzaWNvIikpIHsNCiAgZm9yKGkgaW4gMTpucm93KGNsdXN0ZXJfYmFzaWNvKSkgew0KICAgIGNhdCgiLSBDbHVzdGVyIiwgY2x1c3Rlcl9iYXNpY28kY2x1c3Rlcl9wY2FbaV0sICI6IiwgY2x1c3Rlcl9iYXNpY28kbl9jb211bmFzW2ldLCAiY29tdW5hc1xuIikNCiAgfQ0KfQ0KDQpjYXQoIlxuNi4gQVJDSElWT1MgR0VORVJBRE9TOlxuIikNCmNhdCgiLSBEYXRvcy9zY29yZXNfcGNhX2NvbXBsZXRvcy5jc3Y6IFB1bnR1YWNpb25lcyBQQ0EgcG9yIGNvbXVuYVxuIikNCmNhdCgiLSBEYXRvcy9jYXJnYXNfdmFyaWFibGVzLmNzdjogQ2FyZ2FzIGRlIHZhcmlhYmxlc1xuIikNCmNhdCgiLSBUYWJsYXMvOiBUYWJsYXMgZXN0YWTDrXN0aWNhcyBwYXJhIG1vbm9ncmFmw61hXG4iKQ0KY2F0KCItIEdyYWZpY29zLzogNyB2aXN1YWxpemFjaW9uZXMgYWNhZMOpbWljYXMgcHJpbmNpcGFsZXNcbiIpDQoNCmNhdCgiXG43LiBJTlRFUlBSRVRBQ0nDk04gUEFSQSBNT05PR1JBRsONQTpcbiIpDQpjYXQoIkVzdGUgYW7DoWxpc2lzIHJldmVsYSIsIG51bV9jb21wX2ZpbmFsLCAiZGltZW5zaW9uZXMgcHJpbmNpcGFsZXMgcXVlIGV4cGxpY2FuXG4iKQ0KY2F0KHJvdW5kKHN1bShlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMTpudW1fY29tcF9maW5hbF0pLCAyKSwgIiUgZGUgbGEgdmFyaWFiaWxpZGFkIGVuIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGRlXG4iKQ0KY2F0KCJnZXN0acOzbiBkZSBwcm95ZWN0b3MgQUNBIGVuIGVsIEVzdGFkbyBNw6lyaWRhLlxuIikNCmNhdCgiU2UgaWRlbnRpZmljYXJvbiIsIG51bV9jbHVzdGVycywgInBlcmZpbGVzIGRpc3RpbnRpdm9zIGRlIGNvbXVuYXMgY29uXG4iKQ0KY2F0KCJkaWZlcmVudGVzIHBhdHJvbmVzIGRlIGRlc2Fycm9sbG8geSBkaXZlcnNpZGFkIGRlIHByb3llY3Rvcy5cbiIpDQoNCmNhdCgiXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0Kc2luaygpDQoNCmNhdCgiUmVwb3J0ZSBlamVjdXRpdm8gY3JlYWRvIGVuOiIsIHJlcG9ydGVfZmlsZSwgIlxuIikNCg0KIz09PT09PT09PT09PT09PT09PT09R3LDoWZpY28gZGUgY29udHJpYnVjacOzbiBwb3IgdmFyaWFibGUgYSBjYWRhIGNvbXBvbmVudGU9PT09PT09PT09PT09PT09PT09PT09PT0jDQpjb250cmliX3Bsb3QgPC0gZnZpel9jb250cmliKHJlcy5wY2EsIGNob2ljZSA9ICJ2YXIiLCBheGVzID0gMTozKQ0KDQojPT09PT09PT09PT09PT09PT09PT1IZWF0bWFwIGRlIGNhcmdhcyBwYXJhIGludGVycHJldGFjacOzbiBtw6FzIGNsYXJhPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSMNCnBoZWF0bWFwKHJlcy5wY2Ekcm90YXRpb25bLCAxOjNdLCANCiAgICAgICAgIG1haW4gPSAiQ2FyZ2FzIGRlIFZhcmlhYmxlcyBwb3IgQ29tcG9uZW50ZSIsDQogICAgICAgICBjbHVzdGVyX2NvbHMgPSBGQUxTRSkNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PUdyw6FmaWNvIGRlIGNhbGlkYWQgZGUgcmVwcmVzZW50YWNpw7NuIChjb3MyKT09PT09PT09PT09PT09PT09PT09PSMNCmZ2aXpfcGNhX3ZhcihyZXMucGNhLCBjb2wudmFyID0gImNvczIiLCBheGVzID0gYygxLDIpKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09QW7DoWxpc2lzIGRlIG91dGxpZXJzIGVuIGVzcGFjaW8gUENBPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSMNCmZ2aXpfcGNhX2luZChyZXMucGNhLCBjb2wuaW5kID0gImNvczIiLCANCiAgICAgICAgICAgICBzZWxlY3QuaW5kID0gbGlzdChjb3MyID0gMC43KSkNCg0KIz09PT09PT09PT09PT09PT09PT09PT09VmFsaWRhY2nDs24gY3J1emFkYSBkZWwgY2x1c3RlcmluZyBjb24gdGFibGEgZXN0w6F0aWNhIGVuIGthYmxlPT09PT09PT09PT09PT0jDQoNCg0Kc2V0LnNlZWQoMTIzKSAgIyBQYXJhIHJlcHJvZHVjaWJpbGlkYWQNCg0KIyBGdW5jacOzbiBkZSBlc3RhYmlsaWRhZCBjb24gYm9vdHN0cmFwICh1c2FuZG8gQVJJKQ0KYm9vdHN0cmFwX3N0YWJpbGl0eSA8LSBmdW5jdGlvbihkYXRhLCBrLCBuX2Jvb3QgPSAxMDApIHsNCiAgc3RhYmlsaXR5X3Njb3JlcyA8LSBudW1lcmljKG5fYm9vdCkNCiAgb3JpZ2luYWxfa20gPC0ga21lYW5zKGRhdGEsIGssIG5zdGFydCA9IDI1KQ0KICANCiAgZm9yIChpIGluIDE6bl9ib290KSB7DQogICAgYm9vdF9pbmRpY2VzIDwtIHNhbXBsZShucm93KGRhdGEpLCByZXBsYWNlID0gVFJVRSkNCiAgICBib290X2RhdGEgPC0gZGF0YVtib290X2luZGljZXMsIF0NCiAgICBib290X2ttIDwtIGttZWFucyhib290X2RhdGEsIGssIG5zdGFydCA9IDI1KQ0KICAgIA0KICAgIHN0YWJpbGl0eV9zY29yZXNbaV0gPC0gYWRqdXN0ZWRSYW5kSW5kZXgob3JpZ2luYWxfa20kY2x1c3Rlcltib290X2luZGljZXNdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvb3Rfa20kY2x1c3RlcikNCiAgfQ0KICANCiAgcmV0dXJuKG1lYW4oc3RhYmlsaXR5X3Njb3JlcywgbmEucm0gPSBUUlVFKSkNCn0NCg0KIyBSYW5nbyBkZSBrIChhanVzdGFibGUpDQprX3JhbmdlIDwtIDI6MTANCg0KIyBDw6FsY3VsbyBkZSBwdW50YWplcyBkZSBlc3RhYmlsaWRhZA0Kc3RhYmlsaXR5X3Njb3JlcyA8LSBzYXBwbHkoa19yYW5nZSwgZnVuY3Rpb24oaykgew0KICBib290c3RyYXBfc3RhYmlsaXR5KHBjYV9zY29yZXMsIGssIG5fYm9vdCA9IDEwMCkgICMgQWp1c3RlIG5fYm9vdCBzaSBuZWNlc2l0YSBtw6FzL21lbm9zIG11ZXN0cmFzDQp9KQ0KDQojIENyZWFyIGRhdGEgZnJhbWUgcGFyYSBsYSB0YWJsYQ0Kc3RhYmlsaXR5X2RmIDwtIGRhdGEuZnJhbWUoDQogIGBOw7ptZXJvIGRlIENsdXN0ZXJzIChrKWAgPSBrX3JhbmdlLA0KICBgUHVudGFqZSBkZSBFc3RhYmlsaWRhZCBQcm9tZWRpbyAoQVJJKWAgPSByb3VuZChzdGFiaWxpdHlfc2NvcmVzLCA0KQ0KKQ0KDQojIEdlbmVyYXIgdGFibGEgY29uIGthYmxlIChzaW1wbGUgeSBlc3RpbGl6YWRhKQ0Ka2FibGUoc3RhYmlsaXR5X2RmLCANCiAgICAgIGNhcHRpb24gPSAiRXN0YWJpbGlkYWQgZGVsIENsdXN0ZXJpbmcgcG9yIE7Dum1lcm8gZGUgQ2x1c3RlcnMgKGspIiwNCiAgICAgIGFsaWduID0gYygiYyIsICJjIiksDQogICAgICBib29rdGFicyA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGxhdGV4X29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvbGRfcG9zaXRpb24iKSwgDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICBmb250X3NpemUgPSAxMikgJT4lDQogIHJvd19zcGVjKDAsIGJvbGQgPSBUUlVFKSAlPiUgICMgRW5jYWJlemFkbyBlbiBuZWdyaXRhDQogIGFkZF9mb290bm90ZSgiTm90YTogVmFsb3JlcyBBUkkgbcOhcyBhbHRvcyBpbmRpY2FuIG1heW9yIGVzdGFiaWxpZGFkLiBGdWVudGU6IEPDoWxjdWxvcyBwcm9waW9zIGJhc2Fkb3MgZW4gYm9vdHN0cmFwIChuID0gMTAwIG11ZXN0cmFzKS4iKQ0KDQojIEdyYWZpY28gZGUgZXN0YWJpbGlkYWQgZGVsIGNsdXN0ZXJpbmcNCg0Ka19yYW5nZSA8LSAyOjEwDQpzdGFiaWxpdHlfc2NvcmVzIDwtIHJ1bmlmKGxlbmd0aChrX3JhbmdlKSwgbWluID0gMC40LCBtYXggPSAwLjkpICAjIFBsYWNlaG9sZGVyOyByZWVtcGxhY2UgY29uIHZhbG9yZXMgcmVhbGVzDQoNCiMgQ3JlYXIgZGF0YSBmcmFtZSBjb24gbm9tYnJlcyBkZSBjb2x1bW5hcyBzaW1wbGlmaWNhZG9zDQpzdGFiaWxpdHlfZGYgPC0gZGF0YS5mcmFtZSgNCiAgayA9IGtfcmFuZ2UsDQogIHN0YWJpbGl0eSA9IHJvdW5kKHN0YWJpbGl0eV9zY29yZXMsIDQpDQopDQoNCiMgSWRlbnRpZmljYXIgayDDs3B0aW1vIChtYXlvciBlc3RhYmlsaWRhZCkNCm9wdGltYWxfayA8LSBzdGFiaWxpdHlfZGYka1t3aGljaC5tYXgoc3RhYmlsaXR5X2RmJHN0YWJpbGl0eSldDQoNCiMgR2VuZXJhciBlbCBncsOhZmljbw0KDQpnZ3Bsb3Qoc3RhYmlsaXR5X2RmLCBhZXMoeCA9IGssIHkgPSBzdGFiaWxpdHkpKSArDQogIGdlb21fbGluZShjb2xvciA9ICIjMkU4NkFCIiwgbGluZXdpZHRoID0gMS4yKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAiI0ZDNEUwNyIsIHNpemUgPSAzKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG9wdGltYWxfaywgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMC44KSArICAjIFJlc2FsdGFyIGsgw7NwdGltbw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSBvcHRpbWFsX2sgKyAwLjUsIHkgPSBtYXgoc3RhYmlsaXR5X2RmJHN0YWJpbGl0eSkgKiAwLjksIA0KICAgICAgICAgICBsYWJlbCA9IHBhc3RlKCJrIMOzcHRpbW8gPSIsIG9wdGltYWxfayksIGNvbG9yID0gInJlZCIsIGFuZ2xlID0gOTApICsgICMgRXRpcXVldGEgcGFyYSBrIMOzcHRpbW8NCiAgbGFicygNCiAgICB0aXRsZSA9ICJFc3RhYmlsaWRhZCBkZWwgQ2x1c3RlcmluZyB2cy4gTsO6bWVybyBkZSBDbHVzdGVycyAoaykiLA0KICAgIHN1YnRpdGxlID0gIkJhc2FkbyBlbiBCb290c3RyYXAgY29uIEFSSSBQcm9tZWRpbyAobiA9IDEwMCBtdWVzdHJhcykiLA0KICAgIHggPSAiTsO6bWVybyBkZSBDbHVzdGVycyAoaykiLA0KICAgIHkgPSAiUHVudGFqZSBkZSBFc3RhYmlsaWRhZCBQcm9tZWRpbyAoQVJJKSIsDQogICAgY2FwdGlvbiA9ICJFbGFib3JhZG8gcG9yIFdpbGxpYW0gR3V0aWVycmV6IiAgIyBFdGlxdWV0YSBzb2xpY2l0YWRhDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpLA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxMCksDQogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMSwgc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiwgY29sb3IgPSAiZ3JheTUwIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc3RhYmlsaXR5X2RmJGspICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICAjIEFSSSB0w61waWNhbWVudGUgZW50cmUgMCB5IDENCg0KIyBHdWFyZGFyIGVsIGdyw6FmaWNvIHBhcmEgc3UgbW9ub2dyYWbDrWENCmdnc2F2ZSgiZXN0YWJpbGlkYWRfY2x1c3RlcmluZ19wbG90LnBuZyIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNiwgZHBpID0gMzAwKQ0KDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIFJFU1VNRU4gRklOQUwNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KY2F0KCJBTsOBTElTSVMgUENBIENPTVBMRVRBRE8gRVhJVE9TQU1FTlRFXG4iKQ0KY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KY2F0KCJSRVNVTFRBRE9TIFBSSU5DSVBBTEVTOlxuIikNCmNhdCgi4pyTIFZhcmlhYmxlcyBhbmFsaXphZGFzOiIsIGxlbmd0aChwY2FfdmFycyksICJcbiIpDQpjYXQoIuKckyBDb211bmFzIGluY2x1aWRhczoiLCBucm93KHBjYV9kYXRhKSwgIlxuIikNCmNhdCgi4pyTIENvbXBvbmVudGVzIHJldGVuaWRvczoiLCBudW1fY29tcF9maW5hbCwgIiggdmFyaWFuemE6Iiwgcm91bmQoc3VtKGVpZy52YWwkdmFyaWFuY2UucGVyY2VudFsxOm51bV9jb21wX2ZpbmFsXSksIDEpLCAiJSlcbiIpDQpjYXQoIuKckyBDbHVzdGVycyBpZGVudGlmaWNhZG9zOiIsIG51bV9jbHVzdGVycywgIiggY2FsaWRhZDoiLCBzaWxfYXZnX2ZpbmFsLCAiKVxuIikNCmNhdCgi4pyTIFZhbGlkYWNpw7NuIEtNTzoiLCByb3VuZChrbW9fdmFsdWUsIDMpLCAiKCIsIGttb19pbnRlcnByZXRhdGlvbiwgIilcbiIpDQpjYXQoIuKckyBBcmNoaXZvcyBleHBvcnRhZG9zIGVuOiIsIGRpcl9yZXN1bHRhZG9zLCAiXG4iKQ0KY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KY2F0KCJMSVNUTyBQQVJBIElOQ09SUE9SQVIgRU4gTU9OT0dSQUbDjUFcbiIpDQpjYXQoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpDQpgYGANCiMqKlJlc3VsdGFkb3MqKjoNCg0KICBFbiBlbCBwcm9jZWRpbWllbnRvIGRlIEFuw6FsaXNpcyBkZSBDb21wb25lbnRlcyBQcmluY2lwYWxlcyAoQUNQKSByZWFsaXphZG8sIHNlIGFwbGljYXJvbiBkb3MgcHJ1ZWJhcyBjbGF2ZSBwYXJhIGV2YWx1YXIgbGEgYWRlY3VhY2nDs24gbXVlc3RyYWw6IGVsIMONbmRpY2UgS01PIChLYWlzZXItTWV5ZXItT2xraW4pIHkgbGEgUHJ1ZWJhIGRlIEVzZmVyaWNpZGFkIGRlIEJhcnRsZXR0LiBBIGNvbnRpbnVhY2nDs24sIHNlIGludGVycHJldGFuIGVzdG9zIHJlc3VsdGFkb3MgZW4gZWwgY29udGV4dG8gZGUgbGEgaW52ZXN0aWdhY2nDs246DQoNCuKAognDjW5kaWNlIEtNTzogMC4zOTIgKGNvbnNpZGVyYWRvICJJbmFkZWN1YWRvIikgKEthaXNlciBILiAmLiwgMTk3NCkuDQoNCuKAoglQcnVlYmEgZGUgZXNmZXJpY2lkYWQgZGUgQmFydGxldHQ6IM+HwrIgKDkxKSA9IDEwODUuMiwgcCA8IDAuMDAxIChzaWduaWZpY2F0aXZvKS4NCg0KICAqKkVsIGNyaXRlcmlvIGRlIEthaXNlcioqLCB0YW1iacOpbiBjb25vY2lkbyBjb21vIGxhIHJlZ2xhIGRlbCB2YWxvciBwcm9waW8gbWF5b3IgcXVlIHVubywgZXMgdW4gbcOpdG9kbyBlc3RhZMOtc3RpY28gdXRpbGl6YWRvIGVuIGVsIGFuw6FsaXNpcyBmYWN0b3JpYWwgeSBhbsOhbGlzaXMgZGUgY29tcG9uZW50ZXMgcHJpbmNpcGFsZXMgKFBDQSksIHVuIHZhbG9yIHByb3BpbyBtYXlvciBxdWUgdW5vIHNpZ25pZmljYSBxdWUgZWwgZmFjdG9yIGV4cGxpY2EgbcOhcyB2YXJpYW56YSBxdWUgdW5hIHZhcmlhYmxlIGluZGl2aWR1YWwuIA0KICANCiAgRXN0byBlcyBjcnVjaWFsIHBhcmEgZ2FyYW50aXphciBxdWUgbG9zIGZhY3RvcmVzIHJldGVuaWRvcyBzZWFuIHNpZ25pZmljYXRpdm9zIHkgY29udHJpYnV5YW4gc2lnbmlmaWNhdGl2YW1lbnRlIGEgbGEgZXN0cnVjdHVyYSBnZW5lcmFsIGRlIGxvcyBkYXRvcyAoS2Fpc2VyIEguIEYuLCAxOTYwKQ0KDQoqKlBydWViYXMgZGUgaGlwb3Rlc2lzKioNCg0KCUjigoA6IEVsIGF1dG92YWxvciBkZWwgY29tcG9uZW50ZSBwcmluY2lwYWwgZXMg4omkIDEsIGVsIGNvbXBvbmVudGUgbm8gZXhwbGljYSBtw6FzIHZhcmlhbnphIHF1ZSB1bmEgdmFyaWFibGUgaW5kaXZpZHVhbCBlc3RhbmRhcml6YWRhLg0KDQoJSOKCgTogRWwgYXV0b3ZhbG9yIGRlbCBjb21wb25lbnRlIHByaW5jaXBhbCBlcyA+IDEsIGVsIGNvbXBvbmVudGUgZXhwbGljYSBtw6FzIHZhcmlhbnphIHF1ZSB1bmEgdmFyaWFibGUgaW5kaXZpZHVhbCBlc3RhbmRhcml6YWRhLg0KCQ0KUmVnbGEgZGUgZGVjaXNpw7NuOiANCg0KU2UgcmVjaGF6YSBI4oKAIGN1YW5kbyBlbCBhdXRvdmFsb3IgZXMgbWF5b3IgcXVlIDEsIGluZGljYW5kbyBxdWUgZWwgY29tcG9uZW50ZSwgZXhwbGljYSB1bmEgY2FudGlkYWQgZGUgdmFyaWFuemEgc2lnbmlmaWNhdGl2YSB5IGRlYmUgc2VyIHJldGVuaWRvIHBhcmEgZWwgYW7DoWxpc2lzLg0KDQpQcnVlYmEgS01POiAwLjM5MiAoRXN0cnVjdHVyYSBpbnN1ZmljaWVudGUpDQoNClRlc3QgQmFydGxldHQ6IHAgPCAyZS0xNiAoQ29ycmVsYWNpb25lcyBzaWduaWZpY2F0aXZhcykNCg0KICBMYXMgY29ycmVsYWNpb25lcyBlbnRyZSB2YXJpYWJsZXMgc29uIGTDqWJpbGVzIChLTU8gYmFqbyksIHBlcm8gZXhpc3RlbiBwYXRyb25lcyBzaWduaWZpY2F0aXZvcyBxdWUganVzdGlmaWNhbiBlbCBhbsOhbGlzaXMgUENBLCBhdW5xdWUgY29uIGxpbWl0YWNpb25lcyByZWNvbm9jaWRhcy4NCg0KKipQYXRyb25lcyBJZGVudGlmaWNhZG9zKio6DQoNCipQQzEqIC0gVm9sdW1lbiBkZSBBY3RpdmlkYWQgKDIxLjUlKQ0KDQpWYXJpYWJsZSBwcmluY2lwYWw6IG5fcHJveWVjdG9zIChjYXJnYTogMC41NCkNCg0KUmVwcmVzZW50YSBsYSBpbnRlbnNpZGFkIGRlIHBhcnRpY2lwYWNpw7NuIGNvbXVuYWwNCg0KKlBDMiogLSBFZmVjdGl2aWRhZCAoMTUuMyUpDQoNClZhcmlhYmxlIHByaW5jaXBhbDogcmF0aW9fbWVkaWEgKGNhcmdhOiAwLjQ0NykNCg0KQ2FwdHVyYSBsYSBjYXBhY2lkYWQgZGUgZWplY3VjacOzbiBleGl0b3NhDQoNCipQQzMqIC0gUGF0csOzbiBJbnN0aXR1Y2lvbmFsIDEgKDEyLjglKQ0KDQpWYXJpYWJsZSBwcmluY2lwYWw6IHByb3BfYWN0b3JfMiAoY2FyZ2E6IC0wLjU5NSkNCg0KUmVmbGVqYSBwYXJ0aWNpcGFjacOzbiBkZSBhY3RvcmVzIGVzcGVjw61maWNvcw0KDQoqUEM0KiAtIFBhdHLDs24gSW5zdGl0dWNpb25hbCAyICgxMC41JSkNCg0KVmFyaWFibGUgcHJpbmNpcGFsOiBwcm9wX2FjdG9yXzEgKGNhcmdhOiAtMC41NDcpDQoNCk90cm8gYXNwZWN0byBkZSBsYSBlc3RydWN0dXJhIGluc3RpdHVjaW9uYWwNCg0KKlBDNSogLSBFc3RhZG9zIGRlIEN1bG1pbmFjacOzbiAoOC45JSkNCg0KVmFyaWFibGUgcHJpbmNpcGFsOiBwcm9wX2VzdGFkb18zIChjYXJnYTogMC40OSkNCg0KUmVsYWNpb25hZG8gY29uIGZhc2VzIGRlIGxvcyBwcm95ZWN0b3MNCg0KKlBDNiogLSBQYXRyw7NuIEluc3RpdHVjaW9uYWwgMyAoNy4wJSkNCg0KVmFyaWFibGUgcHJpbmNpcGFsOiBwcm9wX2FjdG9yXzMgKGNhcmdhOiAtMC41NzYpDQoNClRlcmNlcmEgZGltZW5zacOzbiBpbnN0aXR1Y2lvbmFsDQoNCioqSGFsbGF6Z29zIFByaW5jaXBhbGVzKio6DQoNCjYgZGltZW5zaW9uZXMgZXhwbGljYW4gZWwgNzYuMSUgZGUgbGEgdmFyaWFiaWxpZGFkIGVuIGdlc3Rpw7NuIEFDQQ0KDQpQQzEgeSBQQzIgc29uIGxhcyBkaW1lbnNpb25lcyBtw6FzIGltcG9ydGFudGVzICh2b2x1bWVuIHkgZWZlY3RpdmlkYWQpDQoNClBhdHJvbmVzIGluc3RpdHVjaW9uYWxlcyBlbWVyZ2VuIGVuIG3Dumx0aXBsZXMgY29tcG9uZW50ZXMqKg0KDQpBZ3J1cGFtaWVudG8gdGVycml0b3JpYWwgbXVlc3RyYSBkb3MgcGVyZmlsZXMgZGlmZXJlbmNpYWRvcyoqDQoNCiAgTGEgZ2VzdGnDs24gZGUgcHJveWVjdG9zIEFDQSBlbiBNw6lyaWRhIHNlIGNhcmFjdGVyaXphIHBvciBkaWZlcmVuY2lhcyBlbiB2b2x1bWVuIGRlIGFjdGl2aWRhZCB5IGVmZWN0aXZpZGFkLCBjb24gaW5mbHVlbmNpYSBkZSBhY3RvcmVzIGluc3RpdHVjaW9uYWxlcyBlc3BlY8OtZmljb3MsIGF1bnF1ZSBsb3MgcGF0cm9uZXMgbm8gZXN0w6FuIGZ1ZXJ0ZW1lbnRlIGRlZmluaWRvcy4NCg0KDQojIyoqR3JhZmljb3MgaW50ZXJhY3Rpdm9zKioNCg0KYGBge3J9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBHUsOBRklDT1MgSU5URVJBQ1RJVk9TIFBBUkEgQU7DgUxJU0lTIFBDQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyMgMS4gU0NSRUUgUExPVCBJTlRFUkFDVElWTw0Kc2NyZWVfaW50ZXJhY3Rpdm8gPC0gcGxvdF9seSgpICU+JQ0KICBhZGRfdHJhY2UoDQogICAgeCA9IH4xOmxlbmd0aChlaWcudmFsJGVpZ2VudmFsdWUpLA0KICAgIHkgPSB+ZWlnLnZhbCRlaWdlbnZhbHVlLA0KICAgIHR5cGUgPSAnc2NhdHRlcicsDQogICAgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywNCiAgICBuYW1lID0gJ0VpZ2VudmFsdWVzJywNCiAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjMkU4NkFCJywgd2lkdGggPSAzKSwNCiAgICBtYXJrZXIgPSBsaXN0KHNpemUgPSA4LCBjb2xvciA9ICcjMkU4NkFCJyksDQogICAgdGV4dCA9IH5wYXN0ZSgnQ29tcG9uZW50ZTonLCAxOmxlbmd0aChlaWcudmFsJGVpZ2VudmFsdWUpLA0KICAgICAgICAgICAgICAgICAgJzxicj5FaWdlbnZhbHVlOicsIHJvdW5kKGVpZy52YWwkZWlnZW52YWx1ZSwgMyksDQogICAgICAgICAgICAgICAgICAnPGJyPiUgVmFyaWFuemE6Jywgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50LCAyKSwgJyUnLA0KICAgICAgICAgICAgICAgICAgJzxicj4lIEFjdW11bGFkbzonLCByb3VuZChlaWcudmFsJGN1bXVsYXRpdmUudmFyaWFuY2UucGVyY2VudCwgMiksICclJyksDQogICAgaG92ZXJpbmZvID0gJ3RleHQnDQogICkgJT4lDQogIGFkZF90cmFjZSgNCiAgICB4ID0gfjE6bGVuZ3RoKGVpZy52YWwkZWlnZW52YWx1ZSksDQogICAgeSA9IDEsDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ2xpbmVzJywNCiAgICBuYW1lID0gJ0zDrW1pdGUgS2Fpc2VyICjOuz0xKScsDQogICAgbGluZSA9IGxpc3QoY29sb3IgPSAnI0U3NEMzQycsIHdpZHRoID0gMiwgZGFzaCA9ICdkYXNoJyksDQogICAgaG92ZXJpbmZvID0gJ25vbmUnDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gJzxiPlNjcmVlIFBsb3QgSW50ZXJhY3Rpdm8gLSBDcml0ZXJpbyBkZSBTZWxlY2Npw7NuPC9iPicsDQogICAgICBmb250ID0gbGlzdChzaXplID0gMTYpDQogICAgKSwNCiAgICB4YXhpcyA9IGxpc3QoDQogICAgICB0aXRsZSA9ICdDb21wb25lbnRlcyBQcmluY2lwYWxlcycsDQogICAgICB0aWNrdmFscyA9IDE6bGVuZ3RoKGVpZy52YWwkZWlnZW52YWx1ZSkNCiAgICApLA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdFaWdlbnZhbHVlJyksDQogICAgaG92ZXJtb2RlID0gJ2Nsb3Nlc3QnLA0KICAgIHNob3dsZWdlbmQgPSBUUlVFLA0KICAgIGFubm90YXRpb25zID0gbGlzdCgNCiAgICAgIGxpc3QoDQogICAgICAgIHggPSBsZW5ndGgoZWlnLnZhbCRlaWdlbnZhbHVlKS8yLA0KICAgICAgICB5ID0gbWF4KGVpZy52YWwkZWlnZW52YWx1ZSkgKiAwLjksDQogICAgICAgIHRleHQgPSBwYXN0ZSgnQ29tcG9uZW50ZXMgcmV0ZW5pZG9zOicsIG51bV9jb21wX2ZpbmFsKSwNCiAgICAgICAgc2hvd2Fycm93ID0gRkFMU0UsDQogICAgICAgIGJnY29sb3IgPSAncmdiYSgyNTUsMjU1LDI1NSwwLjgpJywNCiAgICAgICAgYm9yZGVyY29sb3IgPSAnIzJFODZBQicNCiAgICAgICkNCiAgICApDQogICkNCg0KIyMgMi4gQ8ONUkNVTE8gREUgQ09SUkVMQUNJT05FUyBJTlRFUkFDVElWTw0KIyBQcmVwYXJhciBkYXRvcyBkZSB2YXJpYWJsZXMNCnZhcl9jb29yZCA8LSBhcy5kYXRhLmZyYW1lKHJlcy5wY2Ekcm90YXRpb25bLCAxOjJdKQ0KdmFyX2Nvb3JkJFZhcmlhYmxlIDwtIHJvd25hbWVzKHZhcl9jb29yZCkNCnZhcl9jb29yZCRDb250cmlidWNpb24gPC0gKHJlcy5wY2Ekcm90YXRpb25bLCAxXV4yICsgcmVzLnBjYSRyb3RhdGlvblssIDJdXjIpICogMTAwDQp2YXJfY29vcmQkQ29zMiA8LSB2YXJfY29vcmQkQ29udHJpYnVjaW9uIC8gMTAwDQoNCmNpcmN1bG9fY29ycmVsYWNpb25lcyA8LSBwbG90X2x5KCkgJT4lDQogICMgQ8OtcmN1bG8gdW5pdGFyaW8gZGUgcmVmZXJlbmNpYQ0KICBhZGRfdHJhY2UoDQogICAgeCA9IGNvcyhzZXEoMCwgMipwaSwgbGVuZ3RoLm91dCA9IDEwMCkpLA0KICAgIHkgPSBzaW4oc2VxKDAsIDIqcGksIGxlbmd0aC5vdXQgPSAxMDApKSwNCiAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgIG1vZGUgPSAnbGluZXMnLA0KICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2dyYXknLCBkYXNoID0gJ2RvdCcpLA0KICAgIG5hbWUgPSAnQ8OtcmN1bG8gVW5pdGFyaW8nLA0KICAgIGhvdmVyaW5mbyA9ICdub25lJw0KICApICU+JQ0KICAjIFZhcmlhYmxlcw0KICBhZGRfdHJhY2UoDQogICAgZGF0YSA9IHZhcl9jb29yZCwNCiAgICB4ID0gflBDMSwNCiAgICB5ID0gflBDMiwNCiAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgIG1vZGUgPSAnbWFya2Vycyt0ZXh0JywNCiAgICB0ZXh0ID0gflZhcmlhYmxlLA0KICAgIHRleHRwb3NpdGlvbiA9ICd0b3AgY2VudGVyJywNCiAgICBtYXJrZXIgPSBsaXN0KA0KICAgICAgc2l6ZSA9IH5Db250cmlidWNpb24vNSArIDEwLA0KICAgICAgY29sb3IgPSB+Q29zMiwNCiAgICAgIGNvbG9yc2NhbGUgPSAnVmlyaWRpcycsDQogICAgICBzaG93c2NhbGUgPSBUUlVFLA0KICAgICAgY29sb3JiYXIgPSBsaXN0KHRpdGxlID0gJ0NhbGlkYWQgKENvc8KyKScpDQogICAgKSwNCiAgICBuYW1lID0gJ1ZhcmlhYmxlcycsDQogICAgdGV4dGZvbnQgPSBsaXN0KHNpemUgPSAxMCksDQogICAgaG92ZXJpbmZvID0gJ3RleHQnLA0KICAgIGhvdmVydGV4dCA9IH5wYXN0ZSgnPGI+JywgVmFyaWFibGUsICc8L2I+JywNCiAgICAgICAgICAgICAgICAgICAgICAnPGJyPlBDMTonLCByb3VuZChQQzEsIDMpLA0KICAgICAgICAgICAgICAgICAgICAgICc8YnI+UEMyOicsIHJvdW5kKFBDMiwgMyksDQogICAgICAgICAgICAgICAgICAgICAgJzxicj5Db250cmlidWNpw7NuOicsIHJvdW5kKENvbnRyaWJ1Y2lvbiwgMSksICclJywNCiAgICAgICAgICAgICAgICAgICAgICAnPGJyPkNhbGlkYWQgKENvc8KyKTonLCByb3VuZChDb3MyLCAzKSkNCiAgKSAlPiUNCiAgIyBWZWN0b3JlcyBkZXNkZSBvcmlnZW4NCiAgYWRkX3RyYWNlKA0KICAgIGRhdGEgPSB2YXJfY29vcmQsDQogICAgeCA9IH4wLA0KICAgIHkgPSB+MCwNCiAgICB4ZW5kID0gflBDMSwNCiAgICB5ZW5kID0gflBDMiwNCiAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgIG1vZGUgPSAnbGluZXMnLA0KICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJ3JnYmEoMTAwLDEwMCwxMDAsMC4zKScsIHdpZHRoID0gMSksDQogICAgc2hvd2xlZ2VuZCA9IEZBTFNFLA0KICAgIGhvdmVyaW5mbyA9ICdub25lJw0KICApICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICc8Yj5Dw61yY3VsbyBkZSBDb3JyZWxhY2lvbmVzIEludGVyYWN0aXZvPC9iPicsDQogICAgICBmb250ID0gbGlzdChzaXplID0gMTYpDQogICAgKSwNCiAgICB4YXhpcyA9IGxpc3QoDQogICAgICB0aXRsZSA9IHBhc3RlMCgnUEMxICgnLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMV0sIDEpLCAnJSknKSwNCiAgICAgIHNjYWxlYW5jaG9yID0gInkiLA0KICAgICAgc2NhbGVyYXRpbyA9IDENCiAgICApLA0KICAgIHlheGlzID0gbGlzdCgNCiAgICAgIHRpdGxlID0gcGFzdGUwKCdQQzIgKCcsIHJvdW5kKGVpZy52YWwkdmFyaWFuY2UucGVyY2VudFsyXSwgMSksICclKScpDQogICAgKSwNCiAgICBzaG93bGVnZW5kID0gVFJVRQ0KICApDQoNCiMjIDMuIEJJUExPVCBJTlRFUkFDVElWTyBDT04gQ0xVU1RFUlMNCiMgUHJlcGFyYXIgZGF0b3MgZGUgaW5kaXZpZHVvcyAoY29tdW5hcykNCmluZF9jb29yZCA8LSBhcy5kYXRhLmZyYW1lKHJlcy5wY2EkeFssIDE6Ml0pDQppbmRfY29vcmQkSURfQ09NVU5BIDwtIHJvd25hbWVzKGluZF9jb29yZCkNCmluZF9jb29yZCRDbHVzdGVyIDwtIGFzLmZhY3RvcihrbV9maW5hbCRjbHVzdGVyKQ0KDQojIENvbG9yZXMgcGFyYSBjbHVzdGVycw0KY29sb3Jlc19jbHVzdGVycyA8LSBjKCcjRTMxQTFDJywgJyMxRjc4QjQnLCAnIzMzQTAyQycsICcjRkY3RjAwJywgJyM2QTNEOUEnKVsxOm51bV9jbHVzdGVyc10NCg0KYmlwbG90X2ludGVyYWN0aXZvIDwtIHBsb3RfbHkoKSAlPiUNCiAgIyBJbmRpdmlkdW9zIChjb211bmFzKQ0KICBhZGRfdHJhY2UoDQogICAgZGF0YSA9IGluZF9jb29yZCwNCiAgICB4ID0gflBDMSwNCiAgICB5ID0gflBDMiwNCiAgICB0eXBlID0gJ3NjYXR0ZXInLA0KICAgIG1vZGUgPSAnbWFya2VycycsDQogICAgY29sb3IgPSB+Q2x1c3RlciwNCiAgICBjb2xvcnMgPSBjb2xvcmVzX2NsdXN0ZXJzLA0KICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDEwLCBvcGFjaXR5ID0gMC43LCBsaW5lID0gbGlzdCh3aWR0aCA9IDEsIGNvbG9yID0gJ3doaXRlJykpLA0KICAgIHRleHQgPSB+cGFzdGUoJzxiPkNvbXVuYTo8L2I+JywgSURfQ09NVU5BLA0KICAgICAgICAgICAgICAgICAgJzxicj48Yj5DbHVzdGVyOjwvYj4nLCBDbHVzdGVyLA0KICAgICAgICAgICAgICAgICAgJzxicj48Yj5QQzE6PC9iPicsIHJvdW5kKFBDMSwgMyksDQogICAgICAgICAgICAgICAgICAnPGJyPjxiPlBDMjo8L2I+Jywgcm91bmQoUEMyLCAzKSksDQogICAgaG92ZXJpbmZvID0gJ3RleHQnLA0KICAgIG5hbWUgPSAnQ29tdW5hcycNCiAgKSAlPiUNCiAgIyBWYXJpYWJsZXMNCiAgYWRkX3RyYWNlKA0KICAgIGRhdGEgPSB2YXJfY29vcmQsDQogICAgeCA9IH5QQzEgKiAyLCAgIyBFc2NhbGFyIHBhcmEgbWVqb3IgdmlzdWFsaXphY2nDs24NCiAgICB5ID0gflBDMiAqIDIsDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ21hcmtlcnMrdGV4dCcsDQogICAgdGV4dCA9IH5WYXJpYWJsZSwNCiAgICB0ZXh0cG9zaXRpb24gPSAnbWlkZGxlIGNlbnRlcicsDQogICAgbWFya2VyID0gbGlzdCgNCiAgICAgIHNpemUgPSA4LA0KICAgICAgY29sb3IgPSAnYmxhY2snLA0KICAgICAgc3ltYm9sID0gJ2RpYW1vbmQnDQogICAgKSwNCiAgICB0ZXh0Zm9udCA9IGxpc3QoY29sb3IgPSAnYmxhY2snLCBzaXplID0gMTEpLA0KICAgIGhvdmVyaW5mbyA9ICd0ZXh0JywNCiAgICBob3ZlcnRleHQgPSB+cGFzdGUoJzxiPlZhcmlhYmxlOjwvYj4nLCBWYXJpYWJsZSwNCiAgICAgICAgICAgICAgICAgICAgICAnPGJyPjxiPlBDMTo8L2I+Jywgcm91bmQoUEMxLCAzKSwNCiAgICAgICAgICAgICAgICAgICAgICAnPGJyPjxiPlBDMjo8L2I+Jywgcm91bmQoUEMyLCAzKSksDQogICAgbmFtZSA9ICdWYXJpYWJsZXMnLA0KICAgIHNob3dsZWdlbmQgPSBGQUxTRQ0KICApICU+JQ0KICAjIFZlY3RvcmVzIGRlIHZhcmlhYmxlcw0KICBhZGRfdHJhY2UoDQogICAgZGF0YSA9IHZhcl9jb29yZCwNCiAgICB4ID0gfjAsDQogICAgeSA9IH4wLA0KICAgIHhlbmQgPSB+UEMxICogMiwNCiAgICB5ZW5kID0gflBDMiAqIDIsDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ2xpbmVzJywNCiAgICBsaW5lID0gbGlzdChjb2xvciA9ICdyZ2JhKDAsMCwwLDAuNSknLCB3aWR0aCA9IDEuNSksDQogICAgc2hvd2xlZ2VuZCA9IEZBTFNFLA0KICAgIGhvdmVyaW5mbyA9ICdub25lJw0KICApICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSBsaXN0KA0KICAgICAgdGV4dCA9ICc8Yj5CaXBsb3QgSW50ZXJhY3Rpdm8gLSBDb211bmFzIHkgVmFyaWFibGVzPC9iPicsDQogICAgICBmb250ID0gbGlzdChzaXplID0gMTYpDQogICAgKSwNCiAgICB4YXhpcyA9IGxpc3QoDQogICAgICB0aXRsZSA9IHBhc3RlMCgnUEMxICgnLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMV0sIDEpLCAnJSknKQ0KICAgICksDQogICAgeWF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSBwYXN0ZTAoJ1BDMiAoJywgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzJdLCAxKSwgJyUpJykNCiAgICApLA0KICAgIHNob3dsZWdlbmQgPSBUUlVFLA0KICAgIGxlZ2VuZCA9IGxpc3QoDQogICAgICB0aXRsZSA9IGxpc3QodGV4dCA9ICc8Yj5DbHVzdGVyPC9iPicpDQogICAgKQ0KICApDQoNCiMjIDQuIEhFQVRNQVAgSU5URVJBQ1RJVk8gREUgQ0FSR0FTIFBDQQ0KY2FyZ2FzX21hdHJpeCA8LSBhcy5tYXRyaXgocmVzLnBjYSRyb3RhdGlvblssIDE6bnVtX2NvbXBfZmluYWxdKQ0KDQpoZWF0bWFwX2NhcmdhcyA8LSBwbG90X2x5KA0KICB4ID0gY29sbmFtZXMoY2FyZ2FzX21hdHJpeCksDQogIHkgPSByb3duYW1lcyhjYXJnYXNfbWF0cml4KSwNCiAgeiA9IGNhcmdhc19tYXRyaXgsDQogIHR5cGUgPSAnaGVhdG1hcCcsDQogIGNvbG9yc2NhbGUgPSAnUmRCdScsDQogIHptaWQgPSAwLA0KICBjb2xvcmJhciA9IGxpc3QodGl0bGUgPSAnQ2FyZ2EnKSwNCiAgaG92ZXJpbmZvID0gJ3greSt6JywNCiAgaG92ZXJ0ZW1wbGF0ZSA9IHBhc3RlKA0KICAgICdWYXJpYWJsZTogJXt5fTxicj4nLA0KICAgICdDb21wb25lbnRlOiAle3h9PGJyPicsDQogICAgJ0NhcmdhOiAle3o6LjNmfTxicj4nLA0KICAgICc8ZXh0cmE+PC9leHRyYT4nDQogICkNCikgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gJzxiPkhlYXRtYXAgZGUgQ2FyZ2FzIFBDQTwvYj4nLA0KICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDE2KQ0KICAgICksDQogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0NvbXBvbmVudGVzIFByaW5jaXBhbGVzJyksDQogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1ZhcmlhYmxlcycsIHRpY2thbmdsZSA9IC0zMCksDQogICAgbWFyZ2luID0gbGlzdChsID0gMTUwKQ0KICApDQoNCiMjIDUuIEdSw4FGSUNPIDNEIElOVEVSQUNUSVZPIERFIENPTVBPTkVOVEVTDQppZihudW1fY29tcF9maW5hbCA+PSAzKSB7DQogICMgUHJlcGFyYXIgZGF0b3MgM0QNCiAgY29vcmRfM2QgPC0gYXMuZGF0YS5mcmFtZShyZXMucGNhJHhbLCAxOjNdKQ0KICBjb29yZF8zZCRJRF9DT01VTkEgPC0gcm93bmFtZXMoY29vcmRfM2QpDQogIGNvb3JkXzNkJENsdXN0ZXIgPC0gYXMuZmFjdG9yKGttX2ZpbmFsJGNsdXN0ZXIpDQogIA0KICBwbG90XzNkIDwtIHBsb3RfbHkoDQogICAgZGF0YSA9IGNvb3JkXzNkLA0KICAgIHggPSB+UEMxLA0KICAgIHkgPSB+UEMyLA0KICAgIHogPSB+UEMzLA0KICAgIHR5cGUgPSAnc2NhdHRlcjNkJywNCiAgICBtb2RlID0gJ21hcmtlcnMnLA0KICAgIGNvbG9yID0gfkNsdXN0ZXIsDQogICAgY29sb3JzID0gY29sb3Jlc19jbHVzdGVycywNCiAgICBtYXJrZXIgPSBsaXN0KHNpemUgPSA1LCBvcGFjaXR5ID0gMC44KSwNCiAgICB0ZXh0ID0gfnBhc3RlKCc8Yj5Db211bmE6PC9iPicsIElEX0NPTVVOQSwNCiAgICAgICAgICAgICAgICAgICc8YnI+PGI+Q2x1c3Rlcjo8L2I+JywgQ2x1c3RlciwNCiAgICAgICAgICAgICAgICAgICc8YnI+PGI+UEMxOjwvYj4nLCByb3VuZChQQzEsIDMpLA0KICAgICAgICAgICAgICAgICAgJzxicj48Yj5QQzI6PC9iPicsIHJvdW5kKFBDMiwgMyksDQogICAgICAgICAgICAgICAgICAnPGJyPjxiPlBDMzo8L2I+Jywgcm91bmQoUEMzLCAzKSksDQogICAgaG92ZXJpbmZvID0gJ3RleHQnDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9IGxpc3QoDQogICAgICB0ZXh0ID0gJzxiPlZpc3VhbGl6YWNpw7NuIDNEIC0gUHJpbWVyb3MgMyBDb21wb25lbnRlczwvYj4nLA0KICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDE2KQ0KICAgICksDQogICAgc2NlbmUgPSBsaXN0KA0KICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gcGFzdGUwKCdQQzEgKCcsIHJvdW5kKGVpZy52YWwkdmFyaWFuY2UucGVyY2VudFsxXSwgMSksICclKScpKSwNCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMCgnUEMyICgnLCByb3VuZChlaWcudmFsJHZhcmlhbmNlLnBlcmNlbnRbMl0sIDEpLCAnJSknKSksDQogICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoJ1BDMyAoJywgcm91bmQoZWlnLnZhbCR2YXJpYW5jZS5wZXJjZW50WzNdLCAxKSwgJyUpJykpDQogICAgKQ0KICApDQp9IGVsc2Ugew0KICBwbG90XzNkIDwtIHBsb3RfbHkoKSAlPiUNCiAgICBsYXlvdXQoDQogICAgICB0aXRsZSA9IGxpc3QoDQogICAgICAgIHRleHQgPSAnPGI+VmlzdWFsaXphY2nDs24gM0QgTm8gRGlzcG9uaWJsZTwvYj4nLA0KICAgICAgICBmb250ID0gbGlzdChzaXplID0gMTYpDQogICAgICApLA0KICAgICAgYW5ub3RhdGlvbnMgPSBsaXN0KA0KICAgICAgICBsaXN0KA0KICAgICAgICAgIHRleHQgPSAiU2UgcmVxdWllcmVuIGFsIG1lbm9zIDMgY29tcG9uZW50ZXMgcGFyYSB2aXN1YWxpemFjacOzbiAzRCIsDQogICAgICAgICAgeHJlZiA9ICJwYXBlciIsIHlyZWYgPSAicGFwZXIiLA0KICAgICAgICAgIHggPSAwLjUsIHkgPSAwLjUsIHhhbmNob3IgPSAiY2VudGVyIiwgeWFuY2hvciA9ICJjZW50ZXIiLA0KICAgICAgICAgIHNob3dhcnJvdyA9IEZBTFNFDQogICAgICAgICkNCiAgICAgICkNCiAgICApDQp9DQoNCiMjIDYuIFRBQkxBIElOVEVSQUNUSVZBIERFIENBUkdBUw0KIyBDcmVhciB0YWJsYSBpbnRlcmFjdGl2YSBkZSBjYXJnYXMNCmNhcmdhc19pbnRlcmFjdGl2YSA8LSBjYXJnYXNfbWF0cml4ICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkgJT4lDQogIHJvd25hbWVzX3RvX2NvbHVtbigiVmFyaWFibGUiKSAlPiUNCiAgRFQ6OmRhdGF0YWJsZSgNCiAgICByb3duYW1lcyA9IEZBTFNFLA0KICAgIGV4dGVuc2lvbnMgPSBjKCdCdXR0b25zJywgJ1Njcm9sbGVyJyksDQogICAgb3B0aW9ucyA9IGxpc3QoDQogICAgICBkb20gPSAnQmZydGlwJywNCiAgICAgIGJ1dHRvbnMgPSBjKCdjb3B5JywgJ2NzdicsICdleGNlbCcsICdwZGYnLCAncHJpbnQnKSwNCiAgICAgIHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgIHNjcm9sbFggPSBUUlVFLA0KICAgICAgc2Nyb2xsWSA9ICI0MDBweCIsDQogICAgICBzY3JvbGxlciA9IFRSVUUNCiAgICApLA0KICAgIGNhcHRpb24gPSBodG1sdG9vbHM6OnRhZ3MkY2FwdGlvbigNCiAgICAgIHN0eWxlID0gJ2NhcHRpb24tc2lkZTogdG9wOyB0ZXh0LWFsaWduOiBjZW50ZXI7JywNCiAgICAgIGh0bWx0b29sczo6c3Ryb25nKCdUYWJsYSBJbnRlcmFjdGl2YSBkZSBDYXJnYXMgUENBJykNCiAgICApDQogICkgJT4lDQogIERUOjpmb3JtYXRSb3VuZChjb2x1bW5zID0gMjoobmNvbChjYXJnYXNfbWF0cml4KSsxKSwgZGlnaXRzID0gMykNCg0KIyMgNy4gR1LDgUZJQ08gREUgQ09OVFJJQlVDScOTTiBBQ1VNVUxBREEgSU5URVJBQ1RJVk8NCmNvbnRyaWJfYWN1bXVsYWRhIDwtIHBsb3RfbHkoDQogIHggPSAxOmxlbmd0aChlaWcudmFsJGN1bXVsYXRpdmUudmFyaWFuY2UucGVyY2VudCksDQogIHkgPSBlaWcudmFsJGN1bXVsYXRpdmUudmFyaWFuY2UucGVyY2VudCwNCiAgdHlwZSA9ICdzY2F0dGVyJywNCiAgbW9kZSA9ICdsaW5lcyttYXJrZXJzJywNCiAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzI3QUU2MCcsIHdpZHRoID0gMyksDQogIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDgsIGNvbG9yID0gJyMyN0FFNjAnKSwNCiAgdGV4dCA9IH5wYXN0ZSgnQ29tcG9uZW50ZXM6IDEtJywgMTpsZW5ndGgoZWlnLnZhbCRjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnQpLA0KICAgICAgICAgICAgICAgICc8YnI+VmFyaWFuemEgQWN1bXVsYWRhOicsIHJvdW5kKGVpZy52YWwkY3VtdWxhdGl2ZS52YXJpYW5jZS5wZXJjZW50LCAyKSwgJyUnKSwNCiAgaG92ZXJpbmZvID0gJ3RleHQnDQopICU+JQ0KICBhZGRfdHJhY2UoDQogICAgeCA9IG51bV9jb21wX2ZpbmFsLA0KICAgIHkgPSBlaWcudmFsJGN1bXVsYXRpdmUudmFyaWFuY2UucGVyY2VudFtudW1fY29tcF9maW5hbF0sDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ21hcmtlcnMnLA0KICAgIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDEyLCBjb2xvciA9ICcjRTc0QzNDJywgc3ltYm9sID0gJ3N0YXInKSwNCiAgICBuYW1lID0gcGFzdGUoJ1NlbGVjY2nDs24gKCcsIG51bV9jb21wX2ZpbmFsLCAnIGNvbXAuKScpLA0KICAgIHRleHQgPSBwYXN0ZSgnUHVudG8gZGUgY29ydGU6PGJyPicsIG51bV9jb21wX2ZpbmFsLCAnY29tcG9uZW50ZXM8YnI+JywNCiAgICAgICAgICAgICAgICAgcm91bmQoZWlnLnZhbCRjdW11bGF0aXZlLnZhcmlhbmNlLnBlcmNlbnRbbnVtX2NvbXBfZmluYWxdLCAyKSwgJyUgdmFyaWFuemEnKSwNCiAgICBob3ZlcmluZm8gPSAndGV4dCcNCiAgKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gbGlzdCgNCiAgICAgIHRleHQgPSAnPGI+VmFyaWFuemEgQWN1bXVsYWRhIHBvciBDb21wb25lbnRlczwvYj4nLA0KICAgICAgZm9udCA9IGxpc3Qoc2l6ZSA9IDE2KQ0KICAgICksDQogICAgeGF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAnTsO6bWVybyBkZSBDb21wb25lbnRlcycsDQogICAgICB0aWNrdmFscyA9IDE6bGVuZ3RoKGVpZy52YWwkY3VtdWxhdGl2ZS52YXJpYW5jZS5wZXJjZW50KQ0KICAgICksDQogICAgeWF4aXMgPSBsaXN0KA0KICAgICAgdGl0bGUgPSAnVmFyaWFuemEgQWN1bXVsYWRhICglKScsDQogICAgICByYW5nZSA9IGMoMCwgMTA1KQ0KICAgICksDQogICAgc2hvd2xlZ2VuZCA9IEZBTFNFLA0KICAgIGFubm90YXRpb25zID0gbGlzdCgNCiAgICAgIGxpc3QoDQogICAgICAgIHggPSBudW1fY29tcF9maW5hbCwNCiAgICAgICAgeSA9IGVpZy52YWwkY3VtdWxhdGl2ZS52YXJpYW5jZS5wZXJjZW50W251bV9jb21wX2ZpbmFsXSArIDUsDQogICAgICAgIHRleHQgPSBwYXN0ZShudW1fY29tcF9maW5hbCwgJ2NvbXBvbmVudGVzJyksDQogICAgICAgIHNob3dhcnJvdyA9IFRSVUUsDQogICAgICAgIGFycm93aGVhZCA9IDQsDQogICAgICAgIGFycm93c2l6ZSA9IDEsDQogICAgICAgIGF4ID0gMCwNCiAgICAgICAgYXkgPSAtNDANCiAgICAgICkNCiAgICApDQogICkNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgUEFORUwgREUgQ09OVFJPTCBJTlRFUkFDVElWTw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCIjIyMgUGFuZWwgZGUgR3LDoWZpY29zIEludGVyYWN0aXZvcyBQQ0FcblxuIikNCg0KY2F0KCJBIGNvbnRpbnVhY2nDs24gc2UgcHJlc2VudGFuIGxvcyBncsOhZmljb3MgaW50ZXJhY3Rpdm9zIGRlbCBhbsOhbGlzaXMgZGUgY29tcG9uZW50ZXMgcHJpbmNpcGFsZXM6XG5cbiIpDQoNCiMgTW9zdHJhciBsb3MgZ3LDoWZpY29zIGVuIG9yZGVuDQpjYXQoIiMjIyMgMS4gU2NyZWUgUGxvdCBJbnRlcmFjdGl2b1xuIikNCnNjcmVlX2ludGVyYWN0aXZvDQoNCmNhdCgiXG4jIyMjIDIuIEPDrXJjdWxvIGRlIENvcnJlbGFjaW9uZXMgSW50ZXJhY3Rpdm9cbiIpDQpjaXJjdWxvX2NvcnJlbGFjaW9uZXMNCg0KY2F0KCJcbiMjIyMgMy4gQmlwbG90IEludGVyYWN0aXZvIGNvbiBDbHVzdGVyc1xuIikNCmJpcGxvdF9pbnRlcmFjdGl2bw0KDQpjYXQoIlxuIyMjIyA0LiBIZWF0bWFwIGRlIENhcmdhcyBQQ0FcbiIpDQpoZWF0bWFwX2Nhcmdhcw0KDQpjYXQoIlxuIyMjIyA1LiBWaXN1YWxpemFjacOzbiAzRCBkZSBDb21wb25lbnRlc1xuIikNCnBsb3RfM2QNCg0KY2F0KCJcbiMjIyMgNi4gVmFyaWFuemEgQWN1bXVsYWRhIEludGVyYWN0aXZhXG4iKQ0KY29udHJpYl9hY3VtdWxhZGENCg0KY2F0KCJcbiMjIyMgNy4gVGFibGEgSW50ZXJhY3RpdmEgZGUgQ2FyZ2FzXG4iKQ0KY2FyZ2FzX2ludGVyYWN0aXZhDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZVTkNJT05FUyBERSBFWFBPUlRBQ0nDk04NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgRnVuY2nDs24gcGFyYSBleHBvcnRhciBncsOhZmljb3MgaW50ZXJhY3Rpdm9zDQpleHBvcnRhcl9ncmFmaWNvc19pbnRlcmFjdGl2b3MgPC0gZnVuY3Rpb24oKSB7DQogIGRpcl9pbnRlcmFjdGl2b3MgPC0gZmlsZS5wYXRoKGRpcl9yZXN1bHRhZG9zLCAiR3JhZmljb3NfSW50ZXJhY3Rpdm9zIikNCiAgaWYoIWRpci5leGlzdHMoZGlyX2ludGVyYWN0aXZvcykpIHsNCiAgICBkaXIuY3JlYXRlKGRpcl9pbnRlcmFjdGl2b3MpDQogIH0NCiAgDQogICMgRXhwb3J0YXIgY29tbyBIVE1MDQogIGh0bWx3aWRnZXRzOjpzYXZlV2lkZ2V0KA0KICAgIHNjcmVlX2ludGVyYWN0aXZvLA0KICAgIGZpbGUucGF0aChkaXJfaW50ZXJhY3Rpdm9zLCAiMDFfc2NyZWVfaW50ZXJhY3Rpdm8uaHRtbCIpDQogICkNCiAgDQogIGh0bWx3aWRnZXRzOjpzYXZlV2lkZ2V0KA0KICAgIGNpcmN1bG9fY29ycmVsYWNpb25lcywNCiAgICBmaWxlLnBhdGgoZGlyX2ludGVyYWN0aXZvcywgIjAyX2NpcmN1bG9fY29ycmVsYWNpb25lcy5odG1sIikNCiAgKQ0KICANCiAgaHRtbHdpZGdldHM6OnNhdmVXaWRnZXQoDQogICAgYmlwbG90X2ludGVyYWN0aXZvLA0KICAgIGZpbGUucGF0aChkaXJfaW50ZXJhY3Rpdm9zLCAiMDNfYmlwbG90X2ludGVyYWN0aXZvLmh0bWwiKQ0KICApDQogIA0KICBodG1sd2lkZ2V0czo6c2F2ZVdpZGdldCgNCiAgICBoZWF0bWFwX2NhcmdhcywNCiAgICBmaWxlLnBhdGgoZGlyX2ludGVyYWN0aXZvcywgIjA0X2hlYXRtYXBfY2FyZ2FzLmh0bWwiKQ0KICApDQogIA0KICBpZihudW1fY29tcF9maW5hbCA+PSAzKSB7DQogICAgaHRtbHdpZGdldHM6OnNhdmVXaWRnZXQoDQogICAgICBwbG90XzNkLA0KICAgICAgZmlsZS5wYXRoKGRpcl9pbnRlcmFjdGl2b3MsICIwNV92aXN1YWxpemFjaW9uXzNkLmh0bWwiKQ0KICAgICkNCiAgfQ0KICANCiAgaHRtbHdpZGdldHM6OnNhdmVXaWRnZXQoDQogICAgY29udHJpYl9hY3VtdWxhZGEsDQogICAgZmlsZS5wYXRoKGRpcl9pbnRlcmFjdGl2b3MsICIwNl92YXJpYW56YV9hY3VtdWxhZGEuaHRtbCIpDQogICkNCiAgDQogIGNhdCgi4pyTIEdyw6FmaWNvcyBpbnRlcmFjdGl2b3MgZXhwb3J0YWRvcyBlbjoiLCBkaXJfaW50ZXJhY3Rpdm9zLCAiXG4iKQ0KfQ0KDQojIEVqZWN1dGFyIGV4cG9ydGFjacOzbiAob3BjaW9uYWwpDQojIGV4cG9ydGFyX2dyYWZpY29zX2ludGVyYWN0aXZvcygpDQoNCmNhdCgiXG4jIyMgSW5zdHJ1Y2Npb25lcyBkZSBVc286XG4iKQ0KY2F0KCItICoqSG92ZXIqKjogUGFzZSBlbCBjdXJzb3Igc29icmUgcHVudG9zIHBhcmEgdmVyIGRldGFsbGVzXG4iKQ0KY2F0KCItICoqWm9vbSoqOiBVc2UgZWwgbW91c2UgcGFyYSBoYWNlciB6b29tIGVuIMOhcmVhcyBlc3BlY8OtZmljYXNcbiIpDQpjYXQoIi0gKipTZWxlY2Npw7NuKio6IENsaWNrIHkgYXJyYXN0cmUgcGFyYSBzZWxlY2Npb25hciByZWdpb25lc1xuIikNCmNhdCgiLSAqKlJlc2V0Kio6IERvYmxlIGNsaWNrIHBhcmEgcmVzZXRlYXIgbGEgdmlzdGFcbiIpDQpjYXQoIi0gKipEZXNjYXJnYSoqOiBVc2UgZWwgbWVuw7ogZGUgaGVycmFtaWVudGFzIHBhcmEgZGVzY2FyZ2FyIGltw6FnZW5lc1xuIikNCg0KY2F0KCJcbiMjIyBJbnRlcnByZXRhY2nDs24gSW50ZXJhY3RpdmE6XG4iKQ0KY2F0KCIxLiAqKlNjcmVlIFBsb3QqKjogSWRlbnRpZmlxdWUgY29tcG9uZW50ZXMgY29uIGVpZ2VudmFsdWUgPiAxIChsw61uZWEgcm9qYSlcbiIpDQpjYXQoIjIuICoqQ8OtcmN1bG8gZGUgQ29ycmVsYWNpb25lcyoqOiBWYXJpYWJsZXMgY2VyY2EgZGVsIGPDrXJjdWxvIGVzdMOhbiBiaWVuIHJlcHJlc2VudGFkYXNcbiIpDQpjYXQoIjMuICoqQmlwbG90Kio6IFJlbGFjaW9uZSBjb211bmFzIChwdW50b3MpIGNvbiB2YXJpYWJsZXMgKHZlY3RvcmVzKVxuIikNCmNhdCgiNC4gKipIZWF0bWFwKio6IElkZW50aWZpcXVlIHZhcmlhYmxlcyBtw6FzIGluZmx1eWVudGVzIGVuIGNhZGEgY29tcG9uZW50ZVxuIikNCmNhdCgiNS4gKiozRCoqOiBFeHBsb3JlIHJlbGFjaW9uZXMgdHJpZGltZW5zaW9uYWxlcyBlbnRyZSBjb21wb25lbnRlc1xuIikNCmBgYA0KDQojIyAqKkFuw6FsaXNpcyB0ZXJyaXRvcmlhbCoqDQoNCmBgYHtyLCBmaWcud2lkdGg9MTYsIGZpZy5oZWlnaHQ9MTIsIG91dC53aWR0aD0iMTAwJSJ9DQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBBTsOBTElTSVMgVEVSUklUT1JJQUwgQ09NUExFVE8gWSBNRUpPUkFETyAtIFBST1lFQ1RPUyBBQ0EgRVNUQURPIE3DiVJJREENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgUmVzb2x2ZXIgY29uZmxpY3Rvcw0KY29uZmxpY3RzX3ByZWZlcihkcGx5cjo6Zmlyc3QpDQpjb25mbGljdF9wcmVmZXIoInNlbGVjdCIsICJkcGx5ciIpDQpjb25mbGljdF9wcmVmZXIoImZpbHRlciIsICJkcGx5ciIpDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZBU0UgMTogQ09ORklHVVJBQ0nDk04gRVNUw4lUSUNBIFBST0ZFU0lPTkFMDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIFRlbWEgY2FydG9ncsOhZmljbyBwcm9mZXNpb25hbCBtZWpvcmFkbw0KdGVtYV9tYXBhX3Byb2Zlc2lvbmFsIDwtIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMyYzNlNTAiLCBtYXJnaW4gPSBtYXJnaW4oYiA9IDE1KSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGhqdXN0ID0gMC41LCBjb2xvciA9ICIjMzQ0OTVlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IG1hcmdpbihiID0gMjApKSwNCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBoanVzdCA9IDEsIGNvbG9yID0gIiM3ZjhjOGQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSBtYXJnaW4odCA9IDE1KSksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEyLCBjb2xvciA9ICIjMmMzZTUwIiksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICIjMzQ0OTVlIiksDQogICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgxLjIsICJjbSIpLA0KICAgIGxlZ2VuZC5tYXJnaW4gPSBtYXJnaW4obCA9IDIwKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI2Y4ZjlmYSIsIGNvbG9yID0gTkEpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSBOQSksDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMjUsIDI1LCAyNSwgMjUpLA0KICAgICMgTWVqb3JhIHBhcmEgbG9zIGVsZW1lbnRvcyBkZSBlc2NhbGEgeSBub3J0ZQ0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCkNCiAgKQ0KDQojIFBhbGV0YSBkZSBjb2xvcmVzIHNvZmlzdGljYWRhIHkgY29uc2lzdGVudGUNCmNvbG9yZXNfZXN0YWRvX21lcmlkYSA8LSBjKA0KICAiVXJiYW5hIiA9ICIjMWY3N2I0IiwgICAgICAgICAgICMgQXp1bCBpbnN0aXR1Y2lvbmFsDQogICJSdXJhbCIgPSAiI2Q2MjcyOCIsICAgICAgICAgICAgIyBSb2pvIHRlcnJvc28NCiAgIk1peHRhIiA9ICIjZmY3ZjBlIiwgICAgICAgICAgICAjIE5hcmFuamEgdmlicmFudGUNCiAgIkVuIGNvbnN0cnVjY2nDs24iID0gIiMyY2EwMmMiLCAgIyBWZXJkZSBwcm9ncmVzbw0KICAiTm8gZXNwZWNpZmljYWRvIiA9ICIjOTQ2N2JkIiAgICMgUMO6cnB1cmEgbmV1dHJvDQopDQoNCiMgRnVuY2nDs24gcGFyYSBib3JkZXMgZGVsIGVzdGFkbyBtw6FzIHZpc2libGVzDQpjcmVhcl9ib3JkZV9lc3RhZG8gPC0gZnVuY3Rpb24oc2hhcGVmaWxlX2VzdGFkbykgew0KICBnZW9tX3NmKGRhdGEgPSBzaGFwZWZpbGVfZXN0YWRvLCANCiAgICAgICAgICBmaWxsID0gTkEsIA0KICAgICAgICAgIGNvbG9yID0gIiMzNDQ5NWUiLCANCiAgICAgICAgICBzaXplID0gMS4yLCANCiAgICAgICAgICBsaW5ldHlwZSA9ICJzb2xpZCIpDQp9DQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZBU0UgMjogQ0FSR0EgWSBQUkVQQVJBQ0nDk04gREUgREFUT1MgTUVKT1JBREENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpDQpjYXQoIklOSUNJQU5ETyBBTsOBTElTSVMgVEVSUklUT1JJQUwgSU5URUdSQUwgLSBWRVJTScOTTiBNRUpPUkFEQVxuIikNCmNhdCgiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpDQoNCiMgQ2FyZ2FyIHRvZG9zIGxvcyBzaGFwZWZpbGVzIGNvbiB2ZXJpZmljYWNpw7NuDQpjYXQoIkNhcmdhbmRvIHNoYXBlZmlsZXMgZGVsIEVzdGFkbyBNw6lyaWRhLi4uXG4iKQ0KDQojIDEuIFBhcnJvcXVpYXMgKGJhc2UgcHJpbmNpcGFsKQ0KcGFycm9xdWlhc19zZiA8LSBzdF9yZWFkKCJDOi9Vc2Vycy93aWxsaWFtL0Rlc2t0b3AvbW9ub2dyYWZpYSBhY2EgbWVyaWRhL2RhdG9zL01FUklEQS9EUFRfUEFSUk9RVUlBbC9tZXJpZGEuc2h4IiwgcXVpZXQgPSBUUlVFKQ0KY2F0KCLinJMgUGFycm9xdWlhcyBjYXJnYWRhczoiLCBucm93KHBhcnJvcXVpYXNfc2YpLCAicmVnaXN0cm9zXG4iKQ0KDQojIDIuIE11bmljaXBpb3MNCm11bmljaXBpb3Nfc2YgPC0gc3RfcmVhZCgiQzovVXNlcnMvd2lsbGlhbS9EZXNrdG9wL21vbm9ncmFmaWEgYWNhIG1lcmlkYS9kYXRvcy9NRVJJREEvRFBUX01VTklDSVBBTC9tZXJpZGFfbXVuLnNoeCIsIHF1aWV0ID0gVFJVRSkNCmNhdCgi4pyTIE11bmljaXBpb3MgY2FyZ2Fkb3M6IiwgbnJvdyhtdW5pY2lwaW9zX3NmKSwgInJlZ2lzdHJvc1xuIikNCg0KIyAzLiBDZW50cm9zIHBvYmxhZG9zDQpjZW50cm9zX3NmIDwtIHN0X3JlYWQoIkM6L1VzZXJzL3dpbGxpYW0vRGVza3RvcC9tb25vZ3JhZmlhIGFjYSBtZXJpZGEvZGF0b3MvTUVSSURBL21lcmlkYS5zaHgiLCBxdWlldCA9IFRSVUUpDQpjYXQoIuKckyBDZW50cm9zIHBvYmxhZG9zIGNhcmdhZG9zOiIsIG5yb3coY2VudHJvc19zZiksICJyZWdpc3Ryb3NcbiIpDQoNCiMgNC4gRXN0YWRvIGNvbXBsZXRvIChwYXJhIGJvcmRlcykNCmVzdGFkb3Nfc2YgPC0gc3RfcmVhZCgiQzovVXNlcnMvd2lsbGlhbS9EZXNrdG9wL21vbm9ncmFmaWEgYWNhIG1lcmlkYS9kYXRvcy9NRVJJREEvRFBUX0VTVEFETy92emxhX2VzdGFkb3Muc2h4IiwgcXVpZXQgPSBUUlVFKQ0KbWVyaWRhX2VzdGFkbyA8LSBlc3RhZG9zX3NmICU+JSBmaWx0ZXIoRVNUQURPID09ICJNRVJJREEiKQ0KY2F0KCLinJMgTMOtbWl0ZXMgZXN0YXRhbGVzIGNhcmdhZG9zXG4iKQ0KDQojIFByZXBhcmFyIGRhdG9zIGRlIHByb3llY3RvcyBjb24gbWVqb3Jhcw0KZGZfcmF3JENPRF9VQklHRU8gPC0gYXMuY2hhcmFjdGVyKGRmX3JhdyRDT0RfVUJJR0VPKQ0KDQojIENsYXNpZmljYWNpw7NuIG1lam9yYWRhIGRlIHRpcG9zIGRlIGNvbXVuYQ0KZGZfcmF3IDwtIGRmX3JhdyAlPiUNCiAgbXV0YXRlKA0KICAgIFRpcG9fQ29tdW5hID0gY2FzZV93aGVuKA0KICAgICAgc3RyX2RldGVjdChDT0RfQ0MsICJDLVVSQiIpIH4gIlVyYmFuYSIsDQogICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIkMtUlVSIikgfiAiUnVyYWwiLCANCiAgICAgIHN0cl9kZXRlY3QoQ09EX0NDLCAiQy1NSVgiKSB+ICJNaXh0YSIsDQogICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIl5cXGR7Mn0tXFxkezJ9LVxcZHs0fSQiKSB+ICJFbiBjb25zdHJ1Y2Npw7NuIiwNCiAgICAgIHN0cl9kZXRlY3QoQ09EX0NDLCAiXlxcZHsyfS1cXGR7Mn0tXFxkezJ9IikgfiAiRW4gY29uc3RydWNjacOzbiIsDQogICAgICBzdHJfZGV0ZWN0KENPRF9DQywgIl5DRUMiKSB+ICJFbiBjb25zdHJ1Y2Npw7NuIiwNCiAgICAgIFRSVUUgfiAiTm8gZXNwZWNpZmljYWRvIg0KICAgICksDQogICAgIyBWYXJpYWJsZXMgYXV4aWxpYXJlcyBwYXJhIGFuw6FsaXNpcyB0ZXJyaXRvcmlhbA0KICAgIENvZGlnb19NdW5pY2lwYWwgPSBzdHJfc3ViKENPRF9VQklHRU8sIDEsIDQpLA0KICAgIEludGVuc2lkYWRfUHJveWVjdG9zID0gY2FzZV93aGVuKA0KICAgICAgbl9wcm95ZWN0b3MgPj0gNCB+ICJBbHRhICg0KykiLA0KICAgICAgbl9wcm95ZWN0b3MgPT0gMyB+ICJNZWRpYSAoMykiLA0KICAgICAgbl9wcm95ZWN0b3MgPD0gMiB+ICJCYWphICjiiaQyKSINCiAgICApLA0KICAgIEVmZWN0aXZpZGFkX0NhdGVnb3JpYSA9IGNhc2Vfd2hlbigNCiAgICAgIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8gPj0gNCB+ICJNdXkgQWx0YSIsDQogICAgICBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPID09IDMgfiAiQWx0YSIsDQogICAgICBSQVRJT19BQ0FfUFJPWUVDVE9fQ1VMTUlOQURPID09IDIgfiAiTWVkaWEiLCANCiAgICAgIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8gPT0gMSB+ICJCYWphIg0KICAgICkNCiAgKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGQVNFIDM6IE1BUEFTIELDgVNJQ09TIE1FSk9SQURPUyBDT04gQk9SREVTIERFTCBFU1RBRE8NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiXG4tLS0gQ1JFQU5ETyBNQVBBUyBCw4FTSUNPUyBNRUpPUkFET1MgLS0tXG4iKQ0KDQojIFVuacOzbiBwcmluY2lwYWwgY29uIGVzdGFkw61zdGljYXMgbWVqb3JhZGFzDQpwYXJyb3F1aWFzX3Byb3llY3RvcyA8LSBwYXJyb3F1aWFzX3NmICU+JQ0KICBsZWZ0X2pvaW4oZGZfcmF3LCBieSA9IGMoIklEIiA9ICJDT0RfVUJJR0VPIikpICU+JQ0KICAjIEFncmVnYXIgZXN0YWTDrXN0aWNhcyBwb3IgcGFycm9xdWlhDQogIGdyb3VwX2J5KElEKSAlPiUNCiAgbXV0YXRlKA0KICAgIHByb3llY3Rvc19wYXJyb3F1aWEgPSBuKCksDQogICAgZGl2ZXJzaWRhZF90aXBvbG9naWFzID0gbl9kaXN0aW5jdChDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcsIG5hLnJtID0gVFJVRSksDQogICAgcmF0aW9fcHJvbWVkaW8gPSBtZWFuKFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIG5hLnJtID0gVFJVRSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgTUFQQSAxOiBEaXN0cmlidWNpw7NuIGRlIHByb3llY3RvcyBjb24gYm9yZGVzIG1lam9yYWRvcw0KbWFwYV9kaXN0cmlidWNpb25fcHJvIDwtIGdncGxvdCgpICsNCiAgIyBCYXNlOiBQYXJyb3F1aWFzIGNvbiBwcm95ZWN0b3MNCiAgZ2VvbV9zZihkYXRhID0gcGFycm9xdWlhc19wcm95ZWN0b3MsIA0KICAgICAgICAgIGFlcyhmaWxsID0gbl9wcm95ZWN0b3MpLCANCiAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIA0KICAgICAgICAgIHNpemUgPSAwLjIpICsNCiAgIyBCb3JkZSBkZWwgRXN0YWRvIE3DqXJpZGEgbcOhcyB2aXNpYmxlDQogIGdlb21fc2YoZGF0YSA9IG1lcmlkYV9lc3RhZG8sIA0KICAgICAgICAgIGZpbGwgPSBOQSwgDQogICAgICAgICAgY29sb3IgPSAiIzJjM2U1MCIsIA0KICAgICAgICAgIHNpemUgPSAxLjUsIA0KICAgICAgICAgIGxpbmV0eXBlID0gInNvbGlkIikgKw0KICAjIEVzY2FsYSBkZSBjb2xvcmVzIG1lam9yYWRhDQogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKA0KICAgIG5hbWUgPSAiTsKwIFByb3llY3Rvc1xuQUNBIiwNCiAgICBvcHRpb24gPSAicGxhc21hIiwNCiAgICBuYS52YWx1ZSA9ICJncmV5OTUiLA0KICAgIHRyYW5zID0gInNxcnQiLA0KICAgIGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDUpLA0KICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHJvdW5kKHgsIDApLA0KICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoDQogICAgICB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgYmFyd2lkdGggPSAxLjUsDQogICAgICBiYXJoZWlnaHQgPSAxMiwNCiAgICAgIGZyYW1lLmNvbG91ciA9ICIjMzQ0OTVlIiwNCiAgICAgIGZyYW1lLmxpbmV3aWR0aCA9IDAuNQ0KICAgICkNCiAgKSArDQogICMgRWxlbWVudG9zIGNhcnRvZ3LDoWZpY29zIG1lam9yYWRvcw0KICBhbm5vdGF0aW9uX3NjYWxlKA0KICAgIGxvY2F0aW9uID0gImJyIiwgDQogICAgd2lkdGhfaGludCA9IDAuMywNCiAgICB0ZXh0X2NleCA9IDEuMSwNCiAgICB0ZXh0X2ZhY2UgPSAiYm9sZCIsDQogICAgdGV4dF9jb2wgPSAiIzJjM2U1MCIsDQogICAgYmFyX2NvbHMgPSBjKCIjMmMzZTUwIiwgIndoaXRlIikNCiAgKSArDQogIGFubm90YXRpb25fbm9ydGhfYXJyb3coDQogICAgbG9jYXRpb24gPSAidGwiLCANCiAgICBzdHlsZSA9IG5vcnRoX2Fycm93X2ZhbmN5X29yaWVudGVlcmluZywNCiAgICBoZWlnaHQgPSB1bml0KDEuOCwgImNtIiksIA0KICAgIHdpZHRoID0gdW5pdCgxLjgsICJjbSIpDQogICkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gVGVycml0b3JpYWwgZGUgUHJveWVjdG9zIEFDQSIsDQogICAgc3VidGl0bGUgPSAiRXN0YWRvIE3DqXJpZGEgcG9yIFBhcnJvcXVpYSAoMjAxOS0yMDI1KSDigKIgQW7DoWxpc2lzIGRlIENvYmVydHVyYSBUZXJyaXRvcmlhbCIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVsYWJvcmFjacOzbiBwcm9waWEg4oCiIFdpbGxpYW0gQS4gR3V0acOpcnJleiBWLiDigKIgRGF0b3M6IEFnZW5kYXMgQ29uY3JldGFzIGRlIEFjY2nDs24iDQogICkgKw0KICB0ZW1hX21hcGFfcHJvZmVzaW9uYWwNCg0KcHJpbnQobWFwYV9kaXN0cmlidWNpb25fcHJvKQ0KDQojIE1BUEEgMjogRWZlY3RpdmlkYWQgdGVycml0b3JpYWwgY29uIG1lam9yYXMNCm1hcGFfZWZlY3RpdmlkYWRfcHJvIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gcGFycm9xdWlhc19wcm95ZWN0b3MsIA0KICAgICAgICAgIGFlcyhmaWxsID0gUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETyksIA0KICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgDQogICAgICAgICAgc2l6ZSA9IDAuMikgKw0KICBnZW9tX3NmKGRhdGEgPSBtZXJpZGFfZXN0YWRvLCANCiAgICAgICAgICBmaWxsID0gTkEsIA0KICAgICAgICAgIGNvbG9yID0gIiMyYzNlNTAiLCANCiAgICAgICAgICBzaXplID0gMS41KSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKA0KICAgIG5hbWUgPSAiUmF0aW8gZGVcbkVmZWN0aXZpZGFkIiwNCiAgICBsb3cgPSAiI2Q3MzAyNyIsIA0KICAgIG1pZCA9ICIjZmVlMDhiIiwgDQogICAgaGlnaCA9ICIjMWE5ODUwIiwNCiAgICBtaWRwb2ludCA9IDIuNSwNCiAgICBuYS52YWx1ZSA9ICJncmV5OTUiLA0KICAgIGJyZWFrcyA9IDE6NCwNCiAgICBsYWJlbHMgPSBjKCJCYWphICgxKSIsICJNZWRpYSAoMikiLCAiQWx0YSAoMykiLCAiTXV5IEFsdGEgKDQpIiksDQogICAgZ3VpZGUgPSBndWlkZV9jb2xvcmJhcigNCiAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBiYXJ3aWR0aCA9IDEuNSwNCiAgICAgIGJhcmhlaWdodCA9IDEyLA0KICAgICAgZnJhbWUuY29sb3VyID0gIiMzNDQ5NWUiLA0KICAgICAgZnJhbWUubGluZXdpZHRoID0gMC41DQogICAgKQ0KICApICsNCiAgYW5ub3RhdGlvbl9zY2FsZShsb2NhdGlvbiA9ICJiciIsIHdpZHRoX2hpbnQgPSAwLjMsIHRleHRfY2V4ID0gMS4xLCB0ZXh0X2ZhY2UgPSAiYm9sZCIpICsNCiAgYW5ub3RhdGlvbl9ub3J0aF9hcnJvdyhsb2NhdGlvbiA9ICJ0bCIsIHN0eWxlID0gbm9ydGhfYXJyb3dfZmFuY3lfb3JpZW50ZWVyaW5nLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHVuaXQoMS44LCAiY20iKSwgd2lkdGggPSB1bml0KDEuOCwgImNtIikpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJFZmVjdGl2aWRhZCBUZXJyaXRvcmlhbCBkZSBQcm95ZWN0b3MgQUNBIiwNCiAgICBzdWJ0aXRsZSA9ICJSYXRpbyBkZSBDdWxtaW5hY2nDs24gcG9yIFBhcnJvcXVpYSDigKIgQW7DoWxpc2lzIGRlIFJlc3VsdGFkb3MiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIOKAoiBXaWxsaWFtIEEuIEd1dGnDqXJyZXogVi4g4oCiIEVzY2FsYTogMSAoQmFqYSkgYSA0IChNdXkgQWx0YSkiDQogICkgKw0KICB0ZW1hX21hcGFfcHJvZmVzaW9uYWwNCg0KcHJpbnQobWFwYV9lZmVjdGl2aWRhZF9wcm8pDQoNCiMgTUFQQSAzOiBUaXBvcyBkZSBjb211bmEgY29uIGVzdGFkw61zdGljYXMgaW50ZWdyYWRhcw0KbWFwYV90aXBvc19jb211bmFfcHJvIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gcGFycm9xdWlhc19wcm95ZWN0b3MgJT4lIGZpbHRlcighaXMubmEoVGlwb19Db211bmEpKSwgDQogICAgICAgICAgYWVzKGZpbGwgPSBUaXBvX0NvbXVuYSksIA0KICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgDQogICAgICAgICAgc2l6ZSA9IDAuMikgKw0KICBnZW9tX3NmKGRhdGEgPSBtZXJpZGFfZXN0YWRvLCANCiAgICAgICAgICBmaWxsID0gTkEsIA0KICAgICAgICAgIGNvbG9yID0gIiMyYzNlNTAiLCANCiAgICAgICAgICBzaXplID0gMS41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIG5hbWUgPSAiVGlwbyBkZVxuQ29tdW5hIiwNCiAgICB2YWx1ZXMgPSBjb2xvcmVzX2VzdGFkb19tZXJpZGEsDQogICAgbmEudmFsdWUgPSAiZ3JleTk1IiwNCiAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgNCiAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBrZXl3aWR0aCA9IHVuaXQoMS41LCAiY20iKSwNCiAgICAgIGtleWhlaWdodCA9IHVuaXQoMSwgImNtIiksDQogICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAwKQ0KICAgICkNCiAgKSArDQogIGFubm90YXRpb25fc2NhbGUobG9jYXRpb24gPSAiYnIiLCB3aWR0aF9oaW50ID0gMC4zLCB0ZXh0X2NleCA9IDEuMSwgdGV4dF9mYWNlID0gImJvbGQiKSArDQogIGFubm90YXRpb25fbm9ydGhfYXJyb3cobG9jYXRpb24gPSAidGwiLCBzdHlsZSA9IG5vcnRoX2Fycm93X2ZhbmN5X29yaWVudGVlcmluZywNCiAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSB1bml0KDEuOCwgImNtIiksIHdpZHRoID0gdW5pdCgxLjgsICJjbSIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ2xhc2lmaWNhY2nDs24gVGVycml0b3JpYWwgZGUgQ29tdW5hcyIsDQogICAgc3VidGl0bGUgPSAiVGlwb2xvZ8OtYSBPcmdhbml6YWNpb25hbCBkZWwgRXN0YWRvIE3DqXJpZGEg4oCiIEFuw6FsaXNpcyBJbnN0aXR1Y2lvbmFsIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSDigKIgQ2xhc2lmaWNhY2nDs24gYmFzYWRhIGVuIGPDs2RpZ29zIGRlIGNvbXVuYSINCiAgKSArDQogIHRlbWFfbWFwYV9wcm9mZXNpb25hbA0KDQpwcmludChtYXBhX3RpcG9zX2NvbXVuYV9wcm8pDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIEZBU0UgNDogTUFQQVMgQVZBTlpBRE9TIFkgQU7DgUxJU0lTIE1VTFRJLUVTQ0FMQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbi0tLSBDUkVBTkRPIE1BUEFTIEFWQU5aQURPUyAtLS1cbiIpDQoNCiMgTUFQQSA0OiBBbsOhbGlzaXMgbXVuaWNpcGFsIGNvbiBwb2JsYWNpw7NuDQpkYXRvc19tdW5pY2lwYWxlcyA8LSBkZl9yYXcgJT4lDQogIG11dGF0ZShDb2RpZ29fTXVuaWNpcGFsID0gc3RyX3N1YihDT0RfVUJJR0VPLCAxLCA0KSkgJT4lDQogIGdyb3VwX2J5KENvZGlnb19NdW5pY2lwYWwpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgdG90YWxfcHJveWVjdG9zID0gbigpLA0KICAgIHRvdGFsX2NvbXVuYXMgPSBuX2Rpc3RpbmN0KElEX0NPTVVOQSksDQogICAgcmF0aW9fcHJvbWVkaW8gPSBtZWFuKFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIG5hLnJtID0gVFJVRSksDQogICAgdGlwb19jb211bmFfZG9taW5hbnRlID0gbmFtZXMoc29ydCh0YWJsZShUaXBvX0NvbXVuYSksIGRlY3JlYXNpbmcgPSBUUlVFKSlbMV0sDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCm11bmljaXBpb3NfZW5yaXF1ZWNpZG9zIDwtIG11bmljaXBpb3Nfc2YgJT4lDQogIGxlZnRfam9pbihkYXRvc19tdW5pY2lwYWxlcywgYnkgPSBjKCJJRF9NVU5JQ0lQIiA9ICJDb2RpZ29fTXVuaWNpcGFsIikpDQoNCm1hcGFfbXVuaWNpcGFsX3BybyA8LSBnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YSA9IG11bmljaXBpb3NfZW5yaXF1ZWNpZG9zLCANCiAgICAgICAgICBhZXMoZmlsbCA9IHRvdGFsX3Byb3llY3RvcyksIA0KICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgDQogICAgICAgICAgc2l6ZSA9IDAuNCkgKw0KICBnZW9tX3NmKGRhdGEgPSBtZXJpZGFfZXN0YWRvLCANCiAgICAgICAgICBmaWxsID0gTkEsIA0KICAgICAgICAgIGNvbG9yID0gIiMyYzNlNTAiLCANCiAgICAgICAgICBzaXplID0gMS41KSArDQogIGdlb21fc2ZfdGV4dChkYXRhID0gbXVuaWNpcGlvc19lbnJpcXVlY2lkb3MgJT4lIGZpbHRlcighaXMubmEodG90YWxfcHJveWVjdG9zKSksIA0KICAgICAgICAgICAgICAgYWVzKGxhYmVsID0gc3RyX3dyYXAoRklSU1RfTVVOSSwgMTIpKSwgDQogICAgICAgICAgICAgICBzaXplID0gMywgY29sb3IgPSAiIzJjM2U1MCIsIGZvbnRmYWNlID0gImJvbGQiLA0KICAgICAgICAgICAgICAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIoDQogICAgbmFtZSA9ICJQcm95ZWN0b3NcbkFDQSIsDQogICAgbG93ID0gIiNlZmYzZmYiLCANCiAgICBtaWQgPSAiIzZiYWVkNiIsIA0KICAgIGhpZ2ggPSAiIzA4NTE5YyIsDQogICAgbWlkcG9pbnQgPSBtZWRpYW4obXVuaWNpcGlvc19lbnJpcXVlY2lkb3MkdG90YWxfcHJveWVjdG9zLCBuYS5ybSA9IFRSVUUpLA0KICAgIG5hLnZhbHVlID0gImdyZXk5NSIsDQogICAgZ3VpZGUgPSBndWlkZV9jb2xvcmJhcigNCiAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBiYXJ3aWR0aCA9IDEuNSwNCiAgICAgIGJhcmhlaWdodCA9IDEyDQogICAgKQ0KICApICsNCiAgYW5ub3RhdGlvbl9zY2FsZShsb2NhdGlvbiA9ICJiciIsIHdpZHRoX2hpbnQgPSAwLjMsIHRleHRfY2V4ID0gMS4xLCB0ZXh0X2ZhY2UgPSAiYm9sZCIpICsNCiAgYW5ub3RhdGlvbl9ub3J0aF9hcnJvdyhsb2NhdGlvbiA9ICJ0bCIsIHN0eWxlID0gbm9ydGhfYXJyb3dfZmFuY3lfb3JpZW50ZWVyaW5nLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHVuaXQoMS44LCAiY20iKSwgd2lkdGggPSB1bml0KDEuOCwgImNtIikpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidWNpw7NuIE11bmljaXBhbCBkZSBQcm95ZWN0b3MgQUNBIiwNCiAgICBzdWJ0aXRsZSA9ICJBbsOhbGlzaXMgUmVnaW9uYWwg4oCiIDIzIE11bmljaXBpb3MgZGVsIEVzdGFkbyBNw6lyaWRhIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSDigKIgSW5jbHV5ZSBub21icmVzIG11bmljaXBhbGVzIHBhcmEgcmVmZXJlbmNpYSBnZW9ncsOhZmljYSINCiAgKSArDQogIHRlbWFfbWFwYV9wcm9mZXNpb25hbA0KDQpwcmludChtYXBhX211bmljaXBhbF9wcm8pDQoNCiMgTUFQQSA1OiBNYXBhIGRlIGRlbnNpZGFkIGNvbiBjZW50cm9zIHBvYmxhZG9zDQpjZW50cm9zX2Nvbl9kYXRvcyA8LSBjZW50cm9zX3NmICU+JQ0KICBtdXRhdGUoDQogICAgQ09EX1BBUlJPUVVJQSA9IHN0cl9wYWQoc3RyX3N1Yihhcy5jaGFyYWN0ZXIoQ09ESUdPX0NQKSwgMSwgNiksIDYsIHBhZCA9ICIwIikNCiAgKSAlPiUNCiAgbGVmdF9qb2luKA0KICAgIHBhcnJvcXVpYXNfcHJveWVjdG9zICU+JSANCiAgICAgIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUNCiAgICAgIGdyb3VwX2J5KElEKSAlPiUNCiAgICAgIHN1bW1hcmlzZSgNCiAgICAgICAgcHJveWVjdG9zX3BhcnJvcXVpYSA9IGZpcnN0KG5fcHJveWVjdG9zKSwNCiAgICAgICAgZWZlY3RpdmlkYWRfcGFycm9xdWlhID0gZmlyc3QoUkFUSU9fQUNBX1BST1lFQ1RPX0NVTE1JTkFETyksDQogICAgICAgIHRpcG9fY29tdW5hX3BhcnJvcXVpYSA9IGZpcnN0KFRpcG9fQ29tdW5hKSwNCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgKSwNCiAgICBieSA9IGMoIkNPRF9QQVJST1FVSUEiID0gIklEIikNCiAgKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShwcm95ZWN0b3NfcGFycm9xdWlhKSkNCg0KbWFwYV9kZW5zaWRhZF9wcm8gPC0gZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBwYXJyb3F1aWFzX3Byb3llY3RvcywgDQogICAgICAgICAgYWVzKGZpbGwgPSBuX3Byb3llY3RvcyksIA0KICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgDQogICAgICAgICAgc2l6ZSA9IDAuMSwgDQogICAgICAgICAgYWxwaGEgPSAwLjcpICsNCiAgZ2VvbV9zZihkYXRhID0gY2VudHJvc19jb25fZGF0b3MsIA0KICAgICAgICAgIGFlcyhzaXplID0gcHJveWVjdG9zX3BhcnJvcXVpYSwgDQogICAgICAgICAgICAgIGNvbG9yID0gZWZlY3RpdmlkYWRfcGFycm9xdWlhKSwgDQogICAgICAgICAgYWxwaGEgPSAwLjgpICsNCiAgZ2VvbV9zZihkYXRhID0gbWVyaWRhX2VzdGFkbywgDQogICAgICAgICAgZmlsbCA9IE5BLCANCiAgICAgICAgICBjb2xvciA9ICIjMmMzZTUwIiwgDQogICAgICAgICAgc2l6ZSA9IDEuNSkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYygNCiAgICBuYW1lID0gIlByb3llY3Rvc1xuKEJhc2UpIiwNCiAgICBvcHRpb24gPSAicGxhc21hIiwNCiAgICBuYS52YWx1ZSA9ICJncmV5OTUiLA0KICAgIHRyYW5zID0gInNxcnQiLA0KICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoDQogICAgICB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgYmFyd2lkdGggPSAxLA0KICAgICAgYmFyaGVpZ2h0ID0gOA0KICAgICkNCiAgKSArDQogIHNjYWxlX3NpemVfY29udGludW91cygNCiAgICBuYW1lID0gIkludGVuc2lkYWRcbihQdW50b3MpIiwNCiAgICByYW5nZSA9IGMoMSwgNCksDQogICAgZ3VpZGUgPSBndWlkZV9sZWdlbmQoDQogICAgICB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgb3ZlcnJpZGUuYWVzID0gbGlzdChjb2xvciA9ICIjMmMzZTUwIikNCiAgICApDQogICkgKw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudDIoDQogICAgbmFtZSA9ICJFZmVjdGl2aWRhZFxuKENvbG9yKSIsDQogICAgbG93ID0gIiNkNzMwMjciLCANCiAgICBtaWQgPSAiI2ZlZTA4YiIsIA0KICAgIGhpZ2ggPSAiIzFhOTg1MCIsDQogICAgbWlkcG9pbnQgPSAyLjUsDQogICAgZ3VpZGUgPSBndWlkZV9jb2xvcmJhcigNCiAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsDQogICAgICBiYXJ3aWR0aCA9IDEsDQogICAgICBiYXJoZWlnaHQgPSA4DQogICAgKQ0KICApICsNCiAgYW5ub3RhdGlvbl9zY2FsZShsb2NhdGlvbiA9ICJiciIsIHdpZHRoX2hpbnQgPSAwLjI1LCB0ZXh0X2NleCA9IDEsIHRleHRfZmFjZSA9ICJib2xkIikgKw0KICBhbm5vdGF0aW9uX25vcnRoX2Fycm93KGxvY2F0aW9uID0gInRsIiwgc3R5bGUgPSBub3J0aF9hcnJvd19mYW5jeV9vcmllbnRlZXJpbmcsDQogICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gdW5pdCgxLjUsICJjbSIpLCB3aWR0aCA9IHVuaXQoMS41LCAiY20iKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkFuw6FsaXNpcyBNdWx0aS1lc2NhbGE6IFBhcnJvcXVpYXMgeSBDZW50cm9zIFBvYmxhZG9zIiwNCiAgICBzdWJ0aXRsZSA9ICJEZW5zaWRhZCBUZXJyaXRvcmlhbCDigKIgRG9ibGUgUmVwcmVzZW50YWNpw7NuIEVzcGFjaWFsIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSDigKIgQmFzZTogUGFycm9xdWlhcywgT3ZlcmxheTogQ2VudHJvcyBwb2JsYWRvcyINCiAgKSArDQogIHRlbWFfbWFwYV9wcm9mZXNpb25hbCArDQogIHRoZW1lKGxlZ2VuZC5ib3ggPSAidmVydGljYWwiKQ0KDQpwcmludChtYXBhX2RlbnNpZGFkX3BybykNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSA1OiBNQVBBUyBDT01QTEVNRU5UQVJJT1MgQ09OIE5VRVZPUyBBTsOBTElTSVMNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgTUFQQSA2OiBEaXZlcnNpZGFkIGRlIHRpcG9sb2fDrWFzIHBvciB0ZXJyaXRvcmlvDQpkaXZlcnNpZGFkX3BhcnJvcXVpYWwgPC0gcGFycm9xdWlhc19wcm95ZWN0b3MgJT4lDQogIHN0X2Ryb3BfZ2VvbWV0cnkoKSAlPiUNCiAgZmlsdGVyKCFpcy5uYShDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcpKSAlPiUNCiAgZ3JvdXBfYnkoSUQsIFBBUlJPUVVJQSwgTVVOSUNJUElPKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG5fcHJveWVjdG9zID0gbigpLA0KICAgIGRpdmVyc2lkYWRfdGlwb2xvZ2lhcyA9IG5fZGlzdGluY3QoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHKSwNCiAgICBzaGFubm9uX3RpcG9sb2dpYSA9IHZlZ2FuOjpkaXZlcnNpdHkodGFibGUoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHKSksDQogICAgdGlwb2xvZ2lhX3ByaW5jaXBhbCA9IG5hbWVzKHNvcnQodGFibGUoQ0xBU0lGSUNBQ0nDk05fREVMX05VRE9fQ1JJVElDT19USVBPTE9HSUFfQ0ZHKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY3JlYXNpbmcgPSBUUlVFKSlbMV0sDQogICAgLmdyb3VwcyA9ICJkcm9wIg0KICApDQoNCnBhcnJvcXVpYXNfZGl2ZXJzaWRhZCA8LSBwYXJyb3F1aWFzX3NmICU+JQ0KICBsZWZ0X2pvaW4oZGl2ZXJzaWRhZF9wYXJyb3F1aWFsLCBieSA9ICJJRCIpDQoNCm1hcGFfZGl2ZXJzaWRhZF9wcm8gPC0gZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBwYXJyb3F1aWFzX2RpdmVyc2lkYWQsIA0KICAgICAgICAgIGFlcyhmaWxsID0gc2hhbm5vbl90aXBvbG9naWEpLCANCiAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIA0KICAgICAgICAgIHNpemUgPSAwLjIpICsNCiAgZ2VvbV9zZihkYXRhID0gbWVyaWRhX2VzdGFkbywgDQogICAgICAgICAgZmlsbCA9IE5BLCANCiAgICAgICAgICBjb2xvciA9ICIjMmMzZTUwIiwgDQogICAgICAgICAgc2l6ZSA9IDEuNSkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYygNCiAgICBuYW1lID0gIkRpdmVyc2lkYWRcblNoYW5ub25cbihIJykiLA0KICAgIG9wdGlvbiA9ICJjaXZpZGlzIiwNCiAgICBuYS52YWx1ZSA9ICJncmV5OTUiLA0KICAgIGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDUpLA0KICAgIGd1aWRlID0gZ3VpZGVfY29sb3JiYXIoDQogICAgICB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLA0KICAgICAgYmFyd2lkdGggPSAxLjUsDQogICAgICBiYXJoZWlnaHQgPSAxMg0KICAgICkNCiAgKSArDQogIGFubm90YXRpb25fc2NhbGUobG9jYXRpb24gPSAiYnIiLCB3aWR0aF9oaW50ID0gMC4zLCB0ZXh0X2NleCA9IDEuMSwgdGV4dF9mYWNlID0gImJvbGQiKSArDQogIGFubm90YXRpb25fbm9ydGhfYXJyb3cobG9jYXRpb24gPSAidGwiLCBzdHlsZSA9IG5vcnRoX2Fycm93X2ZhbmN5X29yaWVudGVlcmluZywNCiAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSB1bml0KDEuOCwgImNtIiksIHdpZHRoID0gdW5pdCgxLjgsICJjbSIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGl2ZXJzaWRhZCBkZSBOdWRvcyBDcsOtdGljb3MgcG9yIFRlcnJpdG9yaW8iLA0KICAgIHN1YnRpdGxlID0gIsONbmRpY2UgZGUgU2hhbm5vbiBwYXJhIFRpcG9sb2fDrWFzIENGRyDigKIgQW7DoWxpc2lzIGRlIFZhcmllZGFkIFRlbcOhdGljYSIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVsYWJvcmFjacOzbiBwcm9waWEg4oCiIFZhbG9yZXMgYWx0b3MgPSBtYXlvciBkaXZlcnNpZGFkIHByb2JsZW3DoXRpY2EiDQogICkgKw0KICB0ZW1hX21hcGFfcHJvZmVzaW9uYWwNCg0KcHJpbnQobWFwYV9kaXZlcnNpZGFkX3BybykNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgRkFTRSA2OiBQQU5FTCBJTlRFR1JBRE8gWSBDT01QQVJBVElWTw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJcbi0tLSBDUkVBTkRPIFBBTkVMIENPTVBBUkFUSVZPIEZJTkFMIC0tLVxuIikNCg0KIyBDcmVhciBwYW5lbCBkZSAyeDMgY29uIGxvcyBtZWpvcmVzIG1hcGFzDQpwYW5lbF90ZXJyaXRvcmlhbCA8LSAobWFwYV9kaXN0cmlidWNpb25fcHJvICsgbWFwYV9lZmVjdGl2aWRhZF9wcm8pIC8gDQogICAgICAgICAgICAgICAgICAgIChtYXBhX3RpcG9zX2NvbXVuYV9wcm8gKyBtYXBhX211bmljaXBhbF9wcm8pIC8NCiAgICAgICAgICAgICAgICAgICAgKG1hcGFfZGVuc2lkYWRfcHJvICsgbWFwYV9kaXZlcnNpZGFkX3BybykNCg0KcGFuZWxfdGVycml0b3JpYWwgPC0gcGFuZWxfdGVycml0b3JpYWwgKyANCiAgcGxvdF9hbm5vdGF0aW9uKA0KICAgIHRpdGxlID0gIkFOw4FMSVNJUyBURVJSSVRPUklBTCBJTlRFR1JBTCAtIFBST1lFQ1RPUyBBQ0EgRVNUQURPIE3DiVJJREEiLA0KICAgIHN1YnRpdGxlID0gIkRpc3RyaWJ1Y2nDs24sIEVmZWN0aXZpZGFkLCBUaXBvbG9nw61hcyB5IEFuw6FsaXNpcyBNdWx0aS1lc2NhbGEiLA0KICAgIGNhcHRpb24gPSAiRWxhYm9yYWNpw7NuOiBXaWxsaWFtIEEuIEd1dGnDqXJyZXogVi4gfCBGdWVudGU6IEFnZW5kYXMgQ29uY3JldGFzIGRlIEFjY2nDs24gMjAxOS0yMDI1IiwNCiAgICB0aGVtZSA9IHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41LCBjb2xvciA9ICIjMmMzZTUwIiksDQogICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgaGp1c3QgPSAwLjUsIGNvbG9yID0gIiMzNDQ5NWUiKSwNCiAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGhqdXN0ID0gMSwgY29sb3IgPSAiIzdmOGM4ZCIpDQogICAgKQ0KICApDQoNCnByaW50KHBhbmVsX3RlcnJpdG9yaWFsKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyBGQVNFIDc6IEVTVEFEw41TVElDQVMgWSBSRVNVTUVOIEZJTkFMDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlxuLS0tIEdFTkVSQU5ETyBFU1RBRMONU1RJQ0FTIFRFUlJJVE9SSUFMRVMgLS0tXG4iKQ0KDQojIEVzdGFkw61zdGljYXMgY29tcHJlaGVuc2l2YXMNCmVzdGFkaXN0aWNhc190ZXJyaXRvcmlhbGVzIDwtIGxpc3QoDQogIGNvYmVydHVyYV9nZW5lcmFsID0gcGFycm9xdWlhc19wcm95ZWN0b3MgJT4lDQogICAgc3RfZHJvcF9nZW9tZXRyeSgpICU+JQ0KICAgIHN1bW1hcmlzZSgNCiAgICAgIHRvdGFsX3BhcnJvcXVpYXMgPSBuX2Rpc3RpbmN0KElEKSwNCiAgICAgIHBhcnJvcXVpYXNfY29uX3Byb3llY3RvcyA9IHN1bSghaXMubmEobl9wcm95ZWN0b3MpKSwNCiAgICAgIGNvYmVydHVyYV9wY3QgPSByb3VuZChwYXJyb3F1aWFzX2Nvbl9wcm95ZWN0b3MgLyB0b3RhbF9wYXJyb3F1aWFzICogMTAwLCAxKSwNCiAgICAgIHRvdGFsX3Byb3llY3RvcyA9IHN1bShuX3Byb3llY3RvcywgbmEucm0gPSBUUlVFKQ0KICAgICksDQogIA0KICBwb3JfdGlwb19jb211bmEgPSBwYXJyb3F1aWFzX3Byb3llY3RvcyAlPiUNCiAgICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lDQogICAgZmlsdGVyKCFpcy5uYShUaXBvX0NvbXVuYSkpICU+JQ0KICAgIGdyb3VwX2J5KFRpcG9fQ29tdW5hKSAlPiUNCiAgICBzdW1tYXJpc2UoDQogICAgICBuX3BhcnJvcXVpYXMgPSBuX2Rpc3RpbmN0KElEKSwNCiAgICAgIHRvdGFsX3Byb3llY3RvcyA9IG4oKSwNCiAgICAgIHByb3llY3Rvc19wcm9tZWRpbyA9IHJvdW5kKG1lYW4obl9wcm95ZWN0b3MsIG5hLnJtID0gVFJVRSksIDIpLA0KICAgICAgZWZlY3RpdmlkYWRfcHJvbWVkaW8gPSByb3VuZChtZWFuKFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIG5hLnJtID0gVFJVRSksIDIpLA0KICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICksDQogIA0KICByYW5raW5nX3BhcnJvcXVpYXMgPSBwYXJyb3F1aWFzX3Byb3llY3RvcyAlPiUNCiAgICBzdF9kcm9wX2dlb21ldHJ5KCkgJT4lDQogICAgZmlsdGVyKCFpcy5uYShuX3Byb3llY3RvcykpICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhuX3Byb3llY3RvcykpICU+JQ0KICAgIGhlYWQoMTApICU+JQ0KICAgIHNlbGVjdChQQVJST1FVSUEsIE1VTklDSVBJTywgbl9wcm95ZWN0b3MsIFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIFRpcG9fQ29tdW5hKQ0KKQ0KDQojIE1vc3RyYXIgZXN0YWTDrXN0aWNhcw0KY2F0KCJcbj09PSBSRVNVTUVOIEVTVEFEw41TVElDTyBURVJSSVRPUklBTCA9PT1cbiIpDQpjYXQoIkNvYmVydHVyYToiLCBlc3RhZGlzdGljYXNfdGVycml0b3JpYWxlcyRjb2JlcnR1cmFfZ2VuZXJhbCRjb2JlcnR1cmFfcGN0LCAiJVxuIikNCmNhdCgiUHJveWVjdG9zIHRvdGFsZXM6IiwgZXN0YWRpc3RpY2FzX3RlcnJpdG9yaWFsZXMkY29iZXJ0dXJhX2dlbmVyYWwkdG90YWxfcHJveWVjdG9zLCAiXG4iKQ0KcHJpbnQoZXN0YWRpc3RpY2FzX3RlcnJpdG9yaWFsZXMkcG9yX3RpcG9fY29tdW5hKQ0KcHJpbnQoZXN0YWRpc3RpY2FzX3RlcnJpdG9yaWFsZXMkcmFua2luZ19wYXJyb3F1aWFzKQ0KDQojIEV4cG9ydGFyIG1hcGFzIG1lam9yYWRvcw0KZ2dzYXZlKCJtYXBhXzAxX2Rpc3RyaWJ1Y2lvbl9wcm9mZXNpb25hbC5wbmciLCBtYXBhX2Rpc3RyaWJ1Y2lvbl9wcm8sIA0KICAgICAgIHdpZHRoID0gMTQsIGhlaWdodCA9IDExLCBkcGkgPSAzMDAsIGJnID0gIndoaXRlIikNCmdnc2F2ZSgibWFwYV8wMl9lZmVjdGl2aWRhZF9wcm9mZXNpb25hbC5wbmciLCBtYXBhX2VmZWN0aXZpZGFkX3BybywgDQogICAgICAgd2lkdGggPSAxNCwgaGVpZ2h0ID0gMTEsIGRwaSA9IDMwMCwgYmcgPSAid2hpdGUiKQ0KZ2dzYXZlKCJtYXBhXzAzX3RpcG9zX2NvbXVuYV9wcm9mZXNpb25hbC5wbmciLCBtYXBhX3RpcG9zX2NvbXVuYV9wcm8sIA0KICAgICAgIHdpZHRoID0gMTQsIGhlaWdodCA9IDExLCBkcGkgPSAzMDAsIGJnID0gIndoaXRlIikNCmdnc2F2ZSgibWFwYV8wNF9tdW5pY2lwYWxfcHJvZmVzaW9uYWwucG5nIiwgbWFwYV9tdW5pY2lwYWxfcHJvLCANCiAgICAgICB3aWR0aCA9IDE0LCBoZWlnaHQgPSAxMSwgZHBpID0gMzAwLCBiZyA9ICJ3aGl0ZSIpDQpnZ3NhdmUoIm1hcGFfMDVfZGVuc2lkYWRfcHJvZmVzaW9uYWwucG5nIiwgbWFwYV9kZW5zaWRhZF9wcm8sIA0KICAgICAgIHdpZHRoID0gMTYsIGhlaWdodCA9IDEyLCBkcGkgPSAzMDAsIGJnID0gIndoaXRlIikNCmdnc2F2ZSgibWFwYV8wNl9kaXZlcnNpZGFkX3Byb2Zlc2lvbmFsLnBuZyIsIG1hcGFfZGl2ZXJzaWRhZF9wcm8sIA0KICAgICAgIHdpZHRoID0gMTQsIGhlaWdodCA9IDExLCBkcGkgPSAzMDAsIGJnID0gIndoaXRlIikNCmdnc2F2ZSgicGFuZWxfdGVycml0b3JpYWxfY29tcGxldG8ucG5nIiwgcGFuZWxfdGVycml0b3JpYWwsIA0KICAgICAgIHdpZHRoID0gMjQsIGhlaWdodCA9IDE4LCBkcGkgPSAzMDAsIGJnID0gIndoaXRlIikNCg0KY2F0KCJcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KY2F0KCJBTsOBTElTSVMgVEVSUklUT1JJQUwgUFJPRkVTSU9OQUwgQ09NUExFVEFETyBFWElUT1NBTUVOVEVcbiIpDQpjYXQoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4iKQ0KY2F0KCJNQVBBUyBHRU5FUkFET1M6XG4iKQ0KY2F0KCIxLiBEaXN0cmlidWNpw7NuIHRlcnJpdG9yaWFsIGNvbiBib3JkZXMgbWVqb3JhZG9zXG4iKQ0KY2F0KCIyLiBFZmVjdGl2aWRhZCB0ZXJyaXRvcmlhbCBjb24gZXNjYWxhIG1lam9yYWRhXG4iKSANCmNhdCgiMy4gVGlwb3MgZGUgY29tdW5hIGNvbiBjb2xvcmVzIHByb2Zlc2lvbmFsZXNcbiIpDQpjYXQoIjQuIEFuw6FsaXNpcyBtdW5pY2lwYWwgY29uIGV0aXF1ZXRhc1xuIikNCmNhdCgiNS4gQW7DoWxpc2lzIG11bHRpLWVzY2FsYSAocGFycm9xdWlhcyArIGNlbnRyb3MpXG4iKQ0KY2F0KCI2LiBEaXZlcnNpZGFkIGRlIHRpcG9sb2fDrWFzIChTaGFubm9uKVxuIikNCmNhdCgiNy4gUGFuZWwgdGVycml0b3JpYWwgaW50ZWdyYWRvICgyeDMpXG4iKQ0KY2F0KCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIikNCmBgYA0KDQpFc3RveSBjcmVhbmRvIHVuIEhUTUwgYSB0cmF2w6lzIGRlIFIgTWFya2Rvd24gcGFyYSBsYSBleHBvc2ljacOzbiBkZSBtaXMgcGFzYW50w61hcywgZGUgbWlzIHJlc3VsdGFkb3MgZGUgbGEgdGVzaXMgbW9ub2dyYWbDrWEgcXVlIGRlc2Fycm9sbGUsIG1lIHB1ZWRlcyBheXVkYXIgYSBwbGFudGVhciBsYSBzZWNjacOzbiBkZSBhbmFsaXNpcyB0ZXJyaXRvcmlhbCBwYXJhIGNvbG9jYXJsYSBlbiBlc2UgSFRNTCBxdWUgc2Vyw6EgbWkgaW5zdHJ1bWVudG8gcGFyYSBsYSBleHBvc2ljacOzbiwgY29tbyBwb2Ryw61hIGNvbnN0cnVpciBkaWdhbW9zIGVzZSBhbmFsaXNpcyB0ZXJyaXRvcmlhbCAsIHZpZW5kbyBlbCBjw7NkaWdvIHkgdmllbmRvIGVsIHRleHRvIHF1ZSBsb3MgaW50ZXJwcmV0YSwgcGFyYSBoYWNlcmxvIGVuIGVzZSBIVE1MIHkgcXVlIHB1ZWRhIGV4cHJlc2FyIGxvIG1hcyBpbnRlcmVzYW50ZSBxdWUgY29uc2VndcOtIGVuIGxhIHRlc2lzIG1vbm9ncmFmaWNhLCBwdWVkZXMgYXl1ZGFybWUgYSBpbnRlcnByZXRhciBkZSBmb3JtYSBjb25jaXNhIGVzdGUgYW5hbGlzaXMgdGVycml0b3JpYWwgLCBlc3RveSBwbGFudGVhbmRvIGFzw60gbGFzIGRpYXBvc2l0aXZhcyBkaWdhbW9zIGVuIGVsIGh0bWwsIHByZXNlbnRvIHVuYSBpbnRyb2R1Y2Npw7NuIGNvcnRhLCBsYXMgZ3JhZmljYXMgaW50ZXJhY3RpdmFzIGp1bnRvIGNvbiBsYXMgdGFibGFzLCBlIGludGVycHJldG8gbG9zIHJlc3VsdGFkb3MgY29uY2lzb3MgY29tbyBwYXJhIHVuYSBkaWFwb3NpdGl2YSwgbWUgcHVlZGVzIGF5dWRhciBjb24gZXNlIGFuYWxpc2lzIHRlcnJpdG9yaWFsLCBlc3RlIGVzIG1pIGNvZGlnbyBjb24gaW1hZ2VuZXMgZmlqYXMsIHF1aWVybyBkYXJ0ZSBhZGVtYXMgbGEgZXN0cnVjdHVyYSBkZSBsb3Mgc2hhcGVmaWxlLCBwYXJhIG1lam9yYXIgbG9zIG1hcGFzIGludGVyYWN0aXZvcyBvIGN1YWxxdWllciBvcHRpbWl6YWNpw7NuOiANCg0KIyMqKk1hcGFzIGludGVyYWN0aXZvcyoqDQoNCioqU8OtbnRlc2lzIGRlIFJlc3VsdGFkb3MqKg0KDQogICpEaXN0cmlidWNpw7NuIGRlc2lndWFsKjogNjUlIGRlIHByb3llY3RvcyBjb25jZW50cmFkb3MgZW4gMzAlIGRlbCB0ZXJyaXRvcmlvLCBwcmluY2lwYWxtZW50ZSBlbiBlamUgdXJiYW5vIE3DqXJpZGEtRWppZG8NCg0KKkVmZWN0aXZpZGFkIGRpZmVyZW5jaWFkYSo6IENvbXVuYXMgdXJiYW5hcyBtdWVzdHJhbiA0MCUgbWF5b3IgZWZlY3RpdmlkYWQgcXVlIHJ1cmFsZXMNCg0KKkRpdmVyc2lkYWQgY29ycmVsYWNpb25hZGEqOiBNYXlvciBuw7ptZXJvIGRlIHByb3llY3RvcyA9IG1heW9yIGRpdmVyc2lkYWQgdGlwb2zDs2dpY2EgKM+BID0gMC44MiBlbiB6b25hcyBtaXh0YXMpDQoNCipTZWdtZW50YWNpw7NuIHRlcnJpdG9yaWFsIGNsYXJhKjogVXJiYW5vIChhbHRhIGRlbnNpZGFkKSwgUnVyYWwgKGVuZm9xdWUgZXNwZWPDrWZpY28pLCBNaXh0byAoY29tcG9ydGFtaWVudG8gaW50ZXJtZWRpbykNCg0KKkJyZWNoYSBkZSBwbGFuaWZpY2FjacOzbio6IENvcnJlbGFjacOzbiBwZXJmZWN0YSBkaWFnbsOzc3RpY28tZ2VzdGnDs24gZW4gZWxlY3RyaWNpZGFkICjPgSA9IDEuMCkgdnMgZGVzY29uZXhpw7NuIGVuIG90cm9zIHNlY3RvcmVzDQoNCipQYXRyw7NuIGNlbnRyby1wZXJpZmVyaWEqOiBEaXNtaW51Y2nDs24gcHJvZ3Jlc2l2YSBkZSBwcm95ZWN0b3MgZGVzZGUgbsO6Y2xlb3MgdXJiYW5vcyBoYWNpYSDDoXJlYXMgcnVyYWxlcw0KDQoqT3BvcnR1bmlkYWQgcsOpcGxpY2EqOiBNb2RlbG9zIGV4aXRvc29zIGVuIGNvbXVuYXMgbWl4dGFzIHB1ZWRlbiBlc2NhbGFyc2UgYSBjb250ZXh0b3Mgc2ltaWxhcmVzDQoNCipQcmlvcml6YWNpw7NuIG5lY2VzYXJpYSo6IDQgdGlwb2xvZ8OtYXMgY29uY2VudHJhbiA2Mi42JSBkZSBudWRvcyBjcsOtdGljb3MsIGluZGljYW5kbyBmb2NvcyBkZSBpbnRlcnZlbmNpw7NuDQoNCipFZmljaWVuY2lhIHRlcnJpdG9yaWFsKjogWm9uYXMgY29uIGNsdXN0ZXJzIGRlIGNlbnRyb3MgcG9ibGFkb3MgbXVlc3RyYW4gbWVqb3IgY29vcmRpbmFjacOzbiBpbnN0aXR1Y2lvbmFsDQoNCipQb2zDrXRpY2EgZGlmZXJlbmNpYWRhKjogVXJnZSBhZGFwdGFyIGVzdHJhdGVnaWFzIHBvciB0aXBvIGNvbXVuYSBwYXJhIG1heGltaXphciBpbXBhY3RvDQoNCmBgYHtyIG1hcGFfaW50ZXJhY3Rpdm9fY29tcGxldG8sIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy53aWR0aD0xNCwgZmlnLmhlaWdodD0xMH0NCg0KDQojIyAqKk1hcGFzIGludGVyYWN0aXZvcyoqDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIE1BUEFTIElOVEVSQUNUSVZPUyBDT01QTEVUT1MgLSBQUk9ZRUNUT1MgQUNBIEVTVEFETyBNw4lSSURBDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAwLiBGVU5DScOTTiBQQVJBIExJTVBJQVIgQ09ESUZJQ0FDScOTTiBERSBURVhUTyAoVkVDVE9SSVpBREEpDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpsaW1waWFyX3RleHRvIDwtIGZ1bmN0aW9uKHRleHRvKSB7DQogICMgVmVjdG9yaXphciBsYSBmdW5jacOzbiBwYXJhIG1hbmVqYXIgdmVjdG9yZXMgY29tcGxldG9zDQogIHNhcHBseSh0ZXh0bywgZnVuY3Rpb24oeCkgew0KICAgIGlmIChpcy5udWxsKHgpIHx8IGlzLm5hKHgpIHx8IHggPT0gIiIpIHJldHVybigiIikNCiAgICANCiAgICAjIENvbnZlcnRpciBhIHN0cmluZyB5IGxpbXBpYXIgY2FyYWN0ZXJlcyBwcm9ibGVtw6F0aWNvcw0KICAgIHRleHRvX2xpbXBpbyA8LSBhcy5jaGFyYWN0ZXIoeCkNCiAgICANCiAgICAjIFJlZW1wbGF6YXIgY2FyYWN0ZXJlcyBwcm9ibGVtw6F0aWNvcyBjb211bmVzDQogICAgdGV4dG9fbGltcGlvIDwtIGljb252KHRleHRvX2xpbXBpbywgZnJvbSA9ICJVVEYtOCIsIHRvID0gIkFTQ0lJLy9UUkFOU0xJVCIsIHN1YiA9ICI/IikNCiAgICANCiAgICAjIFNpIGljb252IGZhbGxhLCB1c2FyIG3DqXRvZG8gYWx0ZXJuYXRpdm8NCiAgICBpZiAoaXMubmEodGV4dG9fbGltcGlvKSkgew0KICAgICAgdGV4dG9fbGltcGlvIDwtIGljb252KHgsIGZyb20gPSAibGF0aW4xIiwgdG8gPSAiQVNDSUkvL1RSQU5TTElUIiwgc3ViID0gIj8iKQ0KICAgIH0NCiAgICANCiAgICAjIEVsaW1pbmFyIGNhcmFjdGVyZXMgcmVzaWR1YWxlcyBwcm9ibGVtw6F0aWNvcw0KICAgIHRleHRvX2xpbXBpbyA8LSBnc3ViKCJbXls6YWxudW06XVs6c3BhY2U6XVs6cHVuY3Q6XV0iLCAiIiwgdGV4dG9fbGltcGlvKQ0KICAgIA0KICAgICMgTGltcGlhciBlc3BhY2lvcyBtw7psdGlwbGVzDQogICAgdGV4dG9fbGltcGlvIDwtIGdzdWIoIlxccysiLCAiICIsIHRleHRvX2xpbXBpbykNCiAgICB0ZXh0b19saW1waW8gPC0gdHJpbXdzKHRleHRvX2xpbXBpbykNCiAgICANCiAgICByZXR1cm4odGV4dG9fbGltcGlvKQ0KICB9LCBVU0UuTkFNRVMgPSBGQUxTRSkNCn0NCg0KIyBGdW5jacOzbiBhbHRlcm5hdGl2YSBtw6FzIHJvYnVzdGENCmxpbXBpYXJfdGV4dG9fdmVjdG9yaXphZG8gPC0gZnVuY3Rpb24odGV4dG8pIHsNCiAgIyBDb252ZXJ0aXIgYSBjYXJhY3Rlcg0KICB0ZXh0byA8LSBhcy5jaGFyYWN0ZXIodGV4dG8pDQogIA0KICAjIFJlZW1wbGF6YXIgTkFzDQogIHRleHRvW2lzLm5hKHRleHRvKV0gPC0gIiINCiAgDQogICMgTGltcGlhciBjb24gaWNvbnYgZGUgbWFuZXJhIHZlY3Rvcml6YWRhDQogIHRleHRvX2xpbXBpbyA8LSBpY29udih0ZXh0bywgZnJvbSA9ICJVVEYtOCIsIHRvID0gIkFTQ0lJLy9UUkFOU0xJVCIsIHN1YiA9ICI/IikNCiAgDQogICMgUGFyYSBsb3MgcXVlIGZhbGxhbiwgaW50ZW50YXIgY29uIGxhdGluMQ0KICBmYWxsb3MgPC0gaXMubmEodGV4dG9fbGltcGlvKQ0KICBpZiAoYW55KGZhbGxvcykpIHsNCiAgICB0ZXh0b19saW1waW9bZmFsbG9zXSA8LSBpY29udih0ZXh0b1tmYWxsb3NdLCBmcm9tID0gImxhdGluMSIsIHRvID0gIkFTQ0lJLy9UUkFOU0xJVCIsIHN1YiA9ICI/IikNCiAgfQ0KICANCiAgIyBBcGxpY2FyIGxpbXBpZXphIGRlIGNhcmFjdGVyZXMNCiAgdGV4dG9fbGltcGlvIDwtIGdzdWIoIlteWzphbG51bTpdWzpzcGFjZTpdWzpwdW5jdDpdXSIsICIiLCB0ZXh0b19saW1waW8pDQogIHRleHRvX2xpbXBpbyA8LSBnc3ViKCJcXHMrIiwgIiAiLCB0ZXh0b19saW1waW8pDQogIHRleHRvX2xpbXBpbyA8LSB0cmltd3ModGV4dG9fbGltcGlvKQ0KICANCiAgcmV0dXJuKHRleHRvX2xpbXBpbykNCn0NCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgMS4gQ09SUkVDQ0nDk04gREUgQ1JTIFkgVFJBTlNGT1JNQUNJw5NODQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIkluaWNpYW5kbyBwcmVwYXJhY2nDs24gZGUgZGF0b3MgZXNwYWNpYWxlcy4uLlxuIikNCg0KIyBWZXJpZmljYXIgeSBhc2lnbmFyIENSUyBhIGxvcyBzaGFwZWZpbGVzIChXR1M4NCAtIEVQU0c6NDMyNikNCmlmKGV4aXN0cygicGFycm9xdWlhc19zZiIpKSB7DQogIGlmKGlzLm5hKHN0X2NycyhwYXJyb3F1aWFzX3NmKSkpIHN0X2NycyhwYXJyb3F1aWFzX3NmKSA8LSA0MzI2DQogIHBhcnJvcXVpYXNfc2Zfd2dzIDwtIHN0X3RyYW5zZm9ybShwYXJyb3F1aWFzX3NmLCA0MzI2KQ0KICANCiAgIyBMSU1QSUFSIFRFWFRPUyBFTiBQQVJST1FVSUFTIChVU0FORE8gRlVOQ0nDk04gVkVDVE9SSVpBREEpDQogIHBhcnJvcXVpYXNfc2Zfd2dzIDwtIHBhcnJvcXVpYXNfc2Zfd2dzICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIFBBUlJPUVVJQSA9IGxpbXBpYXJfdGV4dG9fdmVjdG9yaXphZG8oUEFSUk9RVUlBKSwNCiAgICAgIE1VTklDSVBJTyA9IGxpbXBpYXJfdGV4dG9fdmVjdG9yaXphZG8oTVVOSUNJUElPKQ0KICAgICkNCiAgY2F0KCLinJMgUGFycm9xdWlhcyB0cmFuc2Zvcm1hZGFzIGEgV0dTODQgeSB0ZXh0b3MgbGltcGlhZG9zXG4iKQ0KfSBlbHNlIHsNCiAgc3RvcCgiRXJyb3I6IHBhcnJvcXVpYXNfc2Ygbm8gZW5jb250cmFkbyIpDQp9DQoNCmlmKGV4aXN0cygibXVuaWNpcGlvc19zZiIpKSB7DQogIGlmKGlzLm5hKHN0X2NycyhtdW5pY2lwaW9zX3NmKSkpIHN0X2NycyhtdW5pY2lwaW9zX3NmKSA8LSA0MzI2DQogIG11bmljaXBpb3Nfc2Zfd2dzIDwtIHN0X3RyYW5zZm9ybShtdW5pY2lwaW9zX3NmLCA0MzI2KQ0KICANCiAgIyBMSU1QSUFSIFRFWFRPUyBFTiBNVU5JQ0lQSU9TDQogIGlmKCJGSVJTVF9NVU5JIiAlaW4lIG5hbWVzKG11bmljaXBpb3Nfc2Zfd2dzKSkgew0KICAgIG11bmljaXBpb3Nfc2Zfd2dzIDwtIG11bmljaXBpb3Nfc2Zfd2dzICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBGSVJTVF9NVU5JID0gbGltcGlhcl90ZXh0b192ZWN0b3JpemFkbyhGSVJTVF9NVU5JKQ0KICAgICAgKQ0KICB9DQogIGNhdCgi4pyTIE11bmljaXBpb3MgdHJhbnNmb3JtYWRvcyBhIFdHUzg0IHkgdGV4dG9zIGxpbXBpYWRvc1xuIikNCn0gZWxzZSB7DQogIHN0b3AoIkVycm9yOiBtdW5pY2lwaW9zX3NmIG5vIGVuY29udHJhZG8iKQ0KfQ0KDQppZihleGlzdHMoImNlbnRyb3Nfc2YiKSkgew0KICBpZihpcy5uYShzdF9jcnMoY2VudHJvc19zZikpKSBzdF9jcnMoY2VudHJvc19zZikgPC0gNDMyNg0KICBjZW50cm9zX3NmX3dncyA8LSBzdF90cmFuc2Zvcm0oY2VudHJvc19zZiwgNDMyNikNCiAgDQogICMgTElNUElBUiBURVhUT1MgRU4gQ0VOVFJPUyBQT0JMQURPUw0KICBpZigiTk9NQ0VOUE9CIiAlaW4lIG5hbWVzKGNlbnRyb3Nfc2Zfd2dzKSkgew0KICAgIGNlbnRyb3Nfc2Zfd2dzIDwtIGNlbnRyb3Nfc2Zfd2dzICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBOT01DRU5QT0IgPSBsaW1waWFyX3RleHRvX3ZlY3Rvcml6YWRvKE5PTUNFTlBPQikNCiAgICAgICkNCiAgfQ0KICBjYXQoIuKckyBDZW50cm9zIHBvYmxhZG9zIHRyYW5zZm9ybWFkb3MgYSBXR1M4NCB5IHRleHRvcyBsaW1waWFkb3NcbiIpDQp9IGVsc2Ugew0KICBzdG9wKCJFcnJvcjogY2VudHJvc19zZiBubyBlbmNvbnRyYWRvIikNCn0NCg0KaWYoZXhpc3RzKCJlc3RhZG9zX3NmIikpIHsNCiAgaWYoaXMubmEoc3RfY3JzKGVzdGFkb3Nfc2YpKSkgc3RfY3JzKGVzdGFkb3Nfc2YpIDwtIDQzMjYNCiAgbWVyaWRhX2VzdGFkb193Z3MgPC0gc3RfdHJhbnNmb3JtKGVzdGFkb3Nfc2YgJT4lIGZpbHRlcihFU1RBRE8gPT0gIk1FUklEQSIpLCA0MzI2KQ0KICBjYXQoIuKckyBFc3RhZG8gTcOpcmlkYSB0cmFuc2Zvcm1hZG8gYSBXR1M4NFxuIikNCn0gZWxzZSB7DQogIHN0b3AoIkVycm9yOiBlc3RhZG9zX3NmIG5vIGVuY29udHJhZG8iKQ0KfQ0KDQpjYXQoIuKckyBUb2RvcyBsb3Mgc2hhcGVmaWxlcyB0cmFuc2Zvcm1hZG9zIGEgV0dTODQgY29ycmVjdGFtZW50ZVxuIikNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgMi4gUFJFUEFSQUNJw5NOIERFIERBVE9TIFBBUkEgTUFQQVMgSU5URVJBQ1RJVk9TDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIlByZXBhcmFuZG8gZGF0b3MgcGFyYSBtYXBhcyBpbnRlcmFjdGl2b3MuLi5cbiIpDQoNCiMgVmVyaWZpY2FyIHF1ZSBkZl9yYXcgZXhpc3RlDQppZighZXhpc3RzKCJkZl9yYXciKSkgew0KICBzdG9wKCJFcnJvcjogZGZfcmF3IG5vIGVuY29udHJhZG8uIEFzZWfDunJhdGUgZGUgY2FyZ2FyIGxvcyBkYXRvcyBkZSBwcm95ZWN0b3MgQUNBIikNCn0NCg0KIyBBc2VndXJhciBxdWUgQ09EX1VCSUdFTyBzZWEgY2Fyw6FjdGVyDQpkZl9yYXckQ09EX1VCSUdFTyA8LSBhcy5jaGFyYWN0ZXIoZGZfcmF3JENPRF9VQklHRU8pDQoNCiMgUFJFUEFSQVIgREFUT1MgQ09OIFRFWFRPIExJTVBJTw0KZGF0b3NfcGFycm9xdWlhc19pbnRlcmFjdGl2byA8LSBwYXJyb3F1aWFzX3NmX3dncyAlPiUNCiAgbGVmdF9qb2luKA0KICAgIGRmX3JhdyAlPiUNCiAgICAgIGdyb3VwX2J5KENPRF9VQklHRU8pICU+JQ0KICAgICAgc3VtbWFyaXNlKA0KICAgICAgICB0b3RhbF9wcm95ZWN0b3MgPSBuKCksDQogICAgICAgIHByb3llY3Rvc191bmljb3MgPSBuX2Rpc3RpbmN0KENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgZWZlY3RpdmlkYWRfcHJvbWVkaW8gPSByb3VuZChtZWFuKFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIG5hLnJtID0gVFJVRSksIDIpLA0KICAgICAgICB0aXBvbG9naWFfcHJpbmNpcGFsID0gbmFtZXMoc29ydCh0YWJsZShDTEFTSUZJQ0FDScOTTl9ERUxfTlVET19DUklUSUNPX1RJUE9MT0dJQV9DRkcpLCBkZWNyZWFzaW5nID0gVFJVRSkpWzFdLA0KICAgICAgICB0aXBvX2NvbXVuYV9wcmluY2lwYWwgPSBuYW1lcyhzb3J0KHRhYmxlKFRpcG9fQ29tdW5hKSwgZGVjcmVhc2luZyA9IFRSVUUpKVsxXSwNCiAgICAgICAgLmdyb3VwcyA9ICJkcm9wIg0KICAgICAgKSwNCiAgICBieSA9IGMoIklEIiA9ICJDT0RfVUJJR0VPIikNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIHRvdGFsX3Byb3llY3RvcyA9IGlmZWxzZShpcy5uYSh0b3RhbF9wcm95ZWN0b3MpLCAwLCB0b3RhbF9wcm95ZWN0b3MpLA0KICAgIGVmZWN0aXZpZGFkX3Byb21lZGlvID0gaWZlbHNlKGlzLm5hKGVmZWN0aXZpZGFkX3Byb21lZGlvKSwgMCwgZWZlY3RpdmlkYWRfcHJvbWVkaW8pLA0KICAgICMgTElNUElBUiBURVhUT1MgREUgTEFTIE5VRVZBUyBDT0xVTU5BUw0KICAgIHRpcG9sb2dpYV9wcmluY2lwYWwgPSBsaW1waWFyX3RleHRvX3ZlY3Rvcml6YWRvKHRpcG9sb2dpYV9wcmluY2lwYWwpLA0KICAgIHRpcG9fY29tdW5hX3ByaW5jaXBhbCA9IGxpbXBpYXJfdGV4dG9fdmVjdG9yaXphZG8odGlwb19jb211bmFfcHJpbmNpcGFsKQ0KICApDQoNCiMgQ1JFQVIgUE9QVVAgQ09OVEVOVCBERSBGT1JNQSBTRUdVUkENCmRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kcG9wdXBfY29udGVudF9zYWZlIDwtIHNhcHBseSgxOm5yb3coZGF0b3NfcGFycm9xdWlhc19pbnRlcmFjdGl2byksIGZ1bmN0aW9uKGkpIHsNCiAgcGFycm9xdWlhIDwtIGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kUEFSUk9RVUlBW2ldDQogIG11bmljaXBpbyA8LSBkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvJE1VTklDSVBJT1tpXQ0KICB0b3RhbF9wcm95IDwtIGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kdG90YWxfcHJveWVjdG9zW2ldDQogIGVmZWN0aXZpZGFkIDwtIGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kZWZlY3RpdmlkYWRfcHJvbWVkaW9baV0NCiAgdGlwb2xvZ2lhIDwtIGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kdGlwb2xvZ2lhX3ByaW5jaXBhbFtpXQ0KICB0aXBvX2NvbXVuYSA8LSBkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvJHRpcG9fY29tdW5hX3ByaW5jaXBhbFtpXQ0KICANCiAgcGFzdGUoDQogICAgIjxkaXYgc3R5bGU9J21heC13aWR0aDogMzAwcHg7Jz4iLA0KICAgICI8aDQgc3R5bGU9J2NvbG9yOiAjMmMzZTUwOyBtYXJnaW4tYm90dG9tOiAxMHB4Oyc+IiwgcGFycm9xdWlhLCAiPC9oND4iLA0KICAgICI8cD48c3Ryb25nPk11bmljaXBpbzo8L3N0cm9uZz4gIiwgbXVuaWNpcGlvLCAiPC9wPiIsDQogICAgIjxwPjxzdHJvbmc+VG90YWwgUHJveWVjdG9zOjwvc3Ryb25nPiAiLCB0b3RhbF9wcm95LCAiPC9wPiIsDQogICAgIjxwPjxzdHJvbmc+RWZlY3RpdmlkYWQgUHJvbWVkaW86PC9zdHJvbmc+ICIsIGVmZWN0aXZpZGFkLCAiPC9wPiIsDQogICAgIjxwPjxzdHJvbmc+VGlwb2xvZ8OtYSBQcmluY2lwYWw6PC9zdHJvbmc+ICIsIGlmZWxzZShpcy5uYSh0aXBvbG9naWEpIHwgdGlwb2xvZ2lhID09ICIiLCAiU2luIGRhdG9zIiwgdGlwb2xvZ2lhKSwgIjwvcD4iLA0KICAgICI8cD48c3Ryb25nPlRpcG8gQ29tdW5hOjwvc3Ryb25nPiAiLCBpZmVsc2UoaXMubmEodGlwb19jb211bmEpIHwgdGlwb19jb211bmEgPT0gIiIsICJTaW4gZGF0b3MiLCB0aXBvX2NvbXVuYSksICI8L3A+IiwNCiAgICAiPC9kaXY+Ig0KICApDQp9KQ0KDQpjYXQoIuKckyBEYXRvcyBwcmVwYXJhZG9zIHBhcmEgbWFwYXMgaW50ZXJhY3Rpdm9zXG4iKQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAzLiBNQVBBIElOVEVSQUNUSVZPIDE6IERJU1RSSUJVQ0nDk04gVEVSUklUT1JJQUwNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmNhdCgiQ3JlYW5kbyBNYXBhIDE6IERpc3RyaWJ1Y2nDs24gdGVycml0b3JpYWwuLi5cbiIpDQoNCiMgQW5hbGl6YXIgZWwgcmFuZ28gZGUgZGF0b3MgcGFyYSBkZWZpbmlyIGJpbnMgYXByb3BpYWRvcw0KcmFuZ29fcHJveWVjdG9zIDwtIHJhbmdlKGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kdG90YWxfcHJveWVjdG9zLCBuYS5ybSA9IFRSVUUpDQpjYXQoIlJhbmdvIGRlIHByb3llY3RvcyBwb3IgcGFycm9xdWlhOiIsIHJhbmdvX3Byb3llY3Rvc1sxXSwgIi0iLCByYW5nb19wcm95ZWN0b3NbMl0sICJcbiIpDQoNCiMgRGVmaW5pciBiaW5zIHNlZ8O6biBlbCByYW5nbyBkZSBkYXRvcw0KaWYocmFuZ29fcHJveWVjdG9zWzJdIDw9IDUpIHsNCiAgYmluc19wcm95ZWN0b3MgPC0gYygwLCAxLCAyLCAzLCA0LCA1KQ0KfSBlbHNlIGlmKHJhbmdvX3Byb3llY3Rvc1syXSA8PSAxMCkgew0KICBiaW5zX3Byb3llY3RvcyA8LSBjKDAsIDEsIDMsIDUsIDcsIDEwKQ0KfSBlbHNlIGlmKHJhbmdvX3Byb3llY3Rvc1syXSA8PSAyMCkgew0KICBiaW5zX3Byb3llY3RvcyA8LSBjKDAsIDEsIDUsIDEwLCAxNSwgMjApDQp9IGVsc2Ugew0KICBiaW5zX3Byb3llY3RvcyA8LSBjKDAsIDEsIDUsIDEwLCAyMCwgcmFuZ29fcHJveWVjdG9zWzJdKQ0KfQ0KDQpwYWxfcHJveWVjdG9zIDwtIGNvbG9yQmluKA0KICBwYWxldHRlID0gIllsT3JSZCIsDQogIGRvbWFpbiA9IGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kdG90YWxfcHJveWVjdG9zLA0KICBiaW5zID0gYmluc19wcm95ZWN0b3MsDQogIG5hLmNvbG9yID0gInRyYW5zcGFyZW50Ig0KKQ0KDQptYXBhX2Rpc3RyaWJ1Y2lvbiA8LSBsZWFmbGV0KGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8pICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uLCBncm91cCA9ICJCYXNlIENsYXJvIikgJT4lDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJEVzcmkuV29ybGRJbWFnZXJ5LCBncm91cCA9ICJTYXTDqWxpdGUiKSAlPiUNCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkT3BlblRvcG9NYXAsIGdyb3VwID0gIlRvcG9ncsOhZmljbyIpICU+JQ0KICANCiAgIyBDYXBhIGRlIHBhcnJvcXVpYXMgY29uIHByb3llY3Rvcw0KICBhZGRQb2x5Z29ucygNCiAgICBmaWxsQ29sb3IgPSB+cGFsX3Byb3llY3Rvcyh0b3RhbF9wcm95ZWN0b3MpLA0KICAgIGZpbGxPcGFjaXR5ID0gMC43LA0KICAgIGNvbG9yID0gIndoaXRlIiwNCiAgICB3ZWlnaHQgPSAxLA0KICAgIHBvcHVwID0gfnBvcHVwX2NvbnRlbnRfc2FmZSwNCiAgICBsYWJlbCA9IH5wYXN0ZShQQVJST1FVSUEsICItIiwgdG90YWxfcHJveWVjdG9zLCAicHJveWVjdG9zIiksDQogICAgZ3JvdXAgPSAiUHJveWVjdG9zIHBvciBQYXJyb3F1aWEiLA0KICAgIGhpZ2hsaWdodE9wdGlvbnMgPSBoaWdobGlnaHRPcHRpb25zKA0KICAgICAgY29sb3IgPSAiI0ZGNEQ0RCIsDQogICAgICB3ZWlnaHQgPSAzLA0KICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRQ0KICAgICkNCiAgKSAlPiUNCiAgDQogICMgQ2FwYSBkZSBsw61taXRlcyBtdW5pY2lwYWxlcw0KICBhZGRQb2x5bGluZXMoDQogICAgZGF0YSA9IG11bmljaXBpb3Nfc2Zfd2dzLA0KICAgIGNvbG9yID0gIiMyYzNlNTAiLA0KICAgIHdlaWdodCA9IDIsDQogICAgb3BhY2l0eSA9IDAuOCwNCiAgICBncm91cCA9ICJMw61taXRlcyBNdW5pY2lwYWxlcyIsDQogICAgbGFiZWwgPSB+aWYoZXhpc3RzKCJGSVJTVF9NVU5JIiwgd2hlcmUgPSBtdW5pY2lwaW9zX3NmX3dncykpIEZJUlNUX01VTkkgZWxzZSAiTXVuaWNpcGlvIg0KICApICU+JQ0KICANCiAgIyBDYXBhIGRlIGNlbnRyb3MgcG9ibGFkb3MNCiAgYWRkQ2lyY2xlTWFya2VycygNCiAgICBkYXRhID0gY2VudHJvc19zZl93Z3MsDQogICAgcmFkaXVzID0gNCwNCiAgICBjb2xvciA9ICIjMjk4MGI5IiwNCiAgICBmaWxsQ29sb3IgPSAiIzM0OThkYiIsDQogICAgZmlsbE9wYWNpdHkgPSAwLjgsDQogICAgd2VpZ2h0ID0gMSwNCiAgICBwb3B1cCA9IH5pZihleGlzdHMoIk5PTUNFTlBPQiIsIHdoZXJlID0gY2VudHJvc19zZl93Z3MpKSBwYXN0ZSgiPHN0cm9uZz4iLCBOT01DRU5QT0IsICI8L3N0cm9uZz4iKSBlbHNlICI8c3Ryb25nPkNlbnRybyBQb2JsYWRvPC9zdHJvbmc+IiwNCiAgICBncm91cCA9ICJDZW50cm9zIFBvYmxhZG9zIg0KICApICU+JQ0KICANCiAgIyBDb250cm9sZXMgZGUgY2FwYXMNCiAgYWRkTGF5ZXJzQ29udHJvbCgNCiAgICBiYXNlR3JvdXBzID0gYygiQmFzZSBDbGFybyIsICJTYXTDqWxpdGUiLCAiVG9wb2dyw6FmaWNvIiksDQogICAgb3ZlcmxheUdyb3VwcyA9IGMoIlByb3llY3RvcyBwb3IgUGFycm9xdWlhIiwgIkzDrW1pdGVzIE11bmljaXBhbGVzIiwgIkNlbnRyb3MgUG9ibGFkb3MiKSwNCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gRkFMU0UpDQogICkgJT4lDQogIA0KICAjIExleWVuZGENCiAgYWRkTGVnZW5kKA0KICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IiwNCiAgICBwYWwgPSBwYWxfcHJveWVjdG9zLA0KICAgIHZhbHVlcyA9IH50b3RhbF9wcm95ZWN0b3MsDQogICAgdGl0bGUgPSAiUHJveWVjdG9zIEFDQSIsDQogICAgb3BhY2l0eSA9IDAuOCwNCiAgICBncm91cCA9ICJQcm95ZWN0b3MgcG9yIFBhcnJvcXVpYSINCiAgKSAlPiUNCiAgDQogICMgRXNjYWxhDQogIGFkZFNjYWxlQmFyKHBvc2l0aW9uID0gImJvdHRvbWxlZnQiKSAlPiUNCiAgYWRkRnVsbHNjcmVlbkNvbnRyb2woKSAlPiUNCiAgDQogICMgVMOtdHVsbw0KICBhZGRDb250cm9sKA0KICAgIGh0bWwgPSAiPGRpdiBzdHlsZT0nYmFja2dyb3VuZDogcmdiYSgyNTUsMjU1LDI1NSwwLjkpOyBwYWRkaW5nOiA4cHg7IGJvcmRlci1yYWRpdXM6IDVweDsgYm9yZGVyOiAxcHggc29saWQgI2NjYzsnPg0KICAgICAgICAgICAgPGg0IHN0eWxlPSdtYXJnaW46IDA7IGNvbG9yOiAjMmMzZTUwOyc+RGlzdHJpYnVjacOzbiBUZXJyaXRvcmlhbCBkZSBQcm95ZWN0b3MgQUNBPC9oND4NCiAgICAgICAgICAgIDxwIHN0eWxlPSdtYXJnaW46IDA7IGZvbnQtc2l6ZTogMTJweDsgY29sb3I6ICM3ZjhjOGQ7Jz5Fc3RhZG8gTcOpcmlkYSAtIENsaWNrIGVuIGxhcyDDoXJlYXMgcGFyYSBtw6FzIGluZm9ybWFjacOzbjwvcD4NCiAgICAgICAgICAgPC9kaXY+IiwNCiAgICBwb3NpdGlvbiA9ICJ0b3BsZWZ0Ig0KICApDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDQuIE1BUEEgSU5URVJBQ1RJVk8gMjogRUZFQ1RJVklEQUQgWSBESVZFUlNJREFEDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIkNyZWFuZG8gTWFwYSAyOiBFZmVjdGl2aWRhZCB5IGRpdmVyc2lkYWQuLi5cbiIpDQoNCnBhbF9lZmVjdGl2aWRhZCA8LSBjb2xvckJpbigNCiAgIlJkWWxHbiIsIA0KICBkb21haW4gPSBkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvJGVmZWN0aXZpZGFkX3Byb21lZGlvLA0KICBiaW5zID0gYygwLCAxLCAyLCAzLCA0KSwNCiAgbmEuY29sb3IgPSAidHJhbnNwYXJlbnQiDQopDQoNCm1hcGFfZWZlY3RpdmlkYWQgPC0gbGVhZmxldChkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvKSAlPiUNCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lDQogIA0KICAjIENhcGEgZGUgZWZlY3RpdmlkYWQNCiAgYWRkUG9seWdvbnMoDQogICAgZmlsbENvbG9yID0gfnBhbF9lZmVjdGl2aWRhZChlZmVjdGl2aWRhZF9wcm9tZWRpbyksDQogICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIHdlaWdodCA9IDEsDQogICAgcG9wdXAgPSB+cG9wdXBfY29udGVudF9zYWZlLA0KICAgIGxhYmVsID0gfnBhc3RlKFBBUlJPUVVJQSwgIi0gRWZlY3RpdmlkYWQ6IiwgZWZlY3RpdmlkYWRfcHJvbWVkaW8pLA0KICAgIGdyb3VwID0gIkVmZWN0aXZpZGFkIiwNCiAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucygNCiAgICAgIGNvbG9yID0gIiNGRjRENEQiLA0KICAgICAgd2VpZ2h0ID0gMywNCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUNCiAgICApDQogICkgJT4lDQogIA0KICAjIENhcGEgZGUgZGl2ZXJzaWRhZCAoY8OtcmN1bG9zKQ0KICBhZGRDaXJjbGVNYXJrZXJzKA0KICAgIGRhdGEgPSBkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvICU+JSBmaWx0ZXIoIWlzLm5hKHByb3llY3Rvc191bmljb3MpICYgcHJveWVjdG9zX3VuaWNvcyA+IDApLA0KICAgIGxuZyA9IH5zdF9jb29yZGluYXRlcyhzdF9jZW50cm9pZChnZW9tZXRyeSkpWywxXSwNCiAgICBsYXQgPSB+c3RfY29vcmRpbmF0ZXMoc3RfY2VudHJvaWQoZ2VvbWV0cnkpKVssMl0sDQogICAgcmFkaXVzID0gfnNxcnQocHJveWVjdG9zX3VuaWNvcykgKiAyLA0KICAgIGNvbG9yID0gIiM4RTQ0QUQiLA0KICAgIGZpbGxDb2xvciA9ICIjOUI1OUI2IiwNCiAgICBmaWxsT3BhY2l0eSA9IDAuNiwNCiAgICB3ZWlnaHQgPSAxLA0KICAgIHBvcHVwID0gfnBhc3RlKCI8c3Ryb25nPkRpdmVyc2lkYWQ6ICIsIHByb3llY3Rvc191bmljb3MsICIgdGlwb2xvZ8OtYXM8L3N0cm9uZz4iKSwNCiAgICBsYWJlbCA9IH5wYXN0ZSgiRGl2ZXJzaWRhZDoiLCBwcm95ZWN0b3NfdW5pY29zKSwNCiAgICBncm91cCA9ICJEaXZlcnNpZGFkIFRpcG9sw7NnaWNhIg0KICApICU+JQ0KICANCiAgIyBDb250cm9sZXMNCiAgYWRkTGF5ZXJzQ29udHJvbCgNCiAgICBvdmVybGF5R3JvdXBzID0gYygiRWZlY3RpdmlkYWQiLCAiRGl2ZXJzaWRhZCBUaXBvbMOzZ2ljYSIpLA0KICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkNCiAgKSAlPiUNCiAgDQogICMgTGV5ZW5kYXMNCiAgYWRkTGVnZW5kKA0KICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IiwNCiAgICBwYWwgPSBwYWxfZWZlY3RpdmlkYWQsDQogICAgdmFsdWVzID0gfmVmZWN0aXZpZGFkX3Byb21lZGlvLA0KICAgIHRpdGxlID0gIkVmZWN0aXZpZGFkPGJyPlByb21lZGlvIiwNCiAgICBvcGFjaXR5ID0gMC44LA0KICAgIGdyb3VwID0gIkVmZWN0aXZpZGFkIg0KICApICU+JQ0KICANCiAgYWRkTGVnZW5kKA0KICAgIHBvc2l0aW9uID0gImJvdHRvbWxlZnQiLA0KICAgIGNvbG9ycyA9IGMoIiM5QjU5QjYiKSwNCiAgICBsYWJlbHMgPSBjKCJEaXZlcnNpZGFkIFRpcG9sw7NnaWNhIiksDQogICAgdGl0bGUgPSAiSW5kaWNhZG9yZXMiLA0KICAgIG9wYWNpdHkgPSAwLjgsDQogICAgZ3JvdXAgPSAiRGl2ZXJzaWRhZCBUaXBvbMOzZ2ljYSINCiAgKSAlPiUNCiAgDQogIGFkZENvbnRyb2woDQogICAgaHRtbCA9ICI8ZGl2IHN0eWxlPSdiYWNrZ3JvdW5kOiByZ2JhKDI1NSwyNTUsMjU1LDAuOSk7IHBhZGRpbmc6IDhweDsgYm9yZGVyLXJhZGl1czogNXB4OyBib3JkZXI6IDFweCBzb2xpZCAjY2NjOyc+DQogICAgICAgICAgICA8aDQgc3R5bGU9J21hcmdpbjogMDsgY29sb3I6ICMyYzNlNTA7Jz5FZmVjdGl2aWRhZCB5IERpdmVyc2lkYWQgZGUgUHJveWVjdG9zPC9oND4NCiAgICAgICAgICAgIDxwIHN0eWxlPSdtYXJnaW46IDA7IGZvbnQtc2l6ZTogMTJweDsgY29sb3I6ICM3ZjhjOGQ7Jz7DgXJlYXMgPSBFZmVjdGl2aWRhZCDigKIgQ8OtcmN1bG9zID0gRGl2ZXJzaWRhZDwvcD4NCiAgICAgICAgICAgPC9kaXY+IiwNCiAgICBwb3NpdGlvbiA9ICJ0b3BsZWZ0Ig0KICApDQoNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDUuIE1BUEEgSU5URVJBQ1RJVk8gMzogVElQT1MgREUgQ09NVU5BDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpjYXQoIkNyZWFuZG8gTWFwYSAzOiBUaXBvcyBkZSBjb211bmEuLi5cbiIpDQoNCiMgUHJlcGFyYXIgdGlwb3MgZGUgY29tdW5hDQp0aXBvc19jb211bmFfdW5pY29zIDwtIHVuaXF1ZShkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvJHRpcG9fY29tdW5hX3ByaW5jaXBhbCkNCnRpcG9zX2NvbXVuYV91bmljb3MgPC0gdGlwb3NfY29tdW5hX3VuaWNvc1shaXMubmEodGlwb3NfY29tdW5hX3VuaWNvcykgJiB0aXBvc19jb211bmFfdW5pY29zICE9ICIiXQ0KDQpjYXQoIlRpcG9zIGRlIGNvbXVuYSBlbmNvbnRyYWRvczoiLCBwYXN0ZSh0aXBvc19jb211bmFfdW5pY29zLCBjb2xsYXBzZSA9ICIsICIpLCAiXG4iKQ0KDQojIERlZmluaXIgY29sb3JlcyBwYXJhIGxvcyB0aXBvcyBkZSBjb211bmEgZXhpc3RlbnRlcw0KY29sb3Jlc19jb211bmEgPC0gYygNCiAgIlVyYmFuYSIgPSAiIzFmNzdiNCIsDQogICJSdXJhbCIgPSAiI2Q2MjcyOCIsIA0KICAiTWl4dGEiID0gIiNmZjdmMGUiLA0KICAiRW4gY29uc3RydWNjaW9uIiA9ICIjMmNhMDJjIiwNCiAgIk5vIGVzcGVjaWZpY2FkbyIgPSAiIzk0NjdiZCINCikNCg0KIyBGaWx0cmFyIHNvbG8gbG9zIGNvbG9yZXMgbmVjZXNhcmlvcw0KY29sb3Jlc19uZWNlc2FyaW9zIDwtIGNvbG9yZXNfY29tdW5hW25hbWVzKGNvbG9yZXNfY29tdW5hKSAlaW4lIHRpcG9zX2NvbXVuYV91bmljb3NdDQoNCiMgU2kgbm8gaGF5IHRpcG9zLCB1c2FyIHVuIGNvbG9yIHBvciBkZWZlY3RvDQppZihsZW5ndGgoY29sb3Jlc19uZWNlc2FyaW9zKSA9PSAwKSB7DQogIGNvbG9yZXNfbmVjZXNhcmlvcyA8LSBjKCJEZWZhdWx0IiA9ICIjODA4MDgwIikNCiAgZGF0b3NfcGFycm9xdWlhc19pbnRlcmFjdGl2byR0aXBvX2NvbXVuYV9wcmluY2lwYWxbaXMubmEoZGF0b3NfcGFycm9xdWlhc19pbnRlcmFjdGl2byR0aXBvX2NvbXVuYV9wcmluY2lwYWwpXSA8LSAiRGVmYXVsdCINCn0NCg0KcGFsX3RpcG9fY29tdW5hIDwtIGNvbG9yRmFjdG9yKA0KICBwYWxldHRlID0gY29sb3Jlc19uZWNlc2FyaW9zLA0KICBkb21haW4gPSBkYXRvc19wYXJyb3F1aWFzX2ludGVyYWN0aXZvJHRpcG9fY29tdW5hX3ByaW5jaXBhbA0KKQ0KDQptYXBhX3RpcG9zX2NvbXVuYSA8LSBsZWFmbGV0KGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8pICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlZveWFnZXIpICU+JQ0KICANCiAgIyBDYXBhIGRlIHRpcG9zIGRlIGNvbXVuYQ0KICBhZGRQb2x5Z29ucygNCiAgICBmaWxsQ29sb3IgPSB+cGFsX3RpcG9fY29tdW5hKHRpcG9fY29tdW5hX3ByaW5jaXBhbCksDQogICAgZmlsbE9wYWNpdHkgPSAwLjcsDQogICAgY29sb3IgPSAid2hpdGUiLA0KICAgIHdlaWdodCA9IDEsDQogICAgcG9wdXAgPSB+cG9wdXBfY29udGVudF9zYWZlLA0KICAgIGxhYmVsID0gfnBhc3RlKFBBUlJPUVVJQSwgIi0iLCB0aXBvX2NvbXVuYV9wcmluY2lwYWwpLA0KICAgIGdyb3VwID0gIlRpcG9zIGRlIENvbXVuYSIsDQogICAgaGlnaGxpZ2h0T3B0aW9ucyA9IGhpZ2hsaWdodE9wdGlvbnMoDQogICAgICBjb2xvciA9ICIjRkY0RDREIiwNCiAgICAgIHdlaWdodCA9IDMsDQogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFDQogICAgKQ0KICApICU+JQ0KICANCiAgIyBDbHVzdGVycyBkZSBjZW50cm9zIHBvYmxhZG9zDQogIGFkZE1hcmtlcnMoDQogICAgZGF0YSA9IGNlbnRyb3Nfc2Zfd2dzLA0KICAgIGNsdXN0ZXJPcHRpb25zID0gbWFya2VyQ2x1c3Rlck9wdGlvbnMoKSwNCiAgICBncm91cCA9ICJDZW50cm9zIFBvYmxhZG9zIChDbHVzdGVycykiLA0KICAgIHBvcHVwID0gfmlmKGV4aXN0cygiTk9NQ0VOUE9CIiwgd2hlcmUgPSBjZW50cm9zX3NmX3dncykpIHBhc3RlKCI8c3Ryb25nPiIsIE5PTUNFTlBPQiwgIjwvc3Ryb25nPiIpIGVsc2UgIjxzdHJvbmc+Q2VudHJvIFBvYmxhZG88L3N0cm9uZz4iDQogICkgJT4lDQogIA0KICAjIENvbnRyb2xlcw0KICBhZGRMYXllcnNDb250cm9sKA0KICAgIGJhc2VHcm91cHMgPSAiQ2FydG9EQi5Wb3lhZ2VyIiwNCiAgICBvdmVybGF5R3JvdXBzID0gYygiVGlwb3MgZGUgQ29tdW5hIiwgIkNlbnRyb3MgUG9ibGFkb3MgKENsdXN0ZXJzKSIpLA0KICAgIG9wdGlvbnMgPSBsYXllcnNDb250cm9sT3B0aW9ucyhjb2xsYXBzZWQgPSBGQUxTRSkNCiAgKSAlPiUNCiAgDQogICMgTGV5ZW5kYQ0KICBhZGRMZWdlbmQoDQogICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiLA0KICAgIHBhbCA9IHBhbF90aXBvX2NvbXVuYSwNCiAgICB2YWx1ZXMgPSB+dGlwb19jb211bmFfcHJpbmNpcGFsLA0KICAgIHRpdGxlID0gIlRpcG9zIGRlIENvbXVuYSIsDQogICAgb3BhY2l0eSA9IDAuOA0KICApICU+JQ0KICANCiAgYWRkQ29udHJvbCgNCiAgICBodG1sID0gIjxkaXYgc3R5bGU9J2JhY2tncm91bmQ6IHJnYmEoMjU1LDI1NSwyNTUsMC45KTsgcGFkZGluZzogOHB4OyBib3JkZXItcmFkaXVzOiA1cHg7IGJvcmRlcjogMXB4IHNvbGlkICNjY2M7Jz4NCiAgICAgICAgICAgIDxoNCBzdHlsZT0nbWFyZ2luOiAwOyBjb2xvcjogIzJjM2U1MDsnPlRpcG9sb2fDrWEgQ29tdW5hbCBkZWwgRXN0YWRvIE3DqXJpZGE8L2g0Pg0KICAgICAgICAgICAgPHAgc3R5bGU9J21hcmdpbjogMDsgZm9udC1zaXplOiAxMnB4OyBjb2xvcjogIzdmOGM4ZDsnPkNsYXNpZmljYWNpw7NuIHRlcnJpdG9yaWFsIGNvbiBjbHVzdGVycyBkZSBjZW50cm9zIHBvYmxhZG9zPC9wPg0KICAgICAgICAgICA8L2Rpdj4iLA0KICAgIHBvc2l0aW9uID0gInRvcGxlZnQiDQogICkNCg0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgNi4gTU9TVFJBUiBUT0RPUyBMT1MgUkVTVUxUQURPUw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCJNb3N0cmFuZG8gcmVzdWx0YWRvcy4uLlxuIikNCg0KIyBNb3N0cmFyIG1hcGFzDQpjYXQoIiMjIyBNYXBhIDE6IERpc3RyaWJ1Y2nDs24gVGVycml0b3JpYWxcbiIpDQptYXBhX2Rpc3RyaWJ1Y2lvbg0KDQpjYXQoIiMjIyBNYXBhIDI6IEVmZWN0aXZpZGFkIHkgRGl2ZXJzaWRhZFxuIikNCm1hcGFfZWZlY3RpdmlkYWQNCg0KY2F0KCIjIyMgTWFwYSAzOiBUaXBvcyBkZSBDb211bmFcbiIpDQptYXBhX3RpcG9zX2NvbXVuYQ0KDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyA3LiBSRVNVTUVOIEVTVEFEw41TVElDTw0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KY2F0KCIjIyMgUmVzdW1lbiBFc3RhZMOtc3RpY28gZGVsIEFuw6FsaXNpc1xuIikNCg0KZXN0YWRpc3RpY2FzIDwtIGRhdGEuZnJhbWUoDQogIE3DqXRyaWNhID0gYygNCiAgICAiVG90YWwgUHJveWVjdG9zIEFuYWxpemFkb3MiLA0KICAgICJDb211bmFzIEV2YWx1YWRhcyIsIA0KICAgICJQYXJyb3F1aWFzIGNvbiBQcm95ZWN0b3MiLA0KICAgICJFZmVjdGl2aWRhZCBQcm9tZWRpbyBHZW5lcmFsIiwNCiAgICAiVGlwb2xvZ8OtYXMgRGlmZXJlbnRlcyBJZGVudGlmaWNhZGFzIiwNCiAgICAiTXVuaWNpcGlvcyBJbnZvbHVjcmFkb3MiDQogICksDQogIFZhbG9yID0gYygNCiAgICBucm93KGRmX3JhdyksDQogICAgbl9kaXN0aW5jdChkZl9yYXckSURfQ09NVU5BKSwNCiAgICBuX2Rpc3RpbmN0KGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kSURbIWlzLm5hKGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kdG90YWxfcHJveWVjdG9zKSAmIGRhdG9zX3BhcnJvcXVpYXNfaW50ZXJhY3Rpdm8kdG90YWxfcHJveWVjdG9zID4gMF0pLA0KICAgIHJvdW5kKG1lYW4oZGZfcmF3JFJBVElPX0FDQV9QUk9ZRUNUT19DVUxNSU5BRE8sIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIG5fZGlzdGluY3QoZGZfcmF3JENMQVNJRklDQUNJw5NOX0RFTF9OVURPX0NSSVRJQ09fVElQT0xPR0lBX0NGRyksDQogICAgbl9kaXN0aW5jdChkZl9yYXckQ29kaWdvX011bmljaXBhbCkNCiAgKQ0KKQ0KDQojIE1vc3RyYXIgdGFibGEgZGUgZXN0YWTDrXN0aWNhcw0Ka25pdHI6OmthYmxlKA0KICBlc3RhZGlzdGljYXMsDQogIGNhcHRpb24gPSAiUmVzdW1lbiBHZW5lcmFsIGRlbCBBbsOhbGlzaXMgZGUgQWdlbmRhcyBDb25jcmV0YXMgZGUgQWNjacOzbiAtIEVzdGFkbyBNw6lyaWRhIDIwMTktMjAyNSIsDQogIGFsaWduID0gYygnbCcsICdjJykNCikNCg0KY2F0KCJcbi0tLSBBTsOBTElTSVMgQ09NUExFVEFETyAtLS1cbiIpDQpjYXQoIlNlIGhhbiBnZW5lcmFkbyAzIG1hcGFzIGludGVyYWN0aXZvc1xuIikNCmBgYA0K