Limpiando los datos
Para limpiar las base de datos se seguiran los siguientes pasos:
- Uniformizar el formato de las horas: timezone UTC, con el nombre
Hora_Lima
- Asignar el mismo nombre a la variable temperatura de fondo:
Temp_fond
- Asignar el mismo nombre a la variable saturacion de oxigeno
disuelto: DO_sat
- En caso haya mas de un dato por hora, btener un valor promedio
- Verificar si hay filas duplicadas, valores NA, valores
negativos.
- Asignar una columna con el nombre de la base de datos de
origen.
Limpieza de bdd: Cueto-Vega et al. 2022
constante_loggers <- read_csv("datos/bd-ARTURO-PICES_Sechura_Stressors/CONSTANTE_loggers_historico.csv") %>%
mutate(
Hora_Lima = as.POSIXct(Hora_Lima, format = "%Y-%m-%d %H:%M:%S", tz = "UTC"),
Temp_fond = Temp
) %>%
select(Hora_Lima, Temp_fond, DO_sat) %>%
group_by(Hora_Lima) %>%
summarise(
Temp_fond = mean(Temp_fond, na.rm = TRUE),
DO_sat = mean(DO_sat, na.rm = TRUE)
)
valores_duplicados <- constante_loggers$Hora_Lima[duplicated(constante_loggers$Hora_Lima)]
print(unique(valores_duplicados))
colSums(is.na(constante_loggers))
eliminar <- which(apply(is.na(constante_loggers), 1, any)) #Hay 11821 filas que no tiene datos de DO_sat
constante_loggers <- constante_loggers[-eliminar, ]
colSums(is.nan(as.matrix(constante_loggers)))
any(constante_loggers < 0, na.rm = TRUE)
constante_loggers <- filter(constante_loggers, DO_sat >= 0, DO_sat <=100, !is.na(DO_sat))
constante_loggers <- constante_loggers %>%
mutate(
bdd = "Cueto-Vega_2022",
Zona = "Constante")
Limpeza de bdd: Aguirre-Velarde 2019 Los datos
recopilados por Aguirre-Velarde en el 2019 estan conformados por dos
archivos csv:
- Constante_loggers.csv (08 enero 2019 - 04 marzo 2019)
### BDD Constante_loggers ####
constante_TDO <- read.csv("datos/Informe_SechuraMort2019/Constante_loggers.csv", header = TRUE, dec = ".", sep = ",") %>%
mutate(
Hora_Lima = as.POSIXct(Hora_Lima, format = "%d/%m/%Y %H:%M", tz="UTC"),
Temp_fond = Temp
) %>%
select(Hora_Lima, Temp_fond, DO_sat) %>%
group_by(Hora_Lima) %>%
summarise(
Temp_fond = mean(Temp_fond, na.rm = TRUE),
DO_sat = mean(DO_sat, na.rm = TRUE)
)
valores_duplicados <- constante_TDO$Hora_Lima[duplicated(constante_TDO$Hora_Lima)]
print(unique(valores_duplicados))
colSums(is.na(constante_TDO))
which(apply(is.na(constante_TDO), 1, any)) #La fila 1321 no tiene datos
constante_TDO <- constante_TDO[-1321, ]
colSums(is.nan(as.matrix(constante_TDO)))
any(constante_TDO < 0, na.rm = TRUE)
constante_TDO <- constante_TDO %>%
mutate(
bdd = "Constante_TDO",
Zona = "Constante")
- Constante_multi.csv (05 marzo - 26 de marzo 2019)
En esta base de datos, el oxígeno esta en mg/L, por lo que se debe
convertir DO_c (mg/l) en DO_sat (%). Para ello, se seguirán las
ecuaciones propuestas por Benson y Krause, 1984; utilizadas por YDOC: empresa
holandesa especializada en mediciones por data loggers.
### BDD constante_multi ######
constante_multi <- read.csv("datos/Informe_SechuraMort2019/constante_multi.csv",
header = TRUE, dec = ".", sep = ",") %>%
mutate(
Hora_Lima = as.POSIXct(Hora_Lima, format = "%d/%m/%Y %H:%M:%S", tz="UTC"),
Hora_Lima = make_datetime(year(Hora_Lima), month(Hora_Lima), day(Hora_Lima), hour(Hora_Lima)),
DO_c = DO_fond,
Temp_fond = T_fond,
Temp_kelvin = Temp_fond + 273.15 # Convertir temperatura a Kelvin
) %>%
select(Hora_Lima, Temp_fond, Temp_kelvin, DO_c) %>%
group_by(Hora_Lima) %>%
summarise(
Temp_fond = mean(Temp_fond, na.rm = TRUE),
DO_c = mean(DO_c, na.rm = TRUE),
Temp_kelvin=mean(Temp_kelvin, na.rm=TRUE)
)
valores_duplicados <- constante_multi$Hora_Lima[duplicated(constante_multi$Hora_Lima)]
print(unique(valores_duplicados))
colSums(is.na(constante_multi))
eliminar <- which(apply(is.na(constante_multi), 1, any))
constante_multi <- constante_multi[-eliminar,]
colSums(is.nan(as.matrix(constante_multi)))
any(constante_TDO < 0, na.rm = TRUE)
## Convertir DO_c (mg/l) en DO_sat (%) siguiendo ecuaciones de Benson and Krause, 1984
# Definir salinidad en ppt (g/kg)
SAL <- 35
# Calcular DO_C (corrigiendo por salinidad)
constante_multi <- constante_multi %>%
mutate(
DO_C = DO_c * exp(-1 * SAL * (0.017674 + (-10.754 + 2140.7 / Temp_kelvin) / Temp_kelvin))
)
# Calcular DO saturado en mg/L
constante_multi <- constante_multi %>%
mutate(
DO_sat_mgL = exp(-139.34411 + (1.575701e5 + (-6.642308e7 +
(1.2438e10 - 8.621949e11 / Temp_kelvin) / Temp_kelvin) / Temp_kelvin) / Temp_kelvin) *
exp(-1 * SAL * (0.017674 + (-10.754 + 2140.7 / Temp_kelvin) / Temp_kelvin))
)
# Calcular DO saturado en %
constante_multi <- constante_multi %>%
mutate(
DO_sat = (DO_C / DO_sat_mgL) * 100
) %>%
select(Hora_Lima, Temp_fond, DO_sat)
#Agregar columnas bdd
constante_multi <- constante_multi %>%
mutate(
bdd = "Constante_multi",
Zona = "Constante")
Finalmente, las bases de datos se unirán en una sola, la cual será
llamada “constante”. En esta nueva bdd, se agregará la
columna “Mortalidad”.
- Mortalidad 2015: 21 febrero - 02 marzo - 15 marzo
2015
- Mortalidad 2019: 19 febrero - 04 marzo - 13 marzo
2019
- No mortalidad: resto de datos
barrancos <- read_csv("datos/bd-ARTURO-PICES_Sechura_Stressors/BARRANCOS_loggers_historico.csv") %>%
mutate(
Hora_Lima = as.POSIXct(Hora_Lima, format = "%Y-%m-%d %H:%M:%S", tz = "UTC"),
Temp_fond = Temp
) %>%
select(Hora_Lima, Temp_fond, DO_sat) %>%
group_by(Hora_Lima) %>%
summarise(
Temp_fond = mean(Temp_fond, na.rm = TRUE),
DO_sat = mean(DO_sat, na.rm = TRUE)
)
valores_duplicados <- barrancos$Hora_Lima[duplicated(barrancos$Hora_Lima)]
a <- colSums(is.na(barrancos))
eliminar <- which(apply(is.na(barrancos), 1, any))
barrancos <- barrancos[-eliminar, ]
a <- colSums(is.nan(as.matrix(barrancos)))
a <- any(barrancos < 0, na.rm = TRUE)
barrancos <- filter(barrancos, DO_sat >= 0, DO_sat <=100, !is.na(DO_sat))
barrancos <- barrancos %>%
mutate(
bdd = "Cueto-Vega_2022",
Zona = "Barrancos")
barrancos_filtr <- barrancos %>%
filter(Hora_Lima >= as.POSIXct("2015-02-21", tz="UTC") & Hora_Lima <= as.POSIXct("2015-03-15", tz="UTC"))
constante <- bind_rows(constante_loggers, constante_TDO, constante_multi)
total <- bind_rows(constante, barrancos_filtr)
total <- total %>%
mutate(
Year = format(Hora_Lima, "%Y"), # Extraer el año
Mortalidad = case_when(
(Zona == "Barrancos" & Hora_Lima >= as.POSIXct("2015-02-21", tz = "UTC") & Hora_Lima < as.POSIXct("2015-03-15", tz = "UTC")) ~ "Mortalidad 2015 - Barrancos",
(Zona == "Constante" & Hora_Lima >= as.POSIXct("2015-02-21", tz = "UTC") & Hora_Lima < as.POSIXct("2015-03-15", tz = "UTC")) ~ "Mortalidad 2015 - Constante",
(Zona == "Constante" & Hora_Lima >= as.POSIXct("2019-02-19", tz = "UTC") & Hora_Lima < as.POSIXct("2019-03-13", tz = "UTC")) ~ "Mortalidad 2019 - Constante",
TRUE ~ "No Mortalidad"
)
)
# Contar observaciones por categoría de Mortalidad y Zona
conteo_obs <- total %>%
group_by(Mortalidad) %>%
summarise(Conteo = n(), .groups = "drop")
# Ver los resultados
print(conteo_obs)
Varaibilidad Diaria de la Saturación OD
Para el análisis de datos, primero se realizará la caracterización
ambiental de los registros hipóxicos en Constante. Para ello se
analizará la variabilidad diaria de la saturación de OD en el fondo, los
registros se clasificarán entre día (06:00 – 17:59) y noche (18:00 –
05:59), y se representarán mediante diagrama de cajas. Para
evaluar la variabilidad del ciclo diario se ajustará una función
sinusoidal a las medianas del análisis del diagrama de caja, con el fin
de determinar y comparar la amplitud y la fase del ciclo diario durante
el tiempo de muestreo. Este análisis sigue la metodología planteada por
Igarza et al. (2024).
# Extraer solo la Hora en una nueva columna
total <- total %>%
mutate(
Hora = as.integer(format(Hora_Lima, "%H")),
DiaNoche = ifelse(Hora >= 6 & Hora <= 17, "Día", "Noche")
)
# Definir los colores
colores <- c("Día" = "gray100", "Noche" = "gray80")
# Crear el gráfico con boxplots por cada hora
ggplot(total, aes(x = factor(Hora), y = DO_sat, fill = DiaNoche)) +
geom_boxplot(width = 0.6, alpha = 0.8, outlier.alpha = 0.5, outlier.size = 1) +
facet_wrap(~ Mortalidad, ncol = 2) + # Una faceta por cada periodo de mortalidad
labs(
x = "Hora del Día",
y = "Saturación OD (%)",
fill = "Momento del Día",
title = "Variabilidad Diara de Saturación de Oxígeno"
) +
scale_x_discrete(breaks = seq(0, 23, by = 2)) +
scale_fill_manual(values = colores) +
geom_hline(yintercept = 24.4, linetype = "dashed", color = "red", size = 0.5) +
theme_minimal() +
theme(
strip.background = element_rect(fill = "gray95", color = "black"), # Fondo de las facetas
strip.text = element_text(face = "bold", size = 12), # Texto en las facetas
axis.text = element_text(size = 10), # Tamaño de texto de los ejes
axis.title = element_text(size = 12), # Tamaño de texto de títulos de ejes
panel.grid.major = element_blank(), # Quitar líneas de grilla mayor
panel.grid.minor = element_blank(), # Quitar líneas de grilla menor
axis.line = element_line(color = "black"), # Añadir líneas de los ejes
axis.ticks = element_line(color = "black") # Añadir marcas en los ejes
)

# 1. Calcular la mediana de DO_sat por Hora y Mortalidad
mediana_por_hora <- total %>%
group_by(Mortalidad, Hora) %>%
summarise(
Mediana_DO_sat = median(DO_sat, na.rm = TRUE),
.groups = "drop"
)
# 2. Definir la función sinusoidal
sinusoidal <- function(x, amplitud, frecuencia, fase, desplazamiento) {
amplitud * sin(frecuencia * x + fase) + desplazamiento
}
# 3. Ajustar la función sinusoidal a los datos
ajustes <- mediana_por_hora %>%
group_by(Mortalidad) %>%
summarise(
# Calcular parámetros iniciales
amplitud_inicio = (max(Mediana_DO_sat, na.rm = TRUE) - min(Mediana_DO_sat, na.rm = TRUE)) / 2,
desplazamiento_inicio = mean(Mediana_DO_sat, na.rm = TRUE),
ajuste = list(
nlsLM(
Mediana_DO_sat ~ sinusoidal(Hora, amplitud, frecuencia, fase, desplazamiento),
data = cur_data(),
start = list(
amplitud = amplitud_inicio,
frecuencia = 2 * pi / 24, # Frecuencia para ciclo de 24 horas
fase = 0, # Inicialmente sin desplazamiento
desplazamiento = desplazamiento_inicio
)
)
),
.groups = "drop"
)
# 4. Extraer los parámetros ajustados y corregir amplitud y fase
parametros <- ajustes %>%
mutate(
coeficientes = map(ajuste, coef)
) %>%
select(Mortalidad, coeficientes) %>%
unnest_wider(coeficientes) %>%
mutate(
Amplitud = abs(amplitud), # Asegurar amplitud positiva
Fase = ifelse(amplitud < 0, fase + pi, fase), # Corregir fase si amplitud era negativa
Horamax = (-Fase / frecuencia) %% 24 # Calcular la hora del máximo y asegurar 0-24
) %>%
select(Mortalidad, Amplitud, Frecuencia = frecuencia, Fase, Desplazamiento = desplazamiento, Horamax)
# Imprimir los parámetros ajustados
print(parametros)
## # A tibble: 4 × 6
## Mortalidad Amplitud Frecuencia Fase Desplazamiento Horamax
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Mortalidad 2015 - Barrancos 8.62 0.324 3.30 15.4 13.8
## 2 Mortalidad 2015 - Constante 12.1 0.353 -2.88 46.0 8.16
## 3 Mortalidad 2019 - Constante 6.92 0.310 3.24 12.6 13.6
## 4 No Mortalidad 3.46 0.298 3.24 33.5 13.1
# 5. Crear datos ajustados con la onda sinusoidal
datos_ajustados <- mediana_por_hora %>%
left_join(parametros, by = "Mortalidad") %>%
mutate(
Ajuste = Amplitud * sin(Frecuencia * Hora + Fase) + Desplazamiento
)
# 6. Graficar datos reales y ajustados con escala fija de 0 a 100
ggplot(datos_ajustados, aes(x = Hora)) +
geom_line(aes(y = Ajuste, color = Mortalidad), linetype = "dashed") +
geom_point(aes(y = Mediana_DO_sat, color = Mortalidad), size = 1) +
facet_wrap(~ Mortalidad, scales = "fixed") + # Escala fija en Y
scale_y_continuous(limits = c(0, 60)) + # Fijar límites de 0 a 100
labs(
title = "Ajuste de función sinusoidal",
x = "Hora del día",
y = "Mediana de Saturación de Oxígeno (DO_sat)"
) +
theme_minimal()

# 7. Crear datos ajustados sin desplazamiento vertical (solo amplitud y fase)
datos_ajustados_sin_d <- mediana_por_hora %>%
left_join(parametros, by = "Mortalidad") %>%
mutate(
Ajuste_sin_d = Amplitud * sin(Frecuencia * Hora + Fase) # Eliminar el desplazamiento vertical
)
# 8. Graficar las ondas sinusoidales sin desplazamiento vertical
ggplot(datos_ajustados_sin_d, aes(x = Hora, y = Ajuste_sin_d, color = Mortalidad)) +
geom_line(size = 1, linetype = "solid") +
labs(
title = "Comparación de ondas sinusoidales",
x = "Hora del día",
y = "Oscilación relativa de DO_sat"
) +
theme_minimal(base_size = 14) +
theme(
legend.position = "bottom",
legend.title = element_blank()
)
La amplitud indica cuánto varía la saturación de oxígeno a lo largo del
día, desde el nivel medio (Desplazamiento) hasta los picos (positivos o
negativos). Es una medida de la variabilidad diaria:
Mayor amplitud → Mayor variación diaria entre día y noche. Menor
amplitud → Ciclo diario menos marcado (saturación más estable).
La frecuencia está relacionada con el número de ciclos completados en
un período de tiempo. Interpretación: La frecuencia debería ser
aproximadamente 0.2618 si las oscilaciones ocurren exactamente cada 24
horas. Tus resultados tienen ligeras diferencias:
Mortalidad 2015 - Constante (0.353): Frecuencia un poco mayor, lo
que podría indicar oscilaciones más rápidas (ligeramente desfasadas del
ciclo diario perfecto).
No Mortalidad (0.298): Frecuencia más baja, lo que sugiere
oscilaciones más lentas y un ciclo más “extendido”.
En general, estas pequeñas diferencias podrían deberse a ruido o a
fenómenos biológicos que desvíen el ciclo de un patrón estrictamente
diario.
La fase indica el desplazamiento horizontal de la onda sinusoidal, es
decir, en qué momento del día ocurre el máximo o mínimo de
saturación.
Indicadores de hipoxia
Se evaluará la variabilidad de hipoxia mediante los siguientes
indicadores: el porcentaje de registros hipóxicos, las horas de hipoxia
al día, la mediana de saturación de OD al día y el valor mínimo de
saturación de OD al día.
Después del análisis de la variabilidad del ciclo diario de
saturación de OD, se realizará el análisis de los eventos
hipóxicos. Para determinar un evento hipóxico, este debe ser
igual o inferior al 24.4% de saturación de OD y durar al menos seis
horas consecutivas (Shields y Weidman, 2008).
Numero de horas hipoxicas al dia
Numero de horas hipoxicas al dia:
# Función para agregar columna de hipoxia
agregar_columna_hipoxia <- function(data) {
data$Hipoxia <- ifelse(data$DO_sat <= 24.4, 1, 0)
return(data)
}
total <- agregar_columna_hipoxia(total)
# Función para calcular horas de hipoxia por día
calcular_horas_hipoxia <- function(df) {
df %>%
mutate(Dia = as.Date(Hora_Lima)) %>%
group_by(Dia, Mortalidad) %>%
summarise(Horas_Hipoxia = sum(Hipoxia), .groups = 'drop')
}
horas_hipoxicas <- calcular_horas_hipoxia(total)
# Normalidad de los datos
horas_hipoxicas %>%
group_by(Mortalidad) %>%
summarise(
mensaje = paste(
"Prueba de Shapiro-Wilk para",
first(Mortalidad), # Obtén el nombre del grupo
": p =", signif(shapiro.test(Horas_Hipoxia)$p.value, digits = 3)
)
) %>%
pull(mensaje) %>% # Extrae solo los mensajes
cat(sep = "\n") # Los imprime línea por línea
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Barrancos : p = 0.0238
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Constante : p = 2.25e-05
## Prueba de Shapiro-Wilk para Mortalidad 2019 - Constante : p = 0.00032
## Prueba de Shapiro-Wilk para No Mortalidad : p = 5.03e-28
# Homogeneidad de los datos
levene_result<- leveneTest(Horas_Hipoxia ~ Mortalidad, data = horas_hipoxicas)
# Extraer el valor p del resultado
p_value_levene <- signif(levene_result$`Pr(>F)`[1], digits = 3)
# Crear un mensaje personalizado
cat("Prueba de Levene para homogeneidad de varianzas: p =", p_value_levene, "\n")
## Prueba de Levene para homogeneidad de varianzas: p = 0.659
# Kruskal-Wallis
kruskal_result <- kruskal.test(Horas_Hipoxia ~ Mortalidad, data = horas_hipoxicas)
print(kruskal_result)
##
## Kruskal-Wallis rank sum test
##
## data: Horas_Hipoxia by Mortalidad
## Kruskal-Wallis chi-squared = 29.169, df = 3, p-value = 2.063e-06
# Post-hoc con Dunn para identificar diferencias entre pares de grupos
dunn_result <- dunnTest(Horas_Hipoxia ~ Mortalidad, data = horas_hipoxicas, method = "bonferroni")
# Extraer los resultados en formato de dataframe
tabla_dunn <- as.data.frame(dunn_result$res)
# Renombrar columnas para que sean más legibles
colnames(tabla_dunn) <- c("Comparacion", "Estadistico Z", "P sin ajustar", "P ajustado")
# Crear la tabla con gt
tabla_dunn %>%
gt() %>%
tab_header(
title = "Resultados del Test de Dunn",
subtitle = "Comparaciones de Horas Hipoxicas entre grupos de Mortalidad"
) %>%
fmt_number(
columns = c("Estadistico Z", "P sin ajustar", "P ajustado"),
decimals = 3
) %>%
cols_label(
`Comparacion` = "Grupos Comparados",
`Estadistico Z` = "Estadístico Z",
`P sin ajustar` = "P-valor (sin ajustar)",
`P ajustado` = "P-valor (ajustado)"
)
| Resultados del Test de Dunn |
| Comparaciones de Horas Hipoxicas entre grupos de Mortalidad |
| Grupos Comparados |
Estadístico Z |
P-valor (sin ajustar) |
P-valor (ajustado) |
| Mortalidad 2015 - Barrancos - Mortalidad 2015 - Constante |
3.627 |
0.000 |
0.002 |
| Mortalidad 2015 - Barrancos - Mortalidad 2019 - Constante |
0.297 |
0.766 |
1.000 |
| Mortalidad 2015 - Constante - Mortalidad 2019 - Constante |
−3.507 |
0.000 |
0.003 |
| Mortalidad 2015 - Barrancos - No Mortalidad |
3.749 |
0.000 |
0.001 |
| Mortalidad 2015 - Constante - No Mortalidad |
−1.301 |
0.193 |
1.000 |
| Mortalidad 2019 - Constante - No Mortalidad |
3.696 |
0.000 |
0.001 |
Cual tipo de grafico usar?
# Boxplots
ggplot(horas_hipoxicas, aes(x = Mortalidad, y = Horas_Hipoxia, fill = Mortalidad)) +
geom_boxplot(alpha = 0.7, outlier.shape = NA) +
geom_jitter(width = 0.2, size = 2, alpha = 0.6, color = "black") +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Horas Hipóxicas al día",
x = "",
y = "Horas"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

# Violinplot
ggplot(horas_hipoxicas, aes(x = Mortalidad, y = Horas_Hipoxia, fill = Mortalidad)) +
geom_violin(trim = FALSE, alpha = 0.6, color = "black") +
geom_boxplot(width = 0.1, outlier.shape = NA, alpha = 0.5) +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Horas Hipóxicas al día",
x = "",
y = "Horas"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

# Reordenar los niveles de la variable 'Mortalidad'
horas_hipoxicas$Mortalidad <- factor(
horas_hipoxicas$Mortalidad,
levels = c(
"Mortalidad 2015 - Barrancos",
"Mortalidad 2019 - Constante",
"Mortalidad 2015 - Constante",
"No Mortalidad"
),
labels = c(
"Mortalidad 2015\nBarrancos",
"Mortalidad 2019\nConstante",
"Mortalidad 2015\nConstante",
"No Mortalidad"
)
)
# Stats + graph
ggbetweenstats(
data = horas_hipoxicas,
x = Mortalidad,
y = Horas_Hipoxia,
title = NULL, # Elimina el título
results.subtitle = F, # Elimina el subtítulo que contiene la ecuación
xlab = "",
ylab = "Horas en hipoxia al día",
type = "nonparametric", # Usa Kruskal-Wallis como test principal
pairwise.comparisons = TRUE, # Comparaciones post-hoc entre grupos
var.equal = FALSE,
pairwise.display = "significant", # Solo muestra pares significativos
p.adjust.method = "bonferroni", # Corrección para múltiples comparaciones
ggtheme = ggplot2::theme_minimal(), # Tema minimalista
violin.args = list(width = 0, linewidth = 0) # Para quitar el violin plot
) +
# Personalización del tema
ggplot2::theme(
plot.title = ggplot2::element_text(size = 0), # Quita el título
plot.subtitle = ggplot2::element_text(size = 0), # Quita el subtítulo
legend.text = ggplot2::element_text(size = 12), # Tamaño del texto de la leyenda
axis.text = ggplot2::element_text(size = 12, color = "black"), # Tamaño y color del texto de los ejes
axis.title = ggplot2::element_text(size = 14), # Tamaño de título de los ejes
axis.ticks.length = ggplot2::unit(5, "pt"), # Longitud de los ticks
axis.ticks = ggplot2::element_line(color = "black"), # Color de los ticks
axis.line = ggplot2::element_line(color = "black", size = 0.5), # Líneas de los ejes
panel.grid.major = ggplot2::element_blank(), # Elimina las líneas de la grilla mayor
panel.grid.minor = ggplot2::element_blank() # Elimina las líneas de la grilla menor
) +
ggplot2::scale_color_manual(values = c("#56B4E9", "red", "green", "#D55E00"))

Porcentaje de registros hipóxicos al día
Porcentaje de registros hipóxicos al dia:
# Función para calcular el porcentaje de horas hipóxicas por día
calcular_porcentaje_hipoxia <- function(df) {
df %>%
mutate(Dia = as.Date(Hora_Lima)) %>%
group_by(Dia, Mortalidad) %>%
summarise(
Horas_Hipoxia = sum(Hipoxia), # Contar las horas hipóxicas
Horas_Totales = n(), # Contar el número total de registros por día
Porcentaje = (Horas_Hipoxia / Horas_Totales) * 100, # Calcular el porcentaje de horas hipóxicas
.groups = 'drop'
)
}
# Aplicar la función a tu dataframe
porcentaje_hipoxia <- calcular_porcentaje_hipoxia(total)
# Normalidad de los datos
porcentaje_hipoxia %>%
group_by(Mortalidad) %>%
summarise(
mensaje = paste(
"Prueba de Shapiro-Wilk para",
first(Mortalidad), # Obtén el nombre del grupo
": p =", signif(shapiro.test(Porcentaje)$p.value, digits = 3)
)
) %>%
pull(mensaje) %>% # Extrae solo los mensajes
cat(sep = "\n") # Los imprime línea por línea
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Barrancos : p = 0.000592
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Constante : p = 1.45e-05
## Prueba de Shapiro-Wilk para Mortalidad 2019 - Constante : p = 2.91e-05
## Prueba de Shapiro-Wilk para No Mortalidad : p = 7.13e-28
# Homogeneidad de los datos
levene_result<- leveneTest(Porcentaje ~ Mortalidad, data = porcentaje_hipoxia)
p_value_levene <- signif(levene_result$`Pr(>F)`[1], digits = 3)
cat("Prueba de Levene para homogeneidad de varianzas: p =", p_value_levene, "\n")
## Prueba de Levene para homogeneidad de varianzas: p = 0.00132
# Kruskal-Wallis
kruskal_result <- kruskal.test(Porcentaje ~ Mortalidad, data = porcentaje_hipoxia)
print(kruskal_result)
##
## Kruskal-Wallis rank sum test
##
## data: Porcentaje by Mortalidad
## Kruskal-Wallis chi-squared = 52.345, df = 3, p-value = 2.529e-11
# Post-hoc con Dunn para identificar diferencias entre pares de grupos
dunn_result <- dunnTest(Porcentaje ~ Mortalidad, data = porcentaje_hipoxia, method = "bonferroni")
# Extraer los resultados en formato de dataframe
tabla_dunn <- as.data.frame(dunn_result$res)
# Renombrar columnas para que sean más legibles
colnames(tabla_dunn) <- c("Comparacion", "Estadistico Z", "P sin ajustar", "P ajustado")
# Crear la tabla con gt
tabla_dunn %>%
gt() %>%
tab_header(
title = "Resultados del Test de Dunn",
subtitle = "Comparaciones de Porcentaje de registros hipoxicos entre grupos de Mortalidad"
) %>%
fmt_number(
columns = c("Estadistico Z", "P sin ajustar", "P ajustado"),
decimals = 3
) %>%
cols_label(
`Comparacion` = "Grupos Comparados",
`Estadistico Z` = "Estadístico Z",
`P sin ajustar` = "P-valor (sin ajustar)",
`P ajustado` = "P-valor (ajustado)"
)
| Resultados del Test de Dunn |
| Comparaciones de Porcentaje de registros hipoxicos entre grupos de Mortalidad |
| Grupos Comparados |
Estadístico Z |
P-valor (sin ajustar) |
P-valor (ajustado) |
| Mortalidad 2015 - Barrancos - Mortalidad 2015 - Constante |
3.696 |
0.000 |
0.001 |
| Mortalidad 2015 - Barrancos - Mortalidad 2019 - Constante |
−1.108 |
0.268 |
1.000 |
| Mortalidad 2015 - Constante - Mortalidad 2019 - Constante |
−4.985 |
0.000 |
0.000 |
| Mortalidad 2015 - Barrancos - No Mortalidad |
3.969 |
0.000 |
0.000 |
| Mortalidad 2015 - Constante - No Mortalidad |
−1.177 |
0.239 |
1.000 |
| Mortalidad 2019 - Constante - No Mortalidad |
5.993 |
0.000 |
0.000 |
ggplot(porcentaje_hipoxia, aes(x = Mortalidad, y = Porcentaje, fill = Mortalidad)) +
geom_boxplot(alpha = 0.7, outlier.shape = NA) +
geom_jitter(width = 0.2, size = 2, alpha = 0.6, color = "black") +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Registros Hipóxicos al día",
x = "",
y = "Porcentaje %"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

ggplot(porcentaje_hipoxia, aes(x = Mortalidad, y = Porcentaje, fill = Mortalidad)) +
geom_violin(trim = FALSE, alpha = 0.6, color = "black") +
geom_boxplot(width = 0.1, outlier.shape = NA, alpha = 0.5) +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Registros Hipóxicos al día",
x = "",
y = "Porcentaje %"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

# Reordenar los niveles de la variable 'Mortalidad'
porcentaje_hipoxia$Mortalidad <- factor(
porcentaje_hipoxia$Mortalidad,
levels = c(
"Mortalidad 2015 - Barrancos",
"Mortalidad 2019 - Constante",
"Mortalidad 2015 - Constante",
"No Mortalidad"
),
labels = c(
"Mortalidad 2015\nBarrancos",
"Mortalidad 2019\nConstante",
"Mortalidad 2015\nConstante",
"No Mortalidad"
)
)
# Stats + graph
ggbetweenstats(
data = porcentaje_hipoxia,
x = Mortalidad,
y = Porcentaje,
title = NULL, # Elimina el título
results.subtitle =F, # Elimina el subtítulo que contiene la ecuación
xlab = "",
ylab = "Registros hipóxicos al día (%)",
type = "nonparametric", # Usa Kruskal-Wallis como test principal
pairwise.comparisons = TRUE, # Comparaciones post-hoc entre grupos
var.equal = FALSE,
pairwise.display = "significant", # Solo muestra pares significativos
p.adjust.method = "bonferroni", # Corrección para múltiples comparaciones
ggtheme = ggplot2::theme_minimal(), # Tema minimalista
violin.args = list(width = 0, linewidth = 0) # Para quitar el violin plot
) +
# Paleta de colores personalizada
ggplot2::scale_color_manual(values = c("#56B4E9", "red", "green", "#D55E00")) +
# Personalización del tema
ggplot2::theme(
plot.title = ggplot2::element_text(size = 0), # Quita el título
plot.subtitle = ggplot2::element_text(size = 0), # Quita el subtítulo
legend.text = ggplot2::element_text(size = 12), # Tamaño del texto de la leyenda
axis.text = ggplot2::element_text(size = 12, color = "black"), # Tamaño y color del texto de los ejes
axis.title = ggplot2::element_text(size = 14), # Tamaño del título de los ejes
axis.ticks.length = ggplot2::unit(5, "pt"), # Longitud de los ticks
axis.ticks = ggplot2::element_line(color = "black"), # Color de los ticks
axis.line = ggplot2::element_line(color = "black", size = 0.5), # Líneas de los ejes
panel.grid.major = ggplot2::element_blank(), # Elimina las líneas de la grilla mayor
panel.grid.minor = ggplot2::element_blank() # Elimina las líneas de la grilla menor
)

Minimo de Sat OD al dia
Minimo de Saturacion de oxígeno al día:
# Función para calcular mínimo de DO_sat por día
calcular_min_od <- function(df) {
df %>%
mutate(Dia = as.Date(Hora_Lima)) %>%
group_by(Dia, Mortalidad) %>%
summarise(minimo = min(DO_sat), .groups = 'drop')
}
# Aplicar calcular_min_od a cada conjunto de datos
min_od <- calcular_min_od(total)
# Normalidad de los datos
min_od %>%
group_by(Mortalidad) %>%
summarise(
mensaje = paste(
"Prueba de Shapiro-Wilk para",
first(Mortalidad), # Obtén el nombre del grupo
": p =", signif(shapiro.test(minimo)$p.value, digits = 3)
)
) %>%
pull(mensaje) %>% # Extrae solo los mensajes
cat(sep = "\n") # Los imprime línea por línea
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Barrancos : p = 2.85e-05
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Constante : p = 0.325
## Prueba de Shapiro-Wilk para Mortalidad 2019 - Constante : p = 0.000499
## Prueba de Shapiro-Wilk para No Mortalidad : p = 3.28e-16
# Homogeneidad de los datos
levene_result<- leveneTest(minimo ~ Mortalidad, data = min_od)
p_value_levene <- signif(levene_result$`Pr(>F)`[1], digits = 3)
cat("Prueba de Levene para homogeneidad de varianzas: p =", p_value_levene, "\n")
## Prueba de Levene para homogeneidad de varianzas: p = 1.51e-07
# Kruskal-Wallis
kruskal_result <- kruskal.test(minimo ~ Mortalidad, data = min_od)
print(kruskal_result)
##
## Kruskal-Wallis rank sum test
##
## data: minimo by Mortalidad
## Kruskal-Wallis chi-squared = 58.723, df = 3, p-value = 1.102e-12
# Post-hoc con Dunn para identificar diferencias entre pares de grupos
dunn_result <- dunnTest(minimo ~ Mortalidad, data = min_od, method = "bonferroni")
# Extraer los resultados en formato de dataframe
tabla_dunn <- as.data.frame(dunn_result$res)
# Renombrar columnas para que sean más legibles
colnames(tabla_dunn) <- c("Comparacion", "Estadistico Z", "P sin ajustar", "P ajustado")
# Crear la tabla con gt
tabla_dunn %>%
gt() %>%
tab_header(
title = "Resultados del Test de Dunn",
subtitle = "Comparaciones de Porcentaje de registros hipoxicos entre grupos de Mortalidad"
) %>%
fmt_number(
columns = c("Estadistico Z", "P sin ajustar", "P ajustado"),
decimals = 3
) %>%
cols_label(
`Comparacion` = "Grupos Comparados",
`Estadistico Z` = "Estadístico Z",
`P sin ajustar` = "P-valor (sin ajustar)",
`P ajustado` = "P-valor (ajustado)"
)
| Resultados del Test de Dunn |
| Comparaciones de Porcentaje de registros hipoxicos entre grupos de Mortalidad |
| Grupos Comparados |
Estadístico Z |
P-valor (sin ajustar) |
P-valor (ajustado) |
| Mortalidad 2015 - Barrancos - Mortalidad 2015 - Constante |
−3.661 |
0.000 |
0.002 |
| Mortalidad 2015 - Barrancos - Mortalidad 2019 - Constante |
1.432 |
0.152 |
0.913 |
| Mortalidad 2015 - Constante - Mortalidad 2019 - Constante |
5.272 |
0.000 |
0.000 |
| Mortalidad 2015 - Barrancos - No Mortalidad |
−4.006 |
0.000 |
0.000 |
| Mortalidad 2015 - Constante - No Mortalidad |
1.091 |
0.275 |
1.000 |
| Mortalidad 2019 - Constante - No Mortalidad |
−6.508 |
0.000 |
0.000 |
ggplot(min_od, aes(x = Mortalidad, y = minimo, fill = Mortalidad)) +
geom_boxplot(alpha = 0.7, outlier.shape = NA) +
geom_jitter(width = 0.2, size = 2, alpha = 0.6, color = "black") +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Minima saturacion de oxígeno al día",
x = "",
y = "Saturacion OD (%)"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

ggplot(min_od, aes(x = Mortalidad, y = minimo, fill = Mortalidad)) +
geom_violin(trim = FALSE, alpha = 0.6, color = "black") +
geom_boxplot(width = 0.1, outlier.shape = NA, alpha = 0.5) +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Minima saturacion de oxígeno al día",
x = "",
y = "Saturacion de OD (%)"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

# Reordenar los niveles de la variable 'Mortalidad'
min_od$Mortalidad <- factor(
min_od$Mortalidad,
levels = c(
"Mortalidad 2015 - Barrancos",
"Mortalidad 2019 - Constante",
"Mortalidad 2015 - Constante",
"No Mortalidad"
),
labels = c(
"Mortalidad 2015\nBarrancos",
"Mortalidad 2019\nConstante",
"Mortalidad 2015\nConstante",
"No Mortalidad"
)
)
# Stats + graph
ggbetweenstats(
data = min_od,
x = Mortalidad,
y = minimo,
title = NULL, # Elimina el título
results.subtitle = F, # Elimina el subtítulo que contiene la ecuación
xlab = "",
ylab = "Minima saturación OD al día (%)",
type = "nonparametric", # Usa Kruskal-Wallis como test principal
pairwise.comparisons = TRUE, # Comparaciones post-hoc entre grupos
var.equal = FALSE,
pairwise.display = "significant", # Solo muestra pares significativos
p.adjust.method = "bonferroni", # Corrección para múltiples comparaciones
ggtheme = ggplot2::theme_minimal(), # Tema minimalista
violin.args = list(width = 0, linewidth = 0) # Para quitar el violin plot
) +
# Paleta de colores personalizada
ggplot2::scale_color_manual(values = c("#56B4E9", "red", "green", "#D55E00")) +
# Personalización del tema
ggplot2::theme(
plot.title = ggplot2::element_text(size = 0), # Quita el título
plot.subtitle = ggplot2::element_text(size = 0), # Quita el subtítulo
legend.text = ggplot2::element_text(size = 12), # Tamaño del texto de la leyenda
axis.text = ggplot2::element_text(size = 12, color = "black"), # Tamaño y color del texto de los ejes
axis.title = ggplot2::element_text(size = 14), # Tamaño del título de los ejes
axis.ticks.length = ggplot2::unit(5, "pt"), # Longitud de los ticks
axis.ticks = ggplot2::element_line(color = "black"), # Color de los ticks
axis.line = ggplot2::element_line(color = "black", size = 0.5), # Líneas de los ejes
panel.grid.major = ggplot2::element_blank(), # Elimina las líneas de la grilla mayor
panel.grid.minor = ggplot2::element_blank() # Elimina las líneas de la grilla menor
)

Mediana de Sat OD al dia
Mediana de Saturacion de oxigeno al dia:
# Función para calcular mediana de DO_sat por día y zona
calcular_median_od <- function(df) {
df %>%
mutate(Dia = as.Date(Hora_Lima)) %>%
group_by(Dia, Mortalidad) %>%
summarise(median= median(DO_sat), .groups = 'drop')
}
# Aplicar calcular_min_od a cada conjunto de datos
med_od <- calcular_median_od(total)
# Normalidad de los datos
med_od %>%
group_by(Mortalidad) %>%
summarise(
mensaje = paste(
"Prueba de Shapiro-Wilk para",
first(Mortalidad), # Obtén el nombre del grupo
": p =", signif(shapiro.test(median)$p.value, digits = 3)
)
) %>%
pull(mensaje) %>% # Extrae solo los mensajes
cat(sep = "\n") # Los imprime línea por línea
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Barrancos : p = 0.00683
## Prueba de Shapiro-Wilk para Mortalidad 2015 - Constante : p = 0.2
## Prueba de Shapiro-Wilk para Mortalidad 2019 - Constante : p = 0.143
## Prueba de Shapiro-Wilk para No Mortalidad : p = 8.92e-11
# Homogeneidad de los datos
levene_result<- leveneTest(median ~ Mortalidad, data = med_od)
p_value_levene <- signif(levene_result$`Pr(>F)`[1], digits = 3)
cat("Prueba de Levene para homogeneidad de varianzas: p =", p_value_levene, "\n")
## Prueba de Levene para homogeneidad de varianzas: p = 4.54e-06
# Kruskal-Wallis
kruskal_result <- kruskal.test(median ~ Mortalidad, data = med_od)
print(kruskal_result)
##
## Kruskal-Wallis rank sum test
##
## data: median by Mortalidad
## Kruskal-Wallis chi-squared = 63.399, df = 3, p-value = 1.104e-13
# Post-hoc con Dunn para identificar diferencias entre pares de grupos
dunn_result <- dunnTest(median ~ Mortalidad, data = med_od, method = "bonferroni")
# Extraer los resultados en formato de dataframe
tabla_dunn <- as.data.frame(dunn_result$res)
# Renombrar columnas para que sean más legibles
colnames(tabla_dunn) <- c("Comparacion", "Estadistico Z", "P sin ajustar", "P ajustado")
# Crear la tabla con gt
tabla_dunn %>%
gt() %>%
tab_header(
title = "Resultados del Test de Dunn",
subtitle = "Comparaciones de Porcentaje de registros hipoxicos entre grupos de Mortalidad"
) %>%
fmt_number(
columns = c("Estadistico Z", "P sin ajustar", "P ajustado"),
decimals = 3
) %>%
cols_label(
`Comparacion` = "Grupos Comparados",
`Estadistico Z` = "Estadístico Z",
`P sin ajustar` = "P-valor (sin ajustar)",
`P ajustado` = "P-valor (ajustado)"
)
| Resultados del Test de Dunn |
| Comparaciones de Porcentaje de registros hipoxicos entre grupos de Mortalidad |
| Grupos Comparados |
Estadístico Z |
P-valor (sin ajustar) |
P-valor (ajustado) |
| Mortalidad 2015 - Barrancos - Mortalidad 2015 - Constante |
−3.946 |
0.000 |
0.000 |
| Mortalidad 2015 - Barrancos - Mortalidad 2019 - Constante |
1.340 |
0.180 |
1.000 |
| Mortalidad 2015 - Constante - Mortalidad 2019 - Constante |
5.478 |
0.000 |
0.000 |
| Mortalidad 2015 - Barrancos - No Mortalidad |
−4.278 |
0.000 |
0.000 |
| Mortalidad 2015 - Constante - No Mortalidad |
1.216 |
0.224 |
1.000 |
| Mortalidad 2019 - Constante - No Mortalidad |
−6.672 |
0.000 |
0.000 |
ggplot(med_od, aes(x = Mortalidad, y = median, fill = Mortalidad)) +
geom_boxplot(alpha = 0.7, outlier.shape = NA) +
geom_jitter(width = 0.2, size = 2, alpha = 0.6, color = "black") +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Mediana de la saturacion de oxígeno al día",
x = "",
y = "Saturacion OD (%)"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

ggplot(med_od, aes(x = Mortalidad, y = median, fill = Mortalidad)) +
geom_violin(trim = FALSE, alpha = 0.6, color = "black") +
geom_boxplot(width = 0.1, outlier.shape = NA, alpha = 0.5) +
scale_fill_manual(values = c("#56B4E9", "#E69F00", "#009E73", "#D55E00")) +
labs(
title = "Mediana de la saturacion de oxígeno al día",
x = "",
y = "Saturacion de OD (%)"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", size = 16),
legend.position = "none"
)

# Crear el gráficO
med_od$Mortalidad <- factor(
med_od$Mortalidad,
levels = c(
"Mortalidad 2015 - Barrancos",
"Mortalidad 2019 - Constante",
"Mortalidad 2015 - Constante",
"No Mortalidad"
),
labels = c(
"Mortalidad 2015\nBarrancos",
"Mortalidad 2019\nConstante",
"Mortalidad 2015\nConstante",
"No Mortalidad"
)
)
# Stats + graph
ggbetweenstats(
data = med_od,
x = Mortalidad,
y = median,
title = NULL, # Elimina el título
results.subtitle = FALSE, # Elimina el subtítulo que contiene la ecuación
xlab = "",
ylab = "Mediana de Saturación OD al día (%)",
type = "nonparametric", # Usa Kruskal-Wallis como test principal
pairwise.comparisons = TRUE, # Comparaciones post-hoc entre grupos
var.equal = FALSE,
pairwise.display = "significant", # Solo muestra pares significativos
p.adjust.method = "bonferroni", # Corrección para múltiples comparaciones
ggtheme = ggplot2::theme_minimal(), # Tema minimalista
violin.args = list(width = 0, linewidth = 0) # Para quitar el violin plot
) +
# Paleta de colores personalizada
ggplot2::scale_color_manual(values = c("#56B4E9", "red", "green", "#D55E00")) +
# Personalización del tema
ggplot2::theme(
plot.title = ggplot2::element_text(size = 0), # Quita el título
legend.text = ggplot2::element_text(size = 12), # Tamaño del texto de la leyenda
axis.text = ggplot2::element_text(size = 12, color = "black"), # Tamaño y color del texto de los ejes
axis.title = ggplot2::element_text(size = 14), # Tamaño del título de los ejes
axis.ticks.length = ggplot2::unit(5, "pt"), # Longitud de los ticks
axis.ticks = ggplot2::element_line(color = "black"), # Color de los ticks
axis.line = ggplot2::element_line(color = "black", size = 0.5), # Líneas de los ejes
panel.grid.major = ggplot2::element_blank(), # Elimina las líneas de la grilla mayor
panel.grid.minor = ggplot2::element_blank() # Elimina las líneas de la grilla menor
)

Desarrollo de una matriz de respuesas biologicas de A.
purpuratus frente a la temperatura e hipoxia




BARRANCOS MORTALIDAD 2015
# Ahora asignamos la categoria de Temp_fond y DO_sat
df_indice <- barrancos_2015
df_indice <- df_indice %>%
mutate(
Categoria_T = case_when(
Temp_fond <= 16 ~ "<=16",
Temp_fond > 16 & Temp_fond <= 20 ~ "]16-20]",
Temp_fond > 20 & Temp_fond <= 25 ~ "]20-25]",
Temp_fond > 25 & Temp_fond <= 29 ~ "]25-29]",
Temp_fond > 29 ~ ">29"
),
Categoria_DO = case_when(
DO_sat <= 2 ~ "<=2",
DO_sat > 2 & DO_sat <= 5 ~ "]2-5]",
DO_sat > 5 & DO_sat <= 24.4 ~ "]5-24]",
DO_sat > 24.4 ~ ">24"
),
Categoria_total = paste(Categoria_T, Categoria_DO, sep = ";")
)
# Identificar los cambios en las categorías de Categoria_total dentro de cada group
df_indice <- df_indice %>%
group_by(group) %>%
mutate(change = Categoria_total != lag(Categoria_total, default = first(Categoria_total))) %>%
mutate(group_id = cumsum(change)) %>%
ungroup ()
# Calcular la fecha de inicio y fin de cada grupo de categorías continuas
df_agrupado <- df_indice %>%
group_by(
group,
group_id) %>%
summarize(
fecha_inicio = min(Hora_Lima),
fecha_fin = max(Hora_Lima),
duracion = as.numeric(difftime(max(Hora_Lima), min(Hora_Lima), units = "hours"))+1,
Categoria_total = first(Categoria_total),
Categoria_DO = first (Categoria_DO))
# Agregar columna Hipoxico con valores Hipoxia o Normoxia
df_agrupado <- df_agrupado %>%
mutate(Hipoxia = ifelse(Categoria_DO %in% c("<=2", "]2-5]","]5-24]"), "Hipoxia", "Normoxia")) #%>%
#ungroup() #%>% # Eliminar agrupaciones activas
#select(-group)
# Crear una copia del dataframe original
df_resultado <- df_agrupado
# Identificar periodos menores a 6 horas
df_resultado <- df_resultado %>%
mutate(is_short = duracion < 6)
# Procesar los bloques
procesar_bloques <- function(df) {
bloque_id <- 1
df <- df %>%
mutate(bloque = 0) # Inicializamos con 0 para los bloques
for (i in 1:nrow(df)) {
if (i == 1) {
# Asignar el primer bloque
df$bloque[i] <- bloque_id
} else if (df$group[i] != df$group[i - 1]) {
# Si cambia el grupo, crear un nuevo bloque
bloque_id <- bloque_id + 1
df$bloque[i] <- bloque_id
} else if (df$is_short[i - 1] && df$is_short[i]) {
# Si el periodo actual y el anterior son cortos, pertenecen al mismo bloque
df$bloque[i] <- bloque_id
} else if (df$is_short[i - 1] && !df$is_short[i]) {
# Si el periodo anterior era corto pero este no, verificamos la duración acumulada
bloque_duracion <- sum(df$duracion[df$bloque == bloque_id])
if (bloque_duracion < 6) {
# Vía B: Ignorar la interrupción y extender el bloque al siguiente
df$bloque[i] <- bloque_id
} else {
# Vía A: Crear un nuevo bloque
bloque_id <- bloque_id + 1
df$bloque[i] <- bloque_id
}
} else {
# Crear un nuevo bloque
bloque_id <- bloque_id + 1
df$bloque[i] <- bloque_id
}
}
return(df)
}
df_resultado <- procesar_bloques(df_resultado)
# Calcular resultados finales por bloque
df_final <- df_resultado %>%
group_by(bloque, group) %>%
summarize(
fecha_inicio = min(fecha_inicio),
fecha_fin = max(fecha_fin),
duracion_total = sum(duracion),
Categoria_total = Categoria_total[which.max(duracion)],
Categoria_DO = Categoria_DO[which.max(duracion)]
) %>%
ungroup()
# Agrupar por bloques consecutivos con el mismo Categoria_total
df_consolidado <- df_final %>%
mutate(
grupo_categoria = cumsum(Categoria_total != lag(Categoria_total, default = first(Categoria_total)))
) %>%
group_by(grupo_categoria,group) %>%
summarize(
fecha_inicio = min(fecha_inicio),
fecha_fin = max(fecha_fin),
duracion = sum(duracion_total),
Categoria_total = first(Categoria_total),
Categoria_DO = first(Categoria_DO) # Consideramos la misma lógica para Categoria_DO
) %>%
ungroup()
# Asignar las categorias
df_consolidado <- df_consolidado %>%
mutate(
Indice = case_when(
duracion < 12 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion < 12 & Categoria_total == "<=16;]5-24]" ~ "Estres fisiologico",
duracion<12 & Categoria_total == "<=16;]2-5]"~ "Estres fisiologico",
duracion<12 & Categoria_total =="<=16;<=2" ~ "Estres fisiologico",
duracion<12 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion<12 & Categoria_total == "]16-20];]5-24]" ~ "Estres fisiologico",
duracion<12 & Categoria_total =="]16-20];]2-5]" ~ "Sin informacion",
duracion<12 & Categoria_total == "]16-20];<=2" ~ "Sin informacion",
duracion<12 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion <12 & Categoria_total == "]20-25];]5-24]"~"Estres fisiologico",
duracion<12 & Categoria_total == "]20-25];]2-5]" ~ "Sin informacion",
duracion<12 & Categoria_total == "]20-25];<=2" ~ "Probabilidad de mortalidad",
duracion<12 & Categoria_total == "25-29];>24" ~ "Sin informacion",
duracion <12 & Categoria_total == "]25-29];]5-24]"~"Sin informacion",
duracion<12 & Categoria_total == "]25-29];]2-5]" ~ "Sin informacion",
duracion<12 & Categoria_total == "]25-29];<=2" ~ "Probabilidad de mortalidad",
duracion<12 & Categoria_total == ">29;>24" ~ "Probabilidad de mortalidad",
duracion <12 & Categoria_total == ">29;5-24]"~ "Letal",
duracion<12 & Categoria_total== ">29;]2-5]" ~ "Letal",
duracion<12 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;]5-24]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;]2-5]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;<=2" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];]5-24]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];]2-5]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];<=2" ~ "Probabilidad de mortalidad",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];]5-24]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];]2-5]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];<=2" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == "]25-29];>24" ~ "Sin informacion",
duracion >= 12 & duracion < 24 &Categoria_total == "]25-29];]5-24]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]25-29];]2-5]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]25-29];<=2" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;>24" ~ "Probabilidad de mortalidad",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;5-24]" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;]2-5]" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;]5-24]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;]2-5]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;<=2" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];]5-24]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];]2-5]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];<=2" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];]5-24]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];]2-5]" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];<=2" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];>24" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];]5-24]" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];]2-5]" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];<=2" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;>24"~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;5-24]"~"Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;]2-5]"~"Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;]5-24]" ~ "Probabilidad de mortalidad",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;]2-5]" ~ "Probabilidad de mortalidad",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;<=2" ~ "Letal",
duracion >= 48 & duracion < 120& Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >= 48 & duracion < 120& Categoria_total == "]16-20];]5-24]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]16-20];]2-5]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]16-20];<=2" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion >= 48 & duracion < 120& Categoria_total == "]20-25];]5-24]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]20-25];]2-5]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]20-25];<=2" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];>24" ~ "Probabilidad de mortalidad",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];]5-24]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];]2-5]" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];<=2" ~ "Letal",
duracion >= 48 & duracion < 120& Categoria_total == ">29;>24" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == ">29;5-24]" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == ">29;]2-5]" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >=120 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >=120 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >=120 & Categoria_total == "]20-25];>24" ~ "Inocuo",
TRUE ~ "Sin informacion"
)
)
# Ordenar el dataframe por fecha de inicio
df_consolidado <- df_consolidado %>% arrange(fecha_inicio)
# Convertir las columnas de fecha a POSIXct si no lo están
df_consolidado$fecha_inicio <- as.POSIXct(df_consolidado$fecha_inicio, tz="UTC")
df_consolidado$fecha_fin <- as.POSIXct(df_consolidado$fecha_fin, tz="UTC")
#Función para calcular el punto medio de un intervalo de fechas
interval_midpoint <- function(start, end) {
return(start + (end - start) / 2)
}
# Agregar la columna Hora_Lima a df_agrupado usando interval_midpoint
df_consolidado <- df_consolidado %>%
mutate(Hora_Lima = interval_midpoint(fecha_inicio, fecha_fin))
# Definir los colores de las categorías
colores_categorias <- c("Letal" = "#800000", # Rojo oscuro
"Probabilidad de mortalidad" = "red",
"Estres fisiologico" = "orange",
"Inocuo" = "green",
"Sin informacion" = "grey")
ggplot() +
# Capa 1: fondo con rectángulos de df_consolidado
geom_rect(
data = df_consolidado,
aes(
xmin = as.POSIXct(fecha_inicio, tz = "UTC"),
xmax = as.POSIXct(fecha_fin, tz = "UTC"),
ymin = -Inf,
ymax = Inf,
fill = Indice
),
alpha = 0.8,
color = NA
) +
scale_fill_manual(values = colores_categorias) +
# Capa 2: líneas de barrancos_2015 con agrupación
geom_line(
data = barrancos_2015,
aes(x = Hora_Lima, y = DO_sat, group = group),
color = "black"
) +
# Capa 3: punto crítico de oxígeno
geom_text(
data = data.frame(
x = as.POSIXct("2015-01-15", tz = "UTC"),
y = 27,
label = "Punto crítico de oxígeno"
),
aes(x = x, y = y, label = label),
color = "red",
size = 3.5
) +
# Capa 4: línea horizontal crítica
geom_hline(yintercept = 24, color = "red") +
# Tema y personalización
theme_minimal() +
scale_x_datetime(breaks = "1 week", date_labels = "%d/%b") +
labs(x = "", y = "Saturación de oxígeno (%)", title = "Mortalidad 2015 - Barrancos") +
theme(
title = element_text(size = 20),
axis.text.x = element_text(size = 10, color = "black"),
axis.text.y = element_text(size = 14, color = "black"),
axis.title.x = element_text(size = 16),
axis.title.y = element_text(size = 16),
legend.text = element_text(size = 12),
legend.title = element_text(size = 14),
legend.position = "bottom",
axis.ticks.length = unit(5, "pt"), # Longitud de los ticks
axis.ticks.x = element_line(color = "black"), # Color de los ticks X
axis.ticks.y = element_line(color = "black"), # Color de los ticks Y
axis.line.x = element_line(color = "black", size = 0.5), # Línea horizontal del eje
axis.line.y = element_line(color = "black", size = 0.5) # Línea vertical del eje
) +
# Anotaciones adicionales
annotate(
"rect",
xmin = as.POSIXct("2015-03-02", tz = "UTC"),
xmax = as.POSIXct("2015-03-15", tz = "UTC"),
ymin = -Inf,
ymax = Inf,
alpha = 0,
color = "#636363",
size = 0.7,
linetype = "dashed"
) +
geom_text(
data = data.frame(
x = as.POSIXct("2015-03-09", tz = "UTC"),
y = 98,
label = "Mortalidad"
),
aes(x = x, y = y, label = label),
color = "#636363",
size = 4
)

CONSTANTE MORTALIDAD 2019
# Ahora asignamos la categoria de Temp_fond y DO_sat
df_indice <- constante_2019
df_indice <- df_indice %>%
mutate(
Categoria_T = case_when(
Temp_fond <= 16 ~ "<=16",
Temp_fond > 16 & Temp_fond <= 20 ~ "]16-20]",
Temp_fond > 20 & Temp_fond <= 25 ~ "]20-25]",
Temp_fond > 25 & Temp_fond <= 29 ~ "]25-29]",
Temp_fond > 29 ~ ">29"
),
Categoria_DO = case_when(
DO_sat <= 2 ~ "<=2",
DO_sat > 2 & DO_sat <= 5 ~ "]2-5]",
DO_sat > 5 & DO_sat <= 24.4 ~ "]5-24]",
DO_sat > 24.4 ~ ">24"
),
Categoria_total = paste(Categoria_T, Categoria_DO, sep = ";")
)
# Identificar los cambios en las categorías de Categoria_total dentro de cada group
df_indice <- df_indice %>%
group_by(group) %>%
mutate(change = Categoria_total != lag(Categoria_total, default = first(Categoria_total))) %>%
mutate(group_id = cumsum(change)) %>%
ungroup ()
# Calcular la fecha de inicio y fin de cada grupo de categorías continuas
df_agrupado <- df_indice %>%
group_by(
group,
group_id) %>%
summarize(
fecha_inicio = min(Hora_Lima),
fecha_fin = max(Hora_Lima),
duracion = as.numeric(difftime(max(Hora_Lima), min(Hora_Lima), units = "hours"))+1,
Categoria_total = first(Categoria_total),
Categoria_DO = first (Categoria_DO))
# Agregar columna Hipoxico con valores Hipoxia o Normoxia
df_agrupado <- df_agrupado %>%
mutate(Hipoxia = ifelse(Categoria_DO %in% c("<=2", "]2-5]","]5-24]"), "Hipoxia", "Normoxia")) #%>%
#ungroup() #%>% # Eliminar agrupaciones activas
#select(-group)
# Crear una copia del dataframe original
df_resultado <- df_agrupado
# Identificar periodos menores a 6 horas
df_resultado <- df_resultado %>%
mutate(is_short = duracion < 6)
# Procesar los bloques
procesar_bloques <- function(df) {
bloque_id <- 1
df <- df %>%
mutate(bloque = 0) # Inicializamos con 0 para los bloques
for (i in 1:nrow(df)) {
if (i == 1) {
# Asignar el primer bloque
df$bloque[i] <- bloque_id
} else if (df$group[i] != df$group[i - 1]) {
# Si cambia el grupo, crear un nuevo bloque
bloque_id <- bloque_id + 1
df$bloque[i] <- bloque_id
} else if (df$is_short[i - 1] && df$is_short[i]) {
# Si el periodo actual y el anterior son cortos, pertenecen al mismo bloque
df$bloque[i] <- bloque_id
} else if (df$is_short[i - 1] && !df$is_short[i]) {
# Si el periodo anterior era corto pero este no, verificamos la duración acumulada
bloque_duracion <- sum(df$duracion[df$bloque == bloque_id])
if (bloque_duracion < 6) {
# Vía B: Ignorar la interrupción y extender el bloque al siguiente
df$bloque[i] <- bloque_id
} else {
# Vía A: Crear un nuevo bloque
bloque_id <- bloque_id + 1
df$bloque[i] <- bloque_id
}
} else {
# Crear un nuevo bloque
bloque_id <- bloque_id + 1
df$bloque[i] <- bloque_id
}
}
return(df)
}
df_resultado <- procesar_bloques(df_resultado)
# Calcular resultados finales por bloque
df_final <- df_resultado %>%
group_by(bloque, group) %>%
summarize(
fecha_inicio = min(fecha_inicio),
fecha_fin = max(fecha_fin),
duracion_total = sum(duracion),
Categoria_total = Categoria_total[which.max(duracion)],
Categoria_DO = Categoria_DO[which.max(duracion)]
) %>%
ungroup()
# Agrupar por bloques consecutivos con el mismo Categoria_total
df_consolidado <- df_final %>%
mutate(
grupo_categoria = cumsum(Categoria_total != lag(Categoria_total, default = first(Categoria_total)))
) %>%
group_by(grupo_categoria,group) %>%
summarize(
fecha_inicio = min(fecha_inicio),
fecha_fin = max(fecha_fin),
duracion = sum(duracion_total),
Categoria_total = first(Categoria_total),
Categoria_DO = first(Categoria_DO) # Consideramos la misma lógica para Categoria_DO
) %>%
ungroup()
# Asignar las categorias
df_consolidado <- df_consolidado %>%
mutate(
Indice = case_when(
duracion < 12 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion < 12 & Categoria_total == "<=16;]5-24]" ~ "Estres fisiologico",
duracion<12 & Categoria_total == "<=16;]2-5]"~ "Estres fisiologico",
duracion<12 & Categoria_total =="<=16;<=2" ~ "Estres fisiologico",
duracion<12 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion<12 & Categoria_total == "]16-20];]5-24]" ~ "Estres fisiologico",
duracion<12 & Categoria_total =="]16-20];]2-5]" ~ "Sin informacion",
duracion<12 & Categoria_total == "]16-20];<=2" ~ "Sin informacion",
duracion<12 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion <12 & Categoria_total == "]20-25];]5-24]"~"Estres fisiologico",
duracion<12 & Categoria_total == "]20-25];]2-5]" ~ "Sin informacion",
duracion<12 & Categoria_total == "]20-25];<=2" ~ "Probabilidad de mortalidad",
duracion<12 & Categoria_total == "25-29];>24" ~ "Sin informacion",
duracion <12 & Categoria_total == "]25-29];]5-24]"~"Sin informacion",
duracion<12 & Categoria_total == "]25-29];]2-5]" ~ "Sin informacion",
duracion<12 & Categoria_total == "]25-29];<=2" ~ "Probabilidad de mortalidad",
duracion<12 & Categoria_total == ">29;>24" ~ "Probabilidad de mortalidad",
duracion <12 & Categoria_total == ">29;5-24]"~ "Letal",
duracion<12 & Categoria_total== ">29;]2-5]" ~ "Letal",
duracion<12 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;]5-24]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;]2-5]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "<=16;<=2" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];]5-24]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];]2-5]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]16-20];<=2" ~ "Probabilidad de mortalidad",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];]5-24]" ~ "Estres fisiologico",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];]2-5]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]20-25];<=2" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == "]25-29];>24" ~ "Sin informacion",
duracion >= 12 & duracion < 24 &Categoria_total == "]25-29];]5-24]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]25-29];]2-5]" ~ "Sin informacion",
duracion >= 12 & duracion < 24 & Categoria_total == "]25-29];<=2" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;>24" ~ "Probabilidad de mortalidad",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;5-24]" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;]2-5]" ~ "Letal",
duracion >= 12 & duracion < 24 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;]5-24]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;]2-5]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "<=16;<=2" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];]5-24]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];]2-5]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "]16-20];<=2" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];]5-24]" ~ "Estres fisiologico",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];]2-5]" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]20-25];<=2" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];>24" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];]5-24]" ~ "Probabilidad de mortalidad",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];]2-5]" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == "]25-29];<=2" ~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;>24"~ "Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;5-24]"~"Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;]2-5]"~"Letal",
duracion >= 24 & duracion < 48 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;]5-24]" ~ "Probabilidad de mortalidad",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;]2-5]" ~ "Probabilidad de mortalidad",
duracion >= 48 & duracion < 120 & Categoria_total == "<=16;<=2" ~ "Letal",
duracion >= 48 & duracion < 120& Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >= 48 & duracion < 120& Categoria_total == "]16-20];]5-24]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]16-20];]2-5]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]16-20];<=2" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "]20-25];>24" ~ "Inocuo",
duracion >= 48 & duracion < 120& Categoria_total == "]20-25];]5-24]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]20-25];]2-5]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]20-25];<=2" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];>24" ~ "Probabilidad de mortalidad",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];]5-24]" ~ "Sin informacion",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];]2-5]" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == "]25-29];<=2" ~ "Letal",
duracion >= 48 & duracion < 120& Categoria_total == ">29;>24" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == ">29;5-24]" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == ">29;]2-5]" ~ "Letal",
duracion >= 48 & duracion < 120 & Categoria_total == ">29;<=2" ~ "Letal",
duracion >=120 & Categoria_total == "<=16;>24" ~ "Inocuo",
duracion >=120 & Categoria_total == "]16-20];>24" ~ "Inocuo",
duracion >=120 & Categoria_total == "]20-25];>24" ~ "Inocuo",
TRUE ~ "Sin informacion"
)
)
# Ordenar el dataframe por fecha de inicio
df_consolidado <- df_consolidado %>% arrange(fecha_inicio)
# Convertir las columnas de fecha a POSIXct si no lo están
df_consolidado$fecha_inicio <- as.POSIXct(df_consolidado$fecha_inicio, tz="UTC")
df_consolidado$fecha_fin <- as.POSIXct(df_consolidado$fecha_fin, tz="UTC")
#Función para calcular el punto medio de un intervalo de fechas
interval_midpoint <- function(start, end) {
return(start + (end - start) / 2)
}
# Agregar la columna Hora_Lima a df_agrupado usando interval_midpoint
df_consolidado <- df_consolidado %>%
mutate(Hora_Lima = interval_midpoint(fecha_inicio, fecha_fin))
# Definir los colores de las categorías
colores_categorias <- c("Letal" = "#800000", # Rojo oscuro
"Probabilidad de mortalidad" = "red",
"Estres fisiologico" = "orange",
"Inocuo" = "green",
"Sin informacion" = "grey")
df_consolidado <- df_consolidado %>%
mutate(fecha_fin = fecha_fin - microseconds(1)) # Restamos 1 segundo para que fecha_fin sea inclusiva
ggplot() +
# Capa 1: fondo con rectángulos de df_consolidado
geom_rect(
data = df_consolidado,
aes(
xmin = as.POSIXct(fecha_inicio, tz = "UTC"),
xmax = as.POSIXct(fecha_fin, tz = "UTC"),
ymin = -Inf,
ymax = Inf,
fill = Indice
),
alpha = 0.8,
color = NA
) +
scale_fill_manual(values = colores_categorias) +
# Capa 2: líneas de constnate_2019 con agrupación
geom_line(
data = constante_2019,
aes(x = Hora_Lima, y = DO_sat, group = group),
color = "black"
) +
# Capa 3: punto crítico de oxígeno
geom_text(
data = data.frame(
x = as.POSIXct("2019-01-15", tz = "UTC"),
y = 27,
label = "Punto crítico de oxígeno"
),
aes(x = x, y = y, label = label),
color = "red",
size = 3.5
) +
# Capa 4: línea horizontal crítica
geom_hline(yintercept = 24, color = "red") +
# Tema y personalización
theme_minimal() +
scale_x_datetime(breaks = "1 week", date_labels = "%d/%b") +
labs(x = "", y = "Saturación de oxígeno (%)", title = "Mortalidad 2019 - Constante") +
theme(
title = element_text(size = 20),
axis.text.x = element_text(size = 10, color = "black"),
axis.text.y = element_text(size = 14, color = "black"),
axis.title.x = element_text(size = 16),
axis.title.y = element_text(size = 16),
legend.text = element_text(size = 12),
legend.title = element_text(size = 14),
legend.position = "bottom",
axis.ticks.length = unit(5, "pt"), # Longitud de los ticks
axis.ticks.x = element_line(color = "black"), # Color de los ticks X
axis.ticks.y = element_line(color = "black"), # Color de los ticks Y
axis.line.x = element_line(color = "black", size = 0.5), # Línea horizontal del eje
axis.line.y = element_line(color = "black", size = 0.5) # Línea vertical del eje
) +
# Anotaciones adicionales
annotate(
"rect",
xmin = as.POSIXct("2019-03-04", tz = "UTC"),
xmax = as.POSIXct("2019-03-13", tz = "UTC"),
ymin = -Inf,
ymax = Inf,
alpha = 0,
color = "#636363",
size = 0.7,
linetype = "dashed"
) +
geom_text(
data = data.frame(
x = as.POSIXct("2019-03-10", tz = "UTC"),
y = 98,
label = "Mortalidad"
),
aes(x = x, y = y, label = label),
color = "#636363",
size = 4
)

Puntos negativos:
Antes del periodo de Mortalidad, no sale “Probabilidad de
mortalidad”, por lo que, en ese caso, el sistema de alerta temprana no
funciona.
Durante la Mortalidad, el periodo de letalidad es muy corto, no
abarca el evento entero.
Podría ser todo letal, pero la toma de datos durante la
mortalidad no fue estrictamente todas las horas, por ende, no cumple con
el criterio de duracion >6h… dificil de clasificar dentro de la
categoria Letal.
LS0tDQp0aXRsZTogIlJlcG9ydGUgVGVzaXMgUHJlZ3JhZG8iDQpzdWJ0aXRsZTogIlJlc3VsdGFkb3MiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KYXV0aG9yOiAiUmViZWNhIENhbXBvcyBDdWVsbGFyIg0KZGF0ZTogIjIwMjUtMDEtMTgiDQotLS0NCiMgSW50cm9kdWNjaW9uDQoNCkVuIGVzdGUgcmVwb3J0ZSBlc3TDoW4gbG9zIGPDs2RpZ29zIGRlIGxvcyByZXN1bHRhZG9zIGRlIGxhIHRlc2lzIGRlIFByZWdyYWRvICoqRWxhYm9yYWNpb24gZGUgdW5hIG1hdHJpeiBkZSByZXNwdWVzdGFzIGJpb2zDs2dpY2FzIGZyZW50ZSBhIGxhIHRlbXBlcmF0dXJhIGUgaGlwb3hpYSBwYXJhIGxhIGV2YWx1YWNpw7NuIGRlIHJpZXNnb3MgZW4gY3VsdGl2byBkZSBmb25kbyBkZSAqQXJnb3BlY3RlbiBwdXJwdXJhdHVzKiwgY29uY2hhIGRlIGFiYW5pY28sIGVuIGxhIEJhaMOtYSBkZSBTZWNodXJhKioNCg0KUGFyYSBsYSBlamVjdWNpw7NuIGRlIGxhIHRlc2lzIHNlIHV0aWxpemFyb24gbG9zIGRhdG9zIGRlbCBhcnTDrWN1bG8gKipbQ3VldG8tVmVnYSBldCBhbC4gMjAyMl0oaHR0cHM6Ly9vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvZnVsbC8xMC4xMTExL2p3YXMuMTI3NzcpKiogeSBsb3MgZGF0b3MgcmVjb3BpbGFkb3MgcG9yICoqQWd1aXJyZS1WZWxhcmRlKiogZHVyYW50ZSBsYSBtb3J0YWxpZGFkIGRlIGNvbmNoYSBkZSBhYmFuaWNvIGRlbCAyMDE5Lg0KPGJyPiAgICAgIA0KPHRhYmxlPg0KUHJvZ3JhbWEgZGUgbW9uaXRvcmVvICAgICAgICBQYXLDoW1ldHJvIGFtYmllbnRhbCAgICAgICAgIFBlcmlvZG8gZGUgcmVnaXN0cm8gDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0gDQpDdWV0by1WZWdhIGV0IGFsLjIwMjIgICAgICAgIFRlbXBlcmF0dXJhIHkgU2F0dXJhY2lvbiBPRCAgMDcvMTEvMjAxMy0wNy8xMC8yMDE1ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqJioqICAyMy8wMy8yMDE3LTA3LzAyLzIwMTggDQpBZ3VpcnJlLVZlbGFyZGUgICAgICAgICAgICAgIFRlbXBlcmF0dXJhIHkgU2F0dXJhY2lvbiBPRCAgMDgvMDEvMjAxOS0yNi8wMy8yMDE5ICAgICAgICAgIA0KDQo8L3RhYmxlPg0KDQojIExpbXBpYW5kbyBsb3MgZGF0b3MgDQpQYXJhIGxpbXBpYXIgbGFzIGJhc2UgZGUgZGF0b3Mgc2Ugc2VndWlyYW4gbG9zIHNpZ3VpZW50ZXMgcGFzb3M6DQoNCiAxLiBVbmlmb3JtaXphciBlbCBmb3JtYXRvIGRlIGxhcyBob3JhczogdGltZXpvbmUgVVRDLCBjb24gZWwgbm9tYnJlIEhvcmFfTGltYQ0KIDIuIEFzaWduYXIgZWwgbWlzbW8gbm9tYnJlIGEgbGEgdmFyaWFibGUgdGVtcGVyYXR1cmEgZGUgZm9uZG86IFRlbXBfZm9uZA0KIDMuIEFzaWduYXIgZWwgbWlzbW8gbm9tYnJlIGEgbGEgdmFyaWFibGUgc2F0dXJhY2lvbiBkZSBveGlnZW5vIGRpc3VlbHRvOiBET19zYXQNCiA0LiBFbiBjYXNvIGhheWEgbWFzIGRlIHVuIGRhdG8gcG9yIGhvcmEsIGJ0ZW5lciB1biB2YWxvciBwcm9tZWRpbw0KIDUuIFZlcmlmaWNhciBzaSBoYXkgZmlsYXMgZHVwbGljYWRhcywgdmFsb3JlcyBOQSwgdmFsb3JlcyBuZWdhdGl2b3MuDQogNi4gQXNpZ25hciB1bmEgY29sdW1uYSBjb24gZWwgbm9tYnJlIGRlIGxhIGJhc2UgZGUgZGF0b3MgZGUgb3JpZ2VuLg0KDQpgYGB7cn0NCiN8IGluY2x1ZGUgPSBGQUxTRQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoc24pDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHBhdGNod29yaykNCmxpYnJhcnkoY2FyKQ0KbGlicmFyeShnZ2Rpc3QpIA0KbGlicmFyeShwdXJycikNCmxpYnJhcnkoRlNBKQ0KbGlicmFyeShndCkNCmxpYnJhcnkoZ2dzdGF0c3Bsb3QpDQpsaWJyYXJ5KG1pbnBhY2subG0pDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShwbG90bHkpDQpgYGANCioqTGltcGllemEgZGUgYmRkOiBDdWV0by1WZWdhIGV0IGFsLiAyMDIyKioNCmBgYHtyIGxpbXBpYW5kbyBDdWV0by1WZWdhLCBlY2hvPVRSVUUscmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpjb25zdGFudGVfbG9nZ2VycyA8LSByZWFkX2NzdigiZGF0b3MvYmQtQVJUVVJPLVBJQ0VTX1NlY2h1cmFfU3RyZXNzb3JzL0NPTlNUQU5URV9sb2dnZXJzX2hpc3Rvcmljby5jc3YiKSAlPiUNCiAgbXV0YXRlKA0KICAgIEhvcmFfTGltYSA9IGFzLlBPU0lYY3QoSG9yYV9MaW1hLCBmb3JtYXQgPSAiJVktJW0tJWQgJUg6JU06JVMiLCB0eiA9ICJVVEMiKSwNCiAgICBUZW1wX2ZvbmQgPSBUZW1wICANCiAgICApICU+JQ0KICBzZWxlY3QoSG9yYV9MaW1hLCBUZW1wX2ZvbmQsIERPX3NhdCkgJT4lDQogIGdyb3VwX2J5KEhvcmFfTGltYSkgJT4lIA0KICBzdW1tYXJpc2UoDQogICAgVGVtcF9mb25kID0gbWVhbihUZW1wX2ZvbmQsIG5hLnJtID0gVFJVRSksDQogICAgRE9fc2F0ID0gbWVhbihET19zYXQsIG5hLnJtID0gVFJVRSkNCiAgICApIA0KDQp2YWxvcmVzX2R1cGxpY2Fkb3MgPC0gY29uc3RhbnRlX2xvZ2dlcnMkSG9yYV9MaW1hW2R1cGxpY2F0ZWQoY29uc3RhbnRlX2xvZ2dlcnMkSG9yYV9MaW1hKV0NCnByaW50KHVuaXF1ZSh2YWxvcmVzX2R1cGxpY2Fkb3MpKSANCg0KY29sU3Vtcyhpcy5uYShjb25zdGFudGVfbG9nZ2VycykpICANCmVsaW1pbmFyIDwtIHdoaWNoKGFwcGx5KGlzLm5hKGNvbnN0YW50ZV9sb2dnZXJzKSwgMSwgYW55KSkgI0hheSAxMTgyMSBmaWxhcyBxdWUgbm8gdGllbmUgZGF0b3MgZGUgRE9fc2F0DQpjb25zdGFudGVfbG9nZ2VycyA8LSBjb25zdGFudGVfbG9nZ2Vyc1stZWxpbWluYXIsIF0gDQpjb2xTdW1zKGlzLm5hbihhcy5tYXRyaXgoY29uc3RhbnRlX2xvZ2dlcnMpKSkgIA0KYW55KGNvbnN0YW50ZV9sb2dnZXJzIDwgMCwgbmEucm0gPSBUUlVFKQ0KY29uc3RhbnRlX2xvZ2dlcnMgPC0gZmlsdGVyKGNvbnN0YW50ZV9sb2dnZXJzLCBET19zYXQgPj0gMCwgRE9fc2F0IDw9MTAwLCAhaXMubmEoRE9fc2F0KSkNCg0KY29uc3RhbnRlX2xvZ2dlcnMgPC0gY29uc3RhbnRlX2xvZ2dlcnMgJT4lDQogIG11dGF0ZSgNCiAgICBiZGQgPSAiQ3VldG8tVmVnYV8yMDIyIiwNCiAgICBab25hID0gIkNvbnN0YW50ZSIpIA0KYGBgDQoqKkxpbXBlemEgZGUgYmRkOiBBZ3VpcnJlLVZlbGFyZGUgMjAxOSoqDQpMb3MgZGF0b3MgcmVjb3BpbGFkb3MgcG9yIEFndWlycmUtVmVsYXJkZSBlbiBlbCAyMDE5IGVzdGFuIGNvbmZvcm1hZG9zIHBvciBkb3MgYXJjaGl2b3MgY3N2Og0KDQoqIENvbnN0YW50ZV9sb2dnZXJzLmNzdiAoMDggZW5lcm8gMjAxOSAtIDA0IG1hcnpvIDIwMTkpDQpgYGB7ciBsaW1waWFuZG8gQ29uc3RhbnRlX2xvZ2dlcnMsIGVjaG89VFJVRSwgcmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIyMgQkREIENvbnN0YW50ZV9sb2dnZXJzICMjIyMNCmNvbnN0YW50ZV9URE8gPC0gcmVhZC5jc3YoImRhdG9zL0luZm9ybWVfU2VjaHVyYU1vcnQyMDE5L0NvbnN0YW50ZV9sb2dnZXJzLmNzdiIsIGhlYWRlciA9IFRSVUUsIGRlYyA9ICIuIiwgc2VwID0gIiwiKSAlPiUNCiAgbXV0YXRlKA0KICAgIEhvcmFfTGltYSA9IGFzLlBPU0lYY3QoSG9yYV9MaW1hLCBmb3JtYXQgPSAiJWQvJW0vJVkgJUg6JU0iLCB0ej0iVVRDIiksDQogICAgVGVtcF9mb25kID0gVGVtcCAgDQogICAgKSAlPiUNCiAgc2VsZWN0KEhvcmFfTGltYSwgVGVtcF9mb25kLCBET19zYXQpICU+JQ0KICBncm91cF9ieShIb3JhX0xpbWEpICU+JSANCiAgc3VtbWFyaXNlKA0KICAgIFRlbXBfZm9uZCA9IG1lYW4oVGVtcF9mb25kLCBuYS5ybSA9IFRSVUUpLA0KICAgIERPX3NhdCA9IG1lYW4oRE9fc2F0LCBuYS5ybSA9IFRSVUUpDQogICAgKQ0KDQp2YWxvcmVzX2R1cGxpY2Fkb3MgPC0gY29uc3RhbnRlX1RETyRIb3JhX0xpbWFbZHVwbGljYXRlZChjb25zdGFudGVfVERPJEhvcmFfTGltYSldDQpwcmludCh1bmlxdWUodmFsb3Jlc19kdXBsaWNhZG9zKSkgDQoNCmNvbFN1bXMoaXMubmEoY29uc3RhbnRlX1RETykpICANCndoaWNoKGFwcGx5KGlzLm5hKGNvbnN0YW50ZV9URE8pLCAxLCBhbnkpKSAjTGEgZmlsYSAxMzIxIG5vIHRpZW5lIGRhdG9zDQpjb25zdGFudGVfVERPIDwtIGNvbnN0YW50ZV9URE9bLTEzMjEsIF0NCg0KY29sU3Vtcyhpcy5uYW4oYXMubWF0cml4KGNvbnN0YW50ZV9URE8pKSkgIA0KDQphbnkoY29uc3RhbnRlX1RETyA8IDAsIG5hLnJtID0gVFJVRSkNCg0KY29uc3RhbnRlX1RETyA8LSBjb25zdGFudGVfVERPICU+JQ0KICBtdXRhdGUoDQogICAgYmRkID0gIkNvbnN0YW50ZV9URE8iLA0KICAgIFpvbmEgPSAiQ29uc3RhbnRlIikgIA0KYGBgIA0KKiBDb25zdGFudGVfbXVsdGkuY3N2ICgwNSBtYXJ6byAtIDI2IGRlIG1hcnpvIDIwMTkpDQoNCkVuIGVzdGEgYmFzZSBkZSBkYXRvcywgZWwgb3jDrWdlbm8gZXN0YSBlbiBtZy9MLCBwb3IgbG8gcXVlIHNlIGRlYmUgY29udmVydGlyIERPX2MgKG1nL2wpIGVuIERPX3NhdCAoJSkuIFBhcmEgZWxsbywgc2Ugc2VndWlyw6FuIGxhcyBlY3VhY2lvbmVzIHByb3B1ZXN0YXMgcG9yIEJlbnNvbiB5IEtyYXVzZSwgMTk4NDsgdXRpbGl6YWRhcyBwb3IgW1lET0NdKGh0dHBzOi8veWRvYy5iaXovZGlzc29sdmVkLW94eWdlbi1tZWFzdXJlbWVudHMvKTogZW1wcmVzYSBob2xhbmRlc2EgZXNwZWNpYWxpemFkYSBlbiBtZWRpY2lvbmVzIHBvciBkYXRhIGxvZ2dlcnMuDQpgYGB7ciBsaW1waWFuZG8gQ29uc3RhbnRlX211bHRpLCBlY2hvPVRSVUUsIHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyMjIEJERCBjb25zdGFudGVfbXVsdGkgIyMjIyMjDQpjb25zdGFudGVfbXVsdGkgPC0gcmVhZC5jc3YoImRhdG9zL0luZm9ybWVfU2VjaHVyYU1vcnQyMDE5L2NvbnN0YW50ZV9tdWx0aS5jc3YiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBkZWMgPSAiLiIsIHNlcCA9ICIsIikgJT4lDQogIG11dGF0ZSgNCiAgICBIb3JhX0xpbWEgPSBhcy5QT1NJWGN0KEhvcmFfTGltYSwgZm9ybWF0ID0gIiVkLyVtLyVZICVIOiVNOiVTIiwgdHo9IlVUQyIpLA0KICAgIEhvcmFfTGltYSA9IG1ha2VfZGF0ZXRpbWUoeWVhcihIb3JhX0xpbWEpLCBtb250aChIb3JhX0xpbWEpLCBkYXkoSG9yYV9MaW1hKSwgaG91cihIb3JhX0xpbWEpKSwNCiAgICBET19jID0gRE9fZm9uZCwgIA0KICAgIFRlbXBfZm9uZCA9IFRfZm9uZCwNCiAgICBUZW1wX2tlbHZpbiA9IFRlbXBfZm9uZCArIDI3My4xNSAgIyBDb252ZXJ0aXIgdGVtcGVyYXR1cmEgYSBLZWx2aW4NCiAgKSAlPiUNCiAgc2VsZWN0KEhvcmFfTGltYSwgVGVtcF9mb25kLCBUZW1wX2tlbHZpbiwgRE9fYykgJT4lDQogIGdyb3VwX2J5KEhvcmFfTGltYSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBUZW1wX2ZvbmQgPSBtZWFuKFRlbXBfZm9uZCwgbmEucm0gPSBUUlVFKSwNCiAgICBET19jID0gbWVhbihET19jLCBuYS5ybSA9IFRSVUUpLA0KICAgIFRlbXBfa2VsdmluPW1lYW4oVGVtcF9rZWx2aW4sIG5hLnJtPVRSVUUpDQogICkNCg0KdmFsb3Jlc19kdXBsaWNhZG9zIDwtIGNvbnN0YW50ZV9tdWx0aSRIb3JhX0xpbWFbZHVwbGljYXRlZChjb25zdGFudGVfbXVsdGkkSG9yYV9MaW1hKV0NCnByaW50KHVuaXF1ZSh2YWxvcmVzX2R1cGxpY2Fkb3MpKQ0KDQpjb2xTdW1zKGlzLm5hKGNvbnN0YW50ZV9tdWx0aSkpDQplbGltaW5hciA8LSB3aGljaChhcHBseShpcy5uYShjb25zdGFudGVfbXVsdGkpLCAxLCBhbnkpKQ0KY29uc3RhbnRlX211bHRpIDwtIGNvbnN0YW50ZV9tdWx0aVstZWxpbWluYXIsXSANCmNvbFN1bXMoaXMubmFuKGFzLm1hdHJpeChjb25zdGFudGVfbXVsdGkpKSkNCg0KYW55KGNvbnN0YW50ZV9URE8gPCAwLCBuYS5ybSA9IFRSVUUpDQoNCiMjIENvbnZlcnRpciBET19jIChtZy9sKSBlbiBET19zYXQgKCUpIHNpZ3VpZW5kbyBlY3VhY2lvbmVzIGRlIEJlbnNvbiBhbmQgS3JhdXNlLCAxOTg0DQojIERlZmluaXIgc2FsaW5pZGFkIGVuIHBwdCAoZy9rZykNClNBTCA8LSAzNQ0KDQojIENhbGN1bGFyIERPX0MgKGNvcnJpZ2llbmRvIHBvciBzYWxpbmlkYWQpDQpjb25zdGFudGVfbXVsdGkgPC0gY29uc3RhbnRlX211bHRpICU+JQ0KICBtdXRhdGUoDQogICAgRE9fQyA9IERPX2MgKiBleHAoLTEgKiBTQUwgKiAoMC4wMTc2NzQgKyAoLTEwLjc1NCArIDIxNDAuNyAvIFRlbXBfa2VsdmluKSAvIFRlbXBfa2VsdmluKSkNCiAgKQ0KDQojIENhbGN1bGFyIERPIHNhdHVyYWRvIGVuIG1nL0wNCmNvbnN0YW50ZV9tdWx0aSA8LSBjb25zdGFudGVfbXVsdGkgJT4lDQogIG11dGF0ZSgNCiAgICBET19zYXRfbWdMID0gZXhwKC0xMzkuMzQ0MTEgKyAoMS41NzU3MDFlNSArICgtNi42NDIzMDhlNyArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEuMjQzOGUxMCAtIDguNjIxOTQ5ZTExIC8gVGVtcF9rZWx2aW4pIC8gVGVtcF9rZWx2aW4pIC8gVGVtcF9rZWx2aW4pIC8gVGVtcF9rZWx2aW4pICoNCiAgICAgIGV4cCgtMSAqIFNBTCAqICgwLjAxNzY3NCArICgtMTAuNzU0ICsgMjE0MC43IC8gVGVtcF9rZWx2aW4pIC8gVGVtcF9rZWx2aW4pKQ0KICApDQoNCiMgQ2FsY3VsYXIgRE8gc2F0dXJhZG8gZW4gJSANCmNvbnN0YW50ZV9tdWx0aSA8LSBjb25zdGFudGVfbXVsdGkgJT4lDQogIG11dGF0ZSgNCiAgICBET19zYXQgPSAoRE9fQyAvIERPX3NhdF9tZ0wpICogMTAwDQogICkgJT4lDQpzZWxlY3QoSG9yYV9MaW1hLCBUZW1wX2ZvbmQsIERPX3NhdCkgDQoNCiNBZ3JlZ2FyIGNvbHVtbmFzIGJkZA0KY29uc3RhbnRlX211bHRpIDwtIGNvbnN0YW50ZV9tdWx0aSAlPiUNCiAgbXV0YXRlKA0KICAgIGJkZCA9ICJDb25zdGFudGVfbXVsdGkiLA0KICAgIFpvbmEgPSAiQ29uc3RhbnRlIikgDQoNCmBgYA0KRmluYWxtZW50ZSwgbGFzIGJhc2VzIGRlIGRhdG9zIHNlIHVuaXLDoW4gZW4gdW5hIHNvbGEsIGxhIGN1YWwgc2Vyw6EgbGxhbWFkYSAqKiJjb25zdGFudGUiLioqDQpFbiBlc3RhIG51ZXZhIGJkZCwgc2UgYWdyZWdhcsOhIGxhIGNvbHVtbmEgIk1vcnRhbGlkYWQiLiAgDQoNCiogTW9ydGFsaWRhZCAyMDE1OiAyMSBmZWJyZXJvIC0gKiowMiBtYXJ6byAtIDE1IG1hcnpvIDIwMTUqKg0KKiBNb3J0YWxpZGFkIDIwMTk6IDE5IGZlYnJlcm8gLSAqKjA0IG1hcnpvIC0gMTMgbWFyem8gMjAxOSoqDQoqIE5vIG1vcnRhbGlkYWQ6IHJlc3RvIGRlIGRhdG9zDQpgYGB7ciwgZWNobz1UUlVFLCByZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmJhcnJhbmNvcyA8LSByZWFkX2NzdigiZGF0b3MvYmQtQVJUVVJPLVBJQ0VTX1NlY2h1cmFfU3RyZXNzb3JzL0JBUlJBTkNPU19sb2dnZXJzX2hpc3Rvcmljby5jc3YiKSAlPiUNCiAgbXV0YXRlKA0KICAgIEhvcmFfTGltYSA9IGFzLlBPU0lYY3QoSG9yYV9MaW1hLCBmb3JtYXQgPSAiJVktJW0tJWQgJUg6JU06JVMiLCB0eiA9ICJVVEMiKSwNCiAgICBUZW1wX2ZvbmQgPSBUZW1wICANCiAgKSAlPiUNCiAgc2VsZWN0KEhvcmFfTGltYSwgVGVtcF9mb25kLCBET19zYXQpICU+JQ0KICBncm91cF9ieShIb3JhX0xpbWEpICU+JSANCiAgc3VtbWFyaXNlKA0KICAgIFRlbXBfZm9uZCA9IG1lYW4oVGVtcF9mb25kLCBuYS5ybSA9IFRSVUUpLA0KICAgIERPX3NhdCA9IG1lYW4oRE9fc2F0LCBuYS5ybSA9IFRSVUUpDQogICkgDQogIHZhbG9yZXNfZHVwbGljYWRvcyA8LSBiYXJyYW5jb3MkSG9yYV9MaW1hW2R1cGxpY2F0ZWQoYmFycmFuY29zJEhvcmFfTGltYSldDQogIGEgPC0gY29sU3Vtcyhpcy5uYShiYXJyYW5jb3MpKSAgDQogIGVsaW1pbmFyIDwtIHdoaWNoKGFwcGx5KGlzLm5hKGJhcnJhbmNvcyksIDEsIGFueSkpIA0KICBiYXJyYW5jb3MgPC0gYmFycmFuY29zWy1lbGltaW5hciwgXSANCiAgYSA8LSBjb2xTdW1zKGlzLm5hbihhcy5tYXRyaXgoYmFycmFuY29zKSkpICANCiAgYSA8LSBhbnkoYmFycmFuY29zIDwgMCwgbmEucm0gPSBUUlVFKQ0KICBiYXJyYW5jb3MgPC0gZmlsdGVyKGJhcnJhbmNvcywgRE9fc2F0ID49IDAsIERPX3NhdCA8PTEwMCwgIWlzLm5hKERPX3NhdCkpDQogIGJhcnJhbmNvcyA8LSBiYXJyYW5jb3MgJT4lDQogICAgbXV0YXRlKA0KICAgICAgYmRkID0gIkN1ZXRvLVZlZ2FfMjAyMiIsDQogICAgICBab25hID0gIkJhcnJhbmNvcyIpICANCg0KICBiYXJyYW5jb3NfZmlsdHIgPC0gYmFycmFuY29zICU+JQ0KICBmaWx0ZXIoSG9yYV9MaW1hID49IGFzLlBPU0lYY3QoIjIwMTUtMDItMjEiLCB0ej0iVVRDIikgJiBIb3JhX0xpbWEgPD0gYXMuUE9TSVhjdCgiMjAxNS0wMy0xNSIsIHR6PSJVVEMiKSkNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPVRSVUUscmVzdWx0cz0iaGlkZSIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpjb25zdGFudGUgPC0gIGJpbmRfcm93cyhjb25zdGFudGVfbG9nZ2VycywgY29uc3RhbnRlX1RETywgY29uc3RhbnRlX211bHRpKSANCg0KdG90YWwgPC0gIGJpbmRfcm93cyhjb25zdGFudGUsIGJhcnJhbmNvc19maWx0cikgDQoNCnRvdGFsIDwtIHRvdGFsICU+JQ0KICBtdXRhdGUoDQogICAgWWVhciA9IGZvcm1hdChIb3JhX0xpbWEsICIlWSIpLCAgIyBFeHRyYWVyIGVsIGHDsW8NCiAgICBNb3J0YWxpZGFkID0gY2FzZV93aGVuKA0KICAgICAgKFpvbmEgPT0gIkJhcnJhbmNvcyIgJiBIb3JhX0xpbWEgPj0gYXMuUE9TSVhjdCgiMjAxNS0wMi0yMSIsIHR6ID0gIlVUQyIpICYgSG9yYV9MaW1hIDwgYXMuUE9TSVhjdCgiMjAxNS0wMy0xNSIsIHR6ID0gIlVUQyIpKSB+ICJNb3J0YWxpZGFkIDIwMTUgLSBCYXJyYW5jb3MiLA0KICAgICAgKFpvbmEgPT0gIkNvbnN0YW50ZSIgJiBIb3JhX0xpbWEgPj0gYXMuUE9TSVhjdCgiMjAxNS0wMi0yMSIsIHR6ID0gIlVUQyIpICYgSG9yYV9MaW1hIDwgYXMuUE9TSVhjdCgiMjAxNS0wMy0xNSIsIHR6ID0gIlVUQyIpKSB+ICJNb3J0YWxpZGFkIDIwMTUgLSBDb25zdGFudGUiLA0KICAgICAgKFpvbmEgPT0gIkNvbnN0YW50ZSIgJiBIb3JhX0xpbWEgPj0gYXMuUE9TSVhjdCgiMjAxOS0wMi0xOSIsIHR6ID0gIlVUQyIpICYgSG9yYV9MaW1hIDwgYXMuUE9TSVhjdCgiMjAxOS0wMy0xMyIsIHR6ID0gIlVUQyIpKSB+ICJNb3J0YWxpZGFkIDIwMTkgLSBDb25zdGFudGUiLA0KICAgICAgVFJVRSB+ICJObyBNb3J0YWxpZGFkIg0KICAgICkNCiAgKQ0KDQojIENvbnRhciBvYnNlcnZhY2lvbmVzIHBvciBjYXRlZ29yw61hIGRlIE1vcnRhbGlkYWQgeSBab25hDQpjb250ZW9fb2JzIDwtIHRvdGFsICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKENvbnRlbyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikNCg0KIyBWZXIgbG9zIHJlc3VsdGFkb3MNCnByaW50KGNvbnRlb19vYnMpDQpgYGANCg0KIyBWaXN1YWxpemFjaW9uIGRlIGRhdG9zOiANCg0KIyMgTW9ydGFsaWRhZCAyMDE1IHkgMjAxOSANCg0KRGUgb3jDrWdlbm8gZGlzdWVsdG8geSB0ZW1wZXJhdHVyYSwgZW4gZm9uZG8sIGR1cmFudGUgbGEgbW9ydGFsaWRhZCAyMDE1IHkgMjAxOQ0KDQoqKkRpZmVyZW5jaWFzIGR1cmFudGUgbGEgTW9ydGFsaWRhZCAyMDE1OiBCYXJyYW5jb3MgdnMgQ29uc3RhbnRlPz8qKg0KDQpgYGB7ciwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTgsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgRnVuY2nDs24gcGFyYSBhZ3JlZ2FyIGdydXBvcyBzZWfDum4gaHVlY29zIG1heW9yZXMgYSAyNCBob3Jhcw0KYWdyZWdhcl9ncnVwb3MgPC0gZnVuY3Rpb24oZGF0YSkgew0KICBkYXRhIDwtIGRhdGEgJT4lDQogICAgYXJyYW5nZShIb3JhX0xpbWEpICU+JSAgIyBBc2Vnw7pyYXRlIGRlIHF1ZSBlc3TDqSBvcmRlbmFkbyBwb3IgdGllbXBvDQogICAgbXV0YXRlKA0KICAgICAgdGltZV9kaWZmID0gYXMubnVtZXJpYyhkaWZmdGltZShIb3JhX0xpbWEsIGxhZyhIb3JhX0xpbWEpLCB1bml0cyA9ICJob3VycyIpKSwNCiAgICAgIGdyb3VwID0gY3Vtc3VtKGlmZWxzZShpcy5uYSh0aW1lX2RpZmYpIHwgdGltZV9kaWZmID4gMjQsIDEsIDApKQ0KICAgICkNCiAgcmV0dXJuKGRhdGEpDQp9DQoNCiNQZXJpb2RvcyBhIGdyYWZpY2FyIA0KYmFycmFuY29zXzIwMTUgPC0gYmFycmFuY29zICU+JQ0KICBmaWx0ZXIoSG9yYV9MaW1hID49IGFzLlBPU0lYY3QoIjIwMTUtMDEtMDgiLCB0ej0iVVRDIikgJiBIb3JhX0xpbWEgPD0gYXMuUE9TSVhjdCgiMjAxNS0wMy0xOCIsIHR6PSJVVEMiKSkNCg0KY29uc3RhbnRlXzIwMTUgPC0gY29uc3RhbnRlICU+JQ0KICBmaWx0ZXIoSG9yYV9MaW1hID49IGFzLlBPU0lYY3QoIjIwMTUtMDEtMDgiLCB0ej0iVVRDIikgJiBIb3JhX0xpbWEgPD0gYXMuUE9TSVhjdCgiMjAxNS0wMy0xOCIsIHR6PSJVVEMiKSkNCg0KY29uc3RhbnRlXzIwMTkgPC0gY29uc3RhbnRlICU+JQ0KICBmaWx0ZXIoSG9yYV9MaW1hID49IGFzLlBPU0lYY3QoIjIwMTktMDEtMDgiLCB0ej0iVVRDIikgJiBIb3JhX0xpbWEgPD0gYXMuUE9TSVhjdCgiMjAxOS0wMy0xOCIsIHR6PSJVVEMiKSkNCg0KIyBBcGxpY2FyIGxhIGZ1bmNpw7NuIGEgbG9zIGRhdGFzZXRzDQpiYXJyYW5jb3NfMjAxNSA8LSBhZ3JlZ2FyX2dydXBvcyhiYXJyYW5jb3NfMjAxNSkNCmNvbnN0YW50ZV8yMDE1IDwtICBhZ3JlZ2FyX2dydXBvcyhjb25zdGFudGVfMjAxNSkNCmNvbnN0YW50ZV8yMDE5IDwtIGFncmVnYXJfZ3J1cG9zKGNvbnN0YW50ZV8yMDE5KQ0KDQojIEFjdHVhbGl6YXIgbG9zIGdyw6FmaWNvcyBwYXJhIHVzYXIgJ2dyb3VwJw0KZ3JhZmljb19iYXJyYW5jb3NfMjAxNSA8LSBnZ3Bsb3QoYmFycmFuY29zXzIwMTUsIGFlcyh4ID0gSG9yYV9MaW1hLCB5ID0gRE9fc2F0LCBncm91cCA9IGdyb3VwKSkgKw0KICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBhcy5QT1NJWGN0KCIyMDE1LTAzLTAyIiwgdHogPSAiVVRDIiksDQogICAgICAgICAgICAgICAgeG1heCA9IGFzLlBPU0lYY3QoIjIwMTUtMDMtMTQiLCB0eiA9ICJVVEMiKSwNCiAgICAgICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IEluZiksDQogICAgICAgICAgICBmaWxsID0gInBpbmsiLCBhbHBoYSA9IDAuMDMpICsgIA0KICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC41KSArICANCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMjQuNCwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAic29saWQiLCBzaXplID0gMC41KSArICANCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gYXMuUE9TSVhjdCgiMjAxNS0wMS0xNyIsIHR6ID0gIlVUQyIpLCB5ID0gMjYuNSwNCiAgICAgICAgICAgbGFiZWwgPSAiUHVudG8gY3LDrXRpY28gZGUgb3jDrWdlbm8iLCBjb2xvciA9ICJyZWQiLCBzaXplID0gNCkgKw0KICBzY2FsZV94X2RhdGV0aW1lKGRhdGVfYnJlYWtzID0gIjEgd2VlayIsIGRhdGVfbGFiZWxzID0gIiVkLyViIikgKyAgDQogIGxhYnMoIHg9IiIsDQogICAgeSA9ICJTYXR1cmFjacOzbiBkZSBveMOtZ2VubyAoJSkiLA0KICAgIHRpdGxlID0gIk1vcnRhbGlkYWQgMjAxNSAtIEJhcnJhbmNvcyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgDQoNCmdyYWZpY29fY29uc3RhbnRlXzIwMTUgPC0gZ2dwbG90KGNvbnN0YW50ZV8yMDE1LCBhZXMoeCA9IEhvcmFfTGltYSwgeSA9IERPX3NhdCwgZ3JvdXAgPSBncm91cCkpICsNCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gYXMuUE9TSVhjdCgiMjAxNS0wMy0wMiIsIHR6ID0gIlVUQyIpLA0KICAgICAgICAgICAgICAgIHhtYXggPSBhcy5QT1NJWGN0KCIyMDE1LTAzLTE0IiwgdHogPSAiVVRDIiksDQogICAgICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYpLA0KICAgICAgICAgICAgZmlsbCA9ICJwaW5rIiwgYWxwaGEgPSAwLjAzKSArICANCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKyAgDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDI0LjQsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gInNvbGlkIiwgc2l6ZSA9IDAuNSkgKyAgDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLlBPU0lYY3QoIjIwMTUtMDEtMTgiLCB0eiA9ICJVVEMiKSwgeSA9IDI2LjUsDQogICAgICAgICAgIGxhYmVsID0gIlB1bnRvIGNyw610aWNvIGRlIG94w61nZW5vIiwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDQpICsNCiAgc2NhbGVfeF9kYXRldGltZShkYXRlX2JyZWFrcyA9ICIxIHdlZWsiLCBkYXRlX2xhYmVscyA9ICIlZC8lYiIpICsgIA0KICBsYWJzKCB4PSAiIiwNCiAgICB5ID0gIlNhdHVyYWNpw7NuIGRlIG94w61nZW5vICglKSIsIHRpdGxlID0gIk1vcnRhbGlkYWQgMjAxNSAtIENvbnN0YW50ZSIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgDQoNCmdyYWZpY29fY29uc3RhbnRlXzIwMTkgPC0gZ2dwbG90KGNvbnN0YW50ZV8yMDE5LCBhZXMoeCA9IEhvcmFfTGltYSwgeSA9IERPX3NhdCwgZ3JvdXAgPSBncm91cCkpICsNCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gYXMuUE9TSVhjdCgiMjAxOS0wMy0wNCIsIHR6ID0gIlVUQyIpLA0KICAgICAgICAgICAgICAgIHhtYXggPSBhcy5QT1NJWGN0KCIyMDE5LTAzLTEzIiwgdHogPSAiVVRDIiksDQogICAgICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYpLA0KICAgICAgICAgICAgZmlsbCA9ICJwaW5rIiwgYWxwaGEgPSAwLjAzKSArICANCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKyAgDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDI0LCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJzb2xpZCIsIHNpemUgPSAwLjUpICsgIA0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSBhcy5QT1NJWGN0KCIyMDE5LTAxLTE2IiwgdHogPSAiVVRDIiksIHkgPSAyNi41LA0KICAgICAgICAgICBsYWJlbCA9ICJQdW50byBjcsOtdGljbyBkZSBveMOtZ2VubyIsIGNvbG9yID0gInJlZCIsIHNpemUgPSA0KSArDQogIHNjYWxlX3hfZGF0ZXRpbWUoZGF0ZV9icmVha3MgPSAiMSB3ZWVrIiwgZGF0ZV9sYWJlbHMgPSAiJWQvJWIiKSArIA0KICBsYWJzKHkgPSAiU2F0dXJhY2nDs24gZGUgb3jDrWdlbm8gKCUpIiwgdGl0bGUgPSAiTW9ydGFsaWRhZCAyMDE5IiwgeCA9ICJUaWVtcG8gKGTDrWEvbWVzKSIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgDQoNCiMgQ29tYmluYXIgbG9zIGdyw6FmaWNvcw0KZ3JpZC5hcnJhbmdlKA0KICBncmFmaWNvX2JhcnJhbmNvc18yMDE1LCANCiAgZ3JhZmljb19jb25zdGFudGVfMjAxNSwgDQogIGdyYWZpY29fY29uc3RhbnRlXzIwMTksIA0KICBuY29sID0gMSkNCmBgYA0KDQojIEFuw6FsaXNpcyBlc3RhZMOtc3RpY29zDQoNCnZlciBjdWFudG9zIGRhdG9zIHBvciBncnVwbyA6IGN1YW50b3MgcmVnaXN0cm9zIHBvciBob3JhIHBhcmEgY2FkYSB0aXBvIGRlIG1vcnRhbGlkYWQgKGhpc3RvZ3JhbWEpIA0KdmVyIG5vcm1hbGlkYWQgZGUgbG9zIGRhdG9zIHBvciBncnVwbw0KDQpEZWJlcmlhIGhhY2VyIGJvb3RzdHJhcHBpbmc/DQoNCg0KUGFyYSByZWFsaXphciBlbCBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvLCBzZSBsbGV2YXLDoSBhIGNhYm8gdW4gYW7DoWxpc2lzIHByZWxpbWluYXIgcGFyYSBkZXRlcm1pbmFyIHNpIGxvcyBkYXRvcyBjdW1wbGVuIGNvbiBsb3MgcmVxdWlzaXRvcyBwYXJhIHJlYWxpemFyIGFuw6FsaXNpcyBwYXJhbcOpdHJpY29zIG8gbm8gcGFyYW3DqXRyaWNvcy4gRXN0ZSBhbsOhbGlzaXMgcHJlbGltaW5hciBpbmNsdWlyw6EgbGFzIHBydWViYXMgZGUgbm9ybWFsaWRhZCAoU2hhcGlyby1XaWxrKSB5IGhvbW9nZW5laWRhZCBkZSB2YXJpYW56YXMgKExldmVuZSkuIERlcGVuZGllbmRvIGRlIGxvcyByZXN1bHRhZG9zIGRlIGVzdGUgYW7DoWxpc2lzIHByZWxpbWluYXIsIHNlIGVtcGxlYXLDoW4gbGFzIHBydWViYXMgZXN0YWTDrXN0aWNhcyBhZGVjdWFkYXMgcGFyYSBkZXRlcm1pbmFyIHNpIGV4aXN0ZW4gZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXMgKHAtdmFsb3IgPCAwLjA1KSAqKmR1cmFudGUgZWwgdGllbXBvIGRlIG11ZXN0cmVvKiouIFNpIGxvcyBkYXRvcyBjdW1wbGVuIGNvbiBsb3Mgc3VwdWVzdG9zIGRlIG5vcm1hbGlkYWQgeSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzLCBzZSB1dGlsaXphcsOhIGVsIGFuw6FsaXNpcyBkZSB2YXJpYW56YSAoQU5PVkEpLiBFbiBjYXNvIGNvbnRyYXJpbywgc2UgZW1wbGVhcsOhbiBwcnVlYmFzIG5vIHBhcmFtw6l0cmljYXMgY29tbyBsYSBwcnVlYmEgZGUgS3J1c2thbC1XYWxsaXMuIExvcyBhbsOhbGlzaXMgeSBncsOhZmljb3Mgc2Vyw6FuIHJlYWxpemFkb3MgZW4gUiBTdHVkaW8gKHZlcnNpw7NuIDQuIDMuIDA7IFIgQ29yZSBUZWFtLCAyMDIzKS4NCg0KIyMgTm9ybWFsaWRhZCAtIFBydWViYSBkZSBTaGFwaXJvLVdpbGsgey50YWJzZXR9DQoNCiMjIyBSZXN1bHRhZG9zDQoNCmBgYHtyLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgQ2F0ZWdvcsOtYXMgw7puaWNhcyBkZSBtb3J0YWxpZGFkDQpjYXRlZ29yaWFzIDwtIGMoIk1vcnRhbGlkYWQgMjAxNSAtIEJhcnJhbmNvcyIsIk1vcnRhbGlkYWQgMjAxNSAtIENvbnN0YW50ZSIsIk1vcnRhbGlkYWQgMjAxOSAtIENvbnN0YW50ZSIpDQoNCiMgRnVuY2nDs24gcGFyYSBldmFsdWFyIGNhZGEgY2F0ZWdvcsOtYQ0Kc2hhcGlybyA8LSBmdW5jdGlvbihjYXRlZ29yaWEsIGRhdGEpIHsNCiAgIyBGaWx0cmFyIGVsIGdydXBvDQogIGRhdG9zIDwtIGRhdGEgJT4lIGZpbHRlcihNb3J0YWxpZGFkID09IGNhdGVnb3JpYSkNCiAgDQogICMgTm9ybWFsaWRhZDogU2hhcGlyby1XaWxrDQogIHNoYXBpcm9fcmVzdWx0IDwtIHNoYXBpcm8udGVzdChkYXRvcyRET19zYXQpDQogIHByaW50KHBhc3RlKCJQcnVlYmEgZGUgU2hhcGlyby1XaWxrIHBhcmEiLCBjYXRlZ29yaWEsICI6Iiwgc2hhcGlyb19yZXN1bHQkcC52YWx1ZSkpDQogIA0KfQ0KDQojIEFwbGljYXIgbGEgZnVuY2nDs24gYSBjYWRhIGNhdGVnb3LDrWENCndhbGsoY2F0ZWdvcmlhcywgfiBzaGFwaXJvKC54LCB0b3RhbCkpDQoNCmRhdG9zX25vbW9ydGFsaWRhZDwtIHRvdGFsICU+JQ0KICBmaWx0ZXIoTW9ydGFsaWRhZCA9PSAiTm8gTW9ydGFsaWRhZCIpDQprb2xtb2dvcm92X3Jlc3VsdCA8LSBrcy50ZXN0KHg9ZGF0b3Nfbm9tb3J0YWxpZGFkJERPX3NhdCx5PSdwbm9ybScsYWx0ZXJuYXRpdmU9J3R3by5zaWRlZCcpDQogIHByaW50KHBhc3RlKCJQcnVlYmEgZGUgS29sbW9nb3Jvdi1TbWlybm92IHBhcmEgZWwgcGVyaW9kbyBkZSBObyBNb3J0YWxpZGFkOiIsDQogICAgICAgICAgICBmb3JtYXQoa29sbW9nb3Jvdl9yZXN1bHQkcC52YWx1ZSwgc2NpZW50aWZpYyA9IFRSVUUpKSkNCmBgYA0KDQojIyMgUGxvdHMNCg0KYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgQ2F0ZWdvcsOtYXMgw7puaWNhcyBkZSBtb3J0YWxpZGFkDQpjYXRlZ29yaWFzIDwtIGMoIk1vcnRhbGlkYWQgMjAxNSAtIEJhcnJhbmNvcyIsIk1vcnRhbGlkYWQgMjAxNSAtIENvbnN0YW50ZSIsIk1vcnRhbGlkYWQgMjAxOSAtIENvbnN0YW50ZSIsICJObyBNb3J0YWxpZGFkIikNCiMgRnVuY2nDs24gcGFyYSBwcm9jZXNhciBjYWRhIGNhdGVnb3LDrWENCnBsb3RzIDwtIGZ1bmN0aW9uKGNhdGVnb3JpYSwgZGF0YSkgew0KICAjIEZpbHRyYXIgZWwgZ3J1cG8NCiAgZGF0b3MgPC0gZGF0YSAlPiUgZmlsdGVyKE1vcnRhbGlkYWQgPT0gY2F0ZWdvcmlhKQ0KICANCiAgIyBDdXJ2YSBkZSBkZW5zaWRhZA0KICBkZW5zaWRhZCA8LSBnZ3Bsb3QoZGF0b3MsIGFlcyh4ID0gRE9fc2F0KSkgKw0KICAgIGdlb21fZGVuc2l0eShmaWxsID0gIiM1NkI0RTkiLCBhbHBoYSA9IDAuNSwgY29sb3IgPSAiIzAwNzJCMiIsIHNpemUgPSAxLjIpICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSBwYXN0ZSgiQ3VydmEgZGUgZGVuc2lkYWQgLSIsIGNhdGVnb3JpYSksDQogICAgICB4ID0gIlNhdHVyYWNpw7NuIGRlIE94w61nZW5vIChET19zYXQpIiwNCiAgICAgIHkgPSAiRGVuc2lkYWQiDQogICAgKSArDQogICAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLA0KICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpDQogICAgKQ0KDQogICMgQm94cGxvdCBob3Jpem9udGFsDQogIGJveHBsb3QgPC0gZ2dwbG90KGRhdG9zLCBhZXMoeCA9IERPX3NhdCwgeSA9ICIiKSkgKw0KICAgIGdlb21fYm94cGxvdChmaWxsID0gIiNFNjlGMDAiLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC43LCB3aWR0aCA9IDAuMykgKw0KICAgIGxhYnMoeCA9ICJTYXR1cmFjacOzbiBkZSBPeMOtZ2VubyAoRE9fc2F0KSIsIHkgPSAiIikgKw0KICAgIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsNCiAgICB0aGVtZSgNCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQ0KICAgICkNCg0KICAjIENvbWJpbmFyIGVsIGdyw6FmaWNvIGRlIGRlbnNpZGFkIHkgZWwgYm94cGxvdA0KICBjb21iaW5hZG8gPC0gZGVuc2lkYWQgLyBib3hwbG90ICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMywgMSkpDQogIHByaW50KGNvbWJpbmFkbykNCn0NCg0KIyBBcGxpY2FyIGxhIGZ1bmNpw7NuIGEgY2FkYSBjYXRlZ29yw61hDQp3YWxrKGNhdGVnb3JpYXMsIH4gcGxvdHMoLngsIHRvdGFsKSkNCmBgYA0KDQojIyBIb21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzIC0gUHJ1ZWJhIGRlIExldmVuZSB7LnRhYnNldH0NCg0KIyMjIFJlc3VsdGFkb3MNCg0KYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgSG9tb2dlbmVpZGFkIGRlIHZhcmlhbnphczogUHJ1ZWJhIGRlIExldmVuZQ0KbGV2ZW5lX3Jlc3VsdCA8LSBsZXZlbmVUZXN0KERPX3NhdCB+IE1vcnRhbGlkYWQsIGRhdGEgPSB0b3RhbCkNCiMgRXh0cmFlciBlbCB2YWxvciBwIGRlbCByZXN1bHRhZG8NCnBfdmFsdWVfbGV2ZW5lIDwtIHNpZ25pZihsZXZlbmVfcmVzdWx0JGBQcig+RilgWzFdLCBkaWdpdHMgPSAzKQ0KIyBDcmVhciB1biBtZW5zYWplIHBlcnNvbmFsaXphZG8NCmNhdCgiUHJ1ZWJhIGRlIExldmVuZSBwYXJhIGhvbW9nZW5laWRhZCBkZSB2YXJpYW56YXM6IHAgPSIsIHBfdmFsdWVfbGV2ZW5lLCAiXG4iKQ0KDQpgYGANCg0KIyMjIFBsb3RzDQoNCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy53aWR0aD0xMCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmdncGxvdCh0b3RhbCwgYWVzKHggPSBNb3J0YWxpZGFkLCB5ID0gRE9fc2F0LCBmaWxsID0gTW9ydGFsaWRhZCkpICsNCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC43LCBvdXRsaWVyLnNoYXBlID0gTkEpICsgIyBTaW4gb3V0bGllcnMgcGFyYSBubyBkdXBsaWNhciBwdW50b3MNCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIHNpemUgPSAyLCBhbHBoYSA9IDAuNiwgY29sb3IgPSAiYmxhY2siKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAiI0U2OUYwMCIsICIjMDA5RTczIiwgIiNENTVFMDAiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3BlcnNpb24gZGUgU2F0T0QgcG9yIE1vcnRhbGlkYWQiLA0KICAgIHggPSAiTW9ydGFsaWRhZCIsDQogICAgeSA9ICIiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSINCiAgKQ0KDQpnZ3Bsb3QodG90YWwsIGFlcyh4ID0gRE9fc2F0LCBmaWxsID0gTW9ydGFsaWRhZCkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC42KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAiI0U2OUYwMCIsICIjMDA5RTczIiwgIiNENTVFMDAiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRlbnNpZGFkIGRlIERPX3NhdCBwb3IgTW9ydGFsaWRhZCIsDQogICAgeCA9ICIoRE9fc2F0KSIsDQogICAgeSA9ICJEZW5zaWRhZCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQ0KICApDQoNCmBgYA0KDQoNCiMjIFBydWViYXMgTm8gUGFyYW1ldHJpY2FzDQoNClNpIGxvcyBkYXRvcyBubyBzb24gbm9ybWFsZXMgbyBubyBjdW1wbGVuIGxhIGhvbW9nZW5laWRhZDogVXNhciBsYSBwcnVlYmEgZGUgS3J1c2thbC1XYWxsaXMgc2VndWlkYSBkZSB1biBhbsOhbGlzaXMgcG9zdC1ob2MgKER1bm4gbyBXaWxjb3hvbikgcGFyYSBjb21wYXJhY2lvbmVzIG3Dumx0aXBsZXMuDQpjb21wYXJhY2lvbiBjb24gdW5lcXVhbCB2YXJpYW5jZXM/Pw0KDQpgYGB7ciwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyAjIEtydXNrYWwtV2FsbGlzDQprcnVza2FsX3Jlc3VsdCA8LSBrcnVza2FsLnRlc3QoRE9fc2F0IH4gTW9ydGFsaWRhZCwgZGF0YSA9IHRvdGFsKQ0Ka3J1c2thbF9yZXN1bHQNCg0KIyBQb3N0LWhvYyBjb24gRHVubg0KZHVubl9yZXN1bHQgPC0gZHVublRlc3QoRE9fc2F0IH4gTW9ydGFsaWRhZCwgZGF0YSA9IHRvdGFsLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQoNCiMgRXh0cmFlciBsb3MgcmVzdWx0YWRvcyBlbiBmb3JtYXRvIGRlIGRhdGFmcmFtZQ0KdGFibGFfZHVubiA8LSBhcy5kYXRhLmZyYW1lKGR1bm5fcmVzdWx0JHJlcykNCg0KIyBSZW5vbWJyYXIgY29sdW1uYXMgcGFyYSBxdWUgc2VhbiBtw6FzIGxlZ2libGVzDQpjb2xuYW1lcyh0YWJsYV9kdW5uKSA8LSBjKCJDb21wYXJhY2lvbiIsICJFc3RhZGlzdGljbyBaIiwgIlAgc2luIGFqdXN0YXIiLCAiUCBhanVzdGFkbyIpDQoNCiMgQ3JlYXIgbGEgdGFibGEgY29uIGd0DQp0YWJsYV9kdW5uICU+JQ0KICBndCgpICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gIlJlc3VsdGFkb3MgZGVsIFRlc3QgZGUgRHVubiIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpb25lcyBkZSBTYXRfT0QgZW50cmUgZ3J1cG9zIGRlIE1vcnRhbGlkYWQiDQogICkgJT4lDQogIGZtdF9udW1iZXIoDQogICAgY29sdW1ucyA9IGMoIkVzdGFkaXN0aWNvIFoiLCAiUCBzaW4gYWp1c3RhciIsICJQIGFqdXN0YWRvIiksDQogICAgZGVjaW1hbHMgPSAzDQogICkgJT4lDQogIGNvbHNfbGFiZWwoDQogICAgYENvbXBhcmFjaW9uYCA9ICJHcnVwb3MgQ29tcGFyYWRvcyIsDQogICAgYEVzdGFkaXN0aWNvIFpgID0gIkVzdGFkw61zdGljbyBaIiwNCiAgICBgUCBzaW4gYWp1c3RhcmAgPSAiUC12YWxvciAoc2luIGFqdXN0YXIpIiwNCiAgICBgUCBhanVzdGFkb2AgPSAiUC12YWxvciAoYWp1c3RhZG8pIg0KICApDQoNCmBgYA0KDQojIyBCb290c3RyYXBwaW5nPw0KDQojIFZhcmFpYmlsaWRhZCBEaWFyaWEgZGUgbGEgU2F0dXJhY2nDs24gT0QgDQoNClBhcmEgZWwgYW7DoWxpc2lzIGRlIGRhdG9zLCBwcmltZXJvIHNlIHJlYWxpemFyw6EgbGEgY2FyYWN0ZXJpemFjacOzbiBhbWJpZW50YWwgZGUgbG9zIHJlZ2lzdHJvcyBoaXDDs3hpY29zIGVuIENvbnN0YW50ZS4gUGFyYSBlbGxvIHNlIGFuYWxpemFyw6EgbGEgdmFyaWFiaWxpZGFkIGRpYXJpYSBkZSBsYSBzYXR1cmFjacOzbiBkZSBPRCBlbiBlbCBmb25kbywgbG9zIHJlZ2lzdHJvcyBzZSBjbGFzaWZpY2Fyw6FuIGVudHJlIGTDrWEgKDA2OjAwIOKAkyAxNzo1OSkgeSBub2NoZSAoMTg6MDAg4oCTIDA1OjU5KSwgeSBzZSByZXByZXNlbnRhcsOhbiBtZWRpYW50ZSBkaWFncmFtYSBkZSBjYWphcy4gKipQYXJhIGV2YWx1YXIgbGEgdmFyaWFiaWxpZGFkIGRlbCBjaWNsbyBkaWFyaW8gc2UgYWp1c3RhcsOhIHVuYSBmdW5jacOzbiBzaW51c29pZGFsIGEgbGFzIG1lZGlhbmFzIGRlbCBhbsOhbGlzaXMgZGVsIGRpYWdyYW1hIGRlIGNhamEsIGNvbiBlbCBmaW4gZGUgZGV0ZXJtaW5hciB5IGNvbXBhcmFyIGxhIGFtcGxpdHVkIHkgbGEgZmFzZSBkZWwgY2ljbG8gZGlhcmlvIGR1cmFudGUgZWwgdGllbXBvIGRlIG11ZXN0cmVvLiBFc3RlIGFuw6FsaXNpcyBzaWd1ZSBsYSBtZXRvZG9sb2fDrWEgcGxhbnRlYWRhIHBvciBJZ2FyemEgZXQgYWwuICgyMDI0KSoqLg0KDQpgYGB7ciwgZWNobz1UUlVFLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgRXh0cmFlciBzb2xvIGxhIEhvcmEgZW4gdW5hIG51ZXZhIGNvbHVtbmENCnRvdGFsIDwtIHRvdGFsICU+JQ0KICBtdXRhdGUoDQogICAgSG9yYSA9IGFzLmludGVnZXIoZm9ybWF0KEhvcmFfTGltYSwgIiVIIikpLA0KICAgIERpYU5vY2hlID0gaWZlbHNlKEhvcmEgPj0gNiAmIEhvcmEgPD0gMTcsICJEw61hIiwgIk5vY2hlIikNCiAgKQ0KDQojIERlZmluaXIgbG9zIGNvbG9yZXMNCmNvbG9yZXMgPC0gYygiRMOtYSIgPSAiZ3JheTEwMCIsICJOb2NoZSIgPSAiZ3JheTgwIikNCg0KIyBDcmVhciBlbCBncsOhZmljbyBjb24gYm94cGxvdHMgcG9yIGNhZGEgaG9yYQ0KZ2dwbG90KHRvdGFsLCBhZXMoeCA9IGZhY3RvcihIb3JhKSwgeSA9IERPX3NhdCwgZmlsbCA9IERpYU5vY2hlKSkgKw0KICBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjYsIGFscGhhID0gMC44LCBvdXRsaWVyLmFscGhhID0gMC41LCBvdXRsaWVyLnNpemUgPSAxKSArDQogIGZhY2V0X3dyYXAofiBNb3J0YWxpZGFkLCBuY29sID0gMikgKyAgIyBVbmEgZmFjZXRhIHBvciBjYWRhIHBlcmlvZG8gZGUgbW9ydGFsaWRhZA0KICBsYWJzKA0KICAgIHggPSAiSG9yYSBkZWwgRMOtYSIsDQogICAgeSA9ICJTYXR1cmFjacOzbiBPRCAoJSkiLA0KICAgIGZpbGwgPSAiTW9tZW50byBkZWwgRMOtYSIsDQogICAgdGl0bGUgPSAiVmFyaWFiaWxpZGFkIERpYXJhIGRlIFNhdHVyYWNpw7NuIGRlIE94w61nZW5vIg0KICApICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3MgPSBzZXEoMCwgMjMsIGJ5ID0gMikpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JlcykgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyNC40LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMC41KSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5OTUiLCBjb2xvciA9ICJibGFjayIpLCAgIyBGb25kbyBkZSBsYXMgZmFjZXRhcw0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEyKSwgICMgVGV4dG8gZW4gbGFzIGZhY2V0YXMNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgICMgVGFtYcOxbyBkZSB0ZXh0byBkZSBsb3MgZWplcw0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgICMgVGFtYcOxbyBkZSB0ZXh0byBkZSB0w610dWxvcyBkZSBlamVzDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUXVpdGFyIGzDrW5lYXMgZGUgZ3JpbGxhIG1heW9yDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUXVpdGFyIGzDrW5lYXMgZGUgZ3JpbGxhIG1lbm9yDQogICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiksICAjIEHDsWFkaXIgbMOtbmVhcyBkZSBsb3MgZWplcw0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiYmxhY2siKSAgIyBBw7FhZGlyIG1hcmNhcyBlbiBsb3MgZWplcw0KICApDQpgYGANCmBgYHtyLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgMS4gQ2FsY3VsYXIgbGEgbWVkaWFuYSBkZSBET19zYXQgcG9yIEhvcmEgeSBNb3J0YWxpZGFkDQptZWRpYW5hX3Bvcl9ob3JhIDwtIHRvdGFsICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkLCBIb3JhKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lZGlhbmFfRE9fc2F0ID0gbWVkaWFuKERPX3NhdCwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkNCg0KIyAyLiBEZWZpbmlyIGxhIGZ1bmNpw7NuIHNpbnVzb2lkYWwNCnNpbnVzb2lkYWwgPC0gZnVuY3Rpb24oeCwgYW1wbGl0dWQsIGZyZWN1ZW5jaWEsIGZhc2UsIGRlc3BsYXphbWllbnRvKSB7DQogIGFtcGxpdHVkICogc2luKGZyZWN1ZW5jaWEgKiB4ICsgZmFzZSkgKyBkZXNwbGF6YW1pZW50bw0KfQ0KDQojIDMuIEFqdXN0YXIgbGEgZnVuY2nDs24gc2ludXNvaWRhbCBhIGxvcyBkYXRvcw0KYWp1c3RlcyA8LSBtZWRpYW5hX3Bvcl9ob3JhICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgICMgQ2FsY3VsYXIgcGFyw6FtZXRyb3MgaW5pY2lhbGVzDQogICAgYW1wbGl0dWRfaW5pY2lvID0gKG1heChNZWRpYW5hX0RPX3NhdCwgbmEucm0gPSBUUlVFKSAtIG1pbihNZWRpYW5hX0RPX3NhdCwgbmEucm0gPSBUUlVFKSkgLyAyLA0KICAgIGRlc3BsYXphbWllbnRvX2luaWNpbyA9IG1lYW4oTWVkaWFuYV9ET19zYXQsIG5hLnJtID0gVFJVRSksDQogICAgYWp1c3RlID0gbGlzdCgNCiAgICAgIG5sc0xNKA0KICAgICAgICBNZWRpYW5hX0RPX3NhdCB+IHNpbnVzb2lkYWwoSG9yYSwgYW1wbGl0dWQsIGZyZWN1ZW5jaWEsIGZhc2UsIGRlc3BsYXphbWllbnRvKSwNCiAgICAgICAgZGF0YSA9IGN1cl9kYXRhKCksDQogICAgICAgIHN0YXJ0ID0gbGlzdCgNCiAgICAgICAgICBhbXBsaXR1ZCA9IGFtcGxpdHVkX2luaWNpbywNCiAgICAgICAgICBmcmVjdWVuY2lhID0gMiAqIHBpIC8gMjQsICMgRnJlY3VlbmNpYSBwYXJhIGNpY2xvIGRlIDI0IGhvcmFzDQogICAgICAgICAgZmFzZSA9IDAsICMgSW5pY2lhbG1lbnRlIHNpbiBkZXNwbGF6YW1pZW50bw0KICAgICAgICAgIGRlc3BsYXphbWllbnRvID0gZGVzcGxhemFtaWVudG9faW5pY2lvDQogICAgICAgICkNCiAgICAgICkNCiAgICApLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQojIDQuIEV4dHJhZXIgbG9zIHBhcsOhbWV0cm9zIGFqdXN0YWRvcyB5IGNvcnJlZ2lyIGFtcGxpdHVkIHkgZmFzZQ0KcGFyYW1ldHJvcyA8LSBhanVzdGVzICU+JQ0KICBtdXRhdGUoDQogICAgY29lZmljaWVudGVzID0gbWFwKGFqdXN0ZSwgY29lZikNCiAgKSAlPiUNCiAgc2VsZWN0KE1vcnRhbGlkYWQsIGNvZWZpY2llbnRlcykgJT4lDQogIHVubmVzdF93aWRlcihjb2VmaWNpZW50ZXMpICU+JQ0KICBtdXRhdGUoDQogICAgQW1wbGl0dWQgPSBhYnMoYW1wbGl0dWQpLCAjIEFzZWd1cmFyIGFtcGxpdHVkIHBvc2l0aXZhDQogICAgRmFzZSA9IGlmZWxzZShhbXBsaXR1ZCA8IDAsIGZhc2UgKyBwaSwgZmFzZSksICMgQ29ycmVnaXIgZmFzZSBzaSBhbXBsaXR1ZCBlcmEgbmVnYXRpdmENCiAgICBIb3JhbWF4ID0gKC1GYXNlIC8gZnJlY3VlbmNpYSkgJSUgMjQgIyBDYWxjdWxhciBsYSBob3JhIGRlbCBtw6F4aW1vIHkgYXNlZ3VyYXIgMC0yNA0KICApICU+JQ0KICBzZWxlY3QoTW9ydGFsaWRhZCwgQW1wbGl0dWQsIEZyZWN1ZW5jaWEgPSBmcmVjdWVuY2lhLCBGYXNlLCBEZXNwbGF6YW1pZW50byA9IGRlc3BsYXphbWllbnRvLCBIb3JhbWF4KQ0KDQojIEltcHJpbWlyIGxvcyBwYXLDoW1ldHJvcyBhanVzdGFkb3MNCnByaW50KHBhcmFtZXRyb3MpDQoNCiMgNS4gQ3JlYXIgZGF0b3MgYWp1c3RhZG9zIGNvbiBsYSBvbmRhIHNpbnVzb2lkYWwNCmRhdG9zX2FqdXN0YWRvcyA8LSBtZWRpYW5hX3Bvcl9ob3JhICU+JQ0KICBsZWZ0X2pvaW4ocGFyYW1ldHJvcywgYnkgPSAiTW9ydGFsaWRhZCIpICU+JQ0KICBtdXRhdGUoDQogICAgQWp1c3RlID0gQW1wbGl0dWQgKiBzaW4oRnJlY3VlbmNpYSAqIEhvcmEgKyBGYXNlKSArIERlc3BsYXphbWllbnRvDQogICkNCg0KIyA2LiBHcmFmaWNhciBkYXRvcyByZWFsZXMgeSBhanVzdGFkb3MgY29uIGVzY2FsYSBmaWphIGRlIDAgYSAxMDANCmdncGxvdChkYXRvc19hanVzdGFkb3MsIGFlcyh4ID0gSG9yYSkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gQWp1c3RlLCBjb2xvciA9IE1vcnRhbGlkYWQpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGdlb21fcG9pbnQoYWVzKHkgPSBNZWRpYW5hX0RPX3NhdCwgY29sb3IgPSBNb3J0YWxpZGFkKSwgc2l6ZSA9IDEpICsNCiAgZmFjZXRfd3JhcCh+IE1vcnRhbGlkYWQsIHNjYWxlcyA9ICJmaXhlZCIpICsgICMgRXNjYWxhIGZpamEgZW4gWQ0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA2MCkpICsgICMgRmlqYXIgbMOtbWl0ZXMgZGUgMCBhIDEwMA0KICBsYWJzKA0KICAgIHRpdGxlID0gIkFqdXN0ZSBkZSBmdW5jacOzbiBzaW51c29pZGFsIiwNCiAgICB4ID0gIkhvcmEgZGVsIGTDrWEiLA0KICAgIHkgPSAiTWVkaWFuYSBkZSBTYXR1cmFjacOzbiBkZSBPeMOtZ2VubyAoRE9fc2F0KSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIDcuIENyZWFyIGRhdG9zIGFqdXN0YWRvcyBzaW4gZGVzcGxhemFtaWVudG8gdmVydGljYWwgKHNvbG8gYW1wbGl0dWQgeSBmYXNlKQ0KZGF0b3NfYWp1c3RhZG9zX3Npbl9kIDwtIG1lZGlhbmFfcG9yX2hvcmEgJT4lDQogIGxlZnRfam9pbihwYXJhbWV0cm9zLCBieSA9ICJNb3J0YWxpZGFkIikgJT4lDQogIG11dGF0ZSgNCiAgICBBanVzdGVfc2luX2QgPSBBbXBsaXR1ZCAqIHNpbihGcmVjdWVuY2lhICogSG9yYSArIEZhc2UpICAjIEVsaW1pbmFyIGVsIGRlc3BsYXphbWllbnRvIHZlcnRpY2FsDQogICkNCg0KIyA4LiBHcmFmaWNhciBsYXMgb25kYXMgc2ludXNvaWRhbGVzIHNpbiBkZXNwbGF6YW1pZW50byB2ZXJ0aWNhbA0KZ2dwbG90KGRhdG9zX2FqdXN0YWRvc19zaW5fZCwgYWVzKHggPSBIb3JhLCB5ID0gQWp1c3RlX3Npbl9kLCBjb2xvciA9IE1vcnRhbGlkYWQpKSArDQogIGdlb21fbGluZShzaXplID0gMSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQ29tcGFyYWNpw7NuIGRlIG9uZGFzIHNpbnVzb2lkYWxlcyIsDQogICAgeCA9ICJIb3JhIGRlbCBkw61hIiwNCiAgICB5ID0gIk9zY2lsYWNpw7NuIHJlbGF0aXZhIGRlIERPX3NhdCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsNCiAgdGhlbWUoDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpDQogICkNCmBgYA0KTGEgYW1wbGl0dWQgaW5kaWNhIGN1w6FudG8gdmFyw61hIGxhIHNhdHVyYWNpw7NuIGRlIG94w61nZW5vIGEgbG8gbGFyZ28gZGVsIGTDrWEsIGRlc2RlIGVsIG5pdmVsIG1lZGlvIChEZXNwbGF6YW1pZW50bykgaGFzdGEgbG9zIHBpY29zIChwb3NpdGl2b3MgbyBuZWdhdGl2b3MpLiBFcyB1bmEgbWVkaWRhIGRlIGxhIHZhcmlhYmlsaWRhZCBkaWFyaWE6DQoNCk1heW9yIGFtcGxpdHVkIOKGkiBNYXlvciB2YXJpYWNpw7NuIGRpYXJpYSBlbnRyZSBkw61hIHkgbm9jaGUuDQpNZW5vciBhbXBsaXR1ZCDihpIgQ2ljbG8gZGlhcmlvIG1lbm9zIG1hcmNhZG8gKHNhdHVyYWNpw7NuIG3DoXMgZXN0YWJsZSkuDQoNCkxhIGZyZWN1ZW5jaWEgZXN0w6EgcmVsYWNpb25hZGEgY29uIGVsIG7Dum1lcm8gZGUgY2ljbG9zIGNvbXBsZXRhZG9zIGVuIHVuIHBlcsOtb2RvIGRlIHRpZW1wby4gSW50ZXJwcmV0YWNpw7NuOg0KTGEgZnJlY3VlbmNpYSBkZWJlcsOtYSBzZXIgYXByb3hpbWFkYW1lbnRlIDAuMjYxOCBzaSBsYXMgb3NjaWxhY2lvbmVzIG9jdXJyZW4gZXhhY3RhbWVudGUgY2FkYSAyNCBob3Jhcy4NClR1cyByZXN1bHRhZG9zIHRpZW5lbiBsaWdlcmFzIGRpZmVyZW5jaWFzOg0KDQoqIE1vcnRhbGlkYWQgMjAxNSAtIENvbnN0YW50ZSAoMC4zNTMpOiBGcmVjdWVuY2lhIHVuIHBvY28gbWF5b3IsIGxvIHF1ZSBwb2Ryw61hIGluZGljYXIgb3NjaWxhY2lvbmVzIG3DoXMgcsOhcGlkYXMgKGxpZ2VyYW1lbnRlIGRlc2Zhc2FkYXMgZGVsIGNpY2xvIGRpYXJpbyBwZXJmZWN0bykuDQoNCiogTm8gTW9ydGFsaWRhZCAoMC4yOTgpOiBGcmVjdWVuY2lhIG3DoXMgYmFqYSwgbG8gcXVlIHN1Z2llcmUgb3NjaWxhY2lvbmVzIG3DoXMgbGVudGFzIHkgdW4gY2ljbG8gbcOhcyAiZXh0ZW5kaWRvIi4NCg0KRW4gZ2VuZXJhbCwgZXN0YXMgcGVxdWXDsWFzIGRpZmVyZW5jaWFzIHBvZHLDrWFuIGRlYmVyc2UgYSBydWlkbyBvIGEgZmVuw7NtZW5vcyBiaW9sw7NnaWNvcyBxdWUgZGVzdsOtZW4gZWwgY2ljbG8gZGUgdW4gcGF0csOzbiBlc3RyaWN0YW1lbnRlIGRpYXJpby4NCg0KTGEgZmFzZSBpbmRpY2EgZWwgZGVzcGxhemFtaWVudG8gaG9yaXpvbnRhbCBkZSBsYSBvbmRhIHNpbnVzb2lkYWwsIGVzIGRlY2lyLCBlbiBxdcOpIG1vbWVudG8gZGVsIGTDrWEgb2N1cnJlIGVsIG3DoXhpbW8gbyBtw61uaW1vIGRlIHNhdHVyYWNpw7NuLg0KDQojIEluZGljYWRvcmVzIGRlIGhpcG94aWEgey50YWJzZXR9DQoNClNlIGV2YWx1YXLDoSBsYSB2YXJpYWJpbGlkYWQgZGUgaGlwb3hpYSBtZWRpYW50ZSBsb3Mgc2lndWllbnRlcyBpbmRpY2Fkb3JlczogZWwgcG9yY2VudGFqZSBkZSByZWdpc3Ryb3MgaGlww7N4aWNvcywgbGFzIGhvcmFzIGRlIGhpcG94aWEgYWwgZMOtYSwgbGEgbWVkaWFuYSBkZSBzYXR1cmFjacOzbiBkZSBPRCBhbCBkw61hIHkgZWwgdmFsb3IgbcOtbmltbyBkZSBzYXR1cmFjacOzbiBkZSBPRCBhbCBkw61hLiANCg0KRGVzcHXDqXMgZGVsIGFuw6FsaXNpcyBkZSBsYSB2YXJpYWJpbGlkYWQgZGVsIGNpY2xvIGRpYXJpbyBkZSBzYXR1cmFjacOzbiBkZSBPRCwgc2UgcmVhbGl6YXLDoSBlbCAqKmFuw6FsaXNpcyBkZSBsb3MgZXZlbnRvcyBoaXDDs3hpY29zKiouIFBhcmEgZGV0ZXJtaW5hciB1biBldmVudG8gaGlww7N4aWNvLCBlc3RlIGRlYmUgc2VyIGlndWFsIG8gaW5mZXJpb3IgYWwgMjQuNCUgZGUgc2F0dXJhY2nDs24gZGUgT0QgeSBkdXJhciBhbCBtZW5vcyBzZWlzIGhvcmFzIGNvbnNlY3V0aXZhcyAoU2hpZWxkcyB5IFdlaWRtYW4sIDIwMDgpLg0KDQojIyBOdW1lcm8gZGUgaG9yYXMgaGlwb3hpY2FzIGFsIGRpYQ0KDQoqKk51bWVybyBkZSBob3JhcyBoaXBveGljYXMgYWwgZGlhOioqDQoNCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy53aWR0aD0xMCxtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGdW5jacOzbiBwYXJhIGFncmVnYXIgY29sdW1uYSBkZSBoaXBveGlhDQphZ3JlZ2FyX2NvbHVtbmFfaGlwb3hpYSA8LSBmdW5jdGlvbihkYXRhKSB7DQogIGRhdGEkSGlwb3hpYSA8LSBpZmVsc2UoZGF0YSRET19zYXQgPD0gMjQuNCwgMSwgMCkNCiAgcmV0dXJuKGRhdGEpDQp9DQoNCnRvdGFsIDwtIGFncmVnYXJfY29sdW1uYV9oaXBveGlhKHRvdGFsKQ0KDQojIEZ1bmNpw7NuIHBhcmEgY2FsY3VsYXIgaG9yYXMgZGUgaGlwb3hpYSBwb3IgZMOtYQ0KY2FsY3VsYXJfaG9yYXNfaGlwb3hpYSA8LSBmdW5jdGlvbihkZikgew0KICBkZiAlPiUNCiAgICBtdXRhdGUoRGlhID0gYXMuRGF0ZShIb3JhX0xpbWEpKSAlPiUNCiAgICBncm91cF9ieShEaWEsIE1vcnRhbGlkYWQpICU+JQ0KICAgIHN1bW1hcmlzZShIb3Jhc19IaXBveGlhID0gc3VtKEhpcG94aWEpLCAuZ3JvdXBzID0gJ2Ryb3AnKQ0KfQ0KDQpob3Jhc19oaXBveGljYXMgPC0gY2FsY3VsYXJfaG9yYXNfaGlwb3hpYSh0b3RhbCkNCg0KIyBOb3JtYWxpZGFkIGRlIGxvcyBkYXRvcw0KaG9yYXNfaGlwb3hpY2FzICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lbnNhamUgPSBwYXN0ZSgNCiAgICAgICJQcnVlYmEgZGUgU2hhcGlyby1XaWxrIHBhcmEiLCANCiAgICAgIGZpcnN0KE1vcnRhbGlkYWQpLCAjIE9idMOpbiBlbCBub21icmUgZGVsIGdydXBvDQogICAgICAiOiBwID0iLCBzaWduaWYoc2hhcGlyby50ZXN0KEhvcmFzX0hpcG94aWEpJHAudmFsdWUsIGRpZ2l0cyA9IDMpDQogICAgKQ0KICApICU+JQ0KICBwdWxsKG1lbnNhamUpICU+JSAjIEV4dHJhZSBzb2xvIGxvcyBtZW5zYWplcw0KICBjYXQoc2VwID0gIlxuIikgIyBMb3MgaW1wcmltZSBsw61uZWEgcG9yIGzDrW5lYQ0KDQojIEhvbW9nZW5laWRhZCBkZSBsb3MgZGF0b3MNCmxldmVuZV9yZXN1bHQ8LSBsZXZlbmVUZXN0KEhvcmFzX0hpcG94aWEgfiBNb3J0YWxpZGFkLCBkYXRhID0gaG9yYXNfaGlwb3hpY2FzKQ0KIyBFeHRyYWVyIGVsIHZhbG9yIHAgZGVsIHJlc3VsdGFkbw0KcF92YWx1ZV9sZXZlbmUgPC0gc2lnbmlmKGxldmVuZV9yZXN1bHQkYFByKD5GKWBbMV0sIGRpZ2l0cyA9IDMpDQoNCiMgQ3JlYXIgdW4gbWVuc2FqZSBwZXJzb25hbGl6YWRvDQpjYXQoIlBydWViYSBkZSBMZXZlbmUgcGFyYSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzOiBwID0iLCBwX3ZhbHVlX2xldmVuZSwgIlxuIikNCg0KIyBLcnVza2FsLVdhbGxpcw0Ka3J1c2thbF9yZXN1bHQgPC0ga3J1c2thbC50ZXN0KEhvcmFzX0hpcG94aWEgfiBNb3J0YWxpZGFkLCBkYXRhID0gaG9yYXNfaGlwb3hpY2FzKQ0KcHJpbnQoa3J1c2thbF9yZXN1bHQpDQoNCiMgUG9zdC1ob2MgY29uIER1bm4gcGFyYSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbnRyZSBwYXJlcyBkZSBncnVwb3MNCmR1bm5fcmVzdWx0IDwtIGR1bm5UZXN0KEhvcmFzX0hpcG94aWEgfiBNb3J0YWxpZGFkLCBkYXRhID0gaG9yYXNfaGlwb3hpY2FzLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQoNCiMgRXh0cmFlciBsb3MgcmVzdWx0YWRvcyBlbiBmb3JtYXRvIGRlIGRhdGFmcmFtZQ0KdGFibGFfZHVubiA8LSBhcy5kYXRhLmZyYW1lKGR1bm5fcmVzdWx0JHJlcykNCg0KIyBSZW5vbWJyYXIgY29sdW1uYXMgcGFyYSBxdWUgc2VhbiBtw6FzIGxlZ2libGVzDQpjb2xuYW1lcyh0YWJsYV9kdW5uKSA8LSBjKCJDb21wYXJhY2lvbiIsICJFc3RhZGlzdGljbyBaIiwgIlAgc2luIGFqdXN0YXIiLCAiUCBhanVzdGFkbyIpDQoNCiMgQ3JlYXIgbGEgdGFibGEgY29uIGd0DQp0YWJsYV9kdW5uICU+JQ0KICBndCgpICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gIlJlc3VsdGFkb3MgZGVsIFRlc3QgZGUgRHVubiIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpb25lcyBkZSBIb3JhcyBIaXBveGljYXMgZW50cmUgZ3J1cG9zIGRlIE1vcnRhbGlkYWQiDQogICkgJT4lDQogIGZtdF9udW1iZXIoDQogICAgY29sdW1ucyA9IGMoIkVzdGFkaXN0aWNvIFoiLCAiUCBzaW4gYWp1c3RhciIsICJQIGFqdXN0YWRvIiksDQogICAgZGVjaW1hbHMgPSAzDQogICkgJT4lDQogIGNvbHNfbGFiZWwoDQogICAgYENvbXBhcmFjaW9uYCA9ICJHcnVwb3MgQ29tcGFyYWRvcyIsDQogICAgYEVzdGFkaXN0aWNvIFpgID0gIkVzdGFkw61zdGljbyBaIiwNCiAgICBgUCBzaW4gYWp1c3RhcmAgPSAiUC12YWxvciAoc2luIGFqdXN0YXIpIiwNCiAgICBgUCBhanVzdGFkb2AgPSAiUC12YWxvciAoYWp1c3RhZG8pIg0KICApDQoNCmBgYA0KDQpDdWFsIHRpcG8gZGUgZ3JhZmljbyB1c2FyPw0KYGBge3IsIGVjaG89VFJVRSwgZmlnLndpZHRoPTEwLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIEJveHBsb3RzDQpnZ3Bsb3QoaG9yYXNfaGlwb3hpY2FzLCBhZXMoeCA9IE1vcnRhbGlkYWQsIHkgPSBIb3Jhc19IaXBveGlhLCBmaWxsID0gTW9ydGFsaWRhZCkpICsNCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC43LCBvdXRsaWVyLnNoYXBlID0gTkEpICsNCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIHNpemUgPSAyLCBhbHBoYSA9IDAuNiwgY29sb3IgPSAiYmxhY2siKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAiI0U2OUYwMCIsICIjMDA5RTczIiwgIiNENTVFMDAiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkhvcmFzIEhpcMOzeGljYXMgYWwgZMOtYSIsDQogICAgeCA9ICIiLA0KICAgIHkgPSAiSG9yYXMiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSINCiAgKQ0KDQojIFZpb2xpbnBsb3QNCmdncGxvdChob3Jhc19oaXBveGljYXMsIGFlcyh4ID0gTW9ydGFsaWRhZCwgeSA9IEhvcmFzX0hpcG94aWEsIGZpbGwgPSBNb3J0YWxpZGFkKSkgKw0KICBnZW9tX3Zpb2xpbih0cmltID0gRkFMU0UsIGFscGhhID0gMC42LCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV9ib3hwbG90KHdpZHRoID0gMC4xLCBvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAiI0U2OUYwMCIsICIjMDA5RTczIiwgIiNENTVFMDAiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkhvcmFzIEhpcMOzeGljYXMgYWwgZMOtYSIsDQogICAgeCA9ICIiLA0KICAgIHkgPSAiSG9yYXMiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSINCiAgKQ0KDQojIFJlb3JkZW5hciBsb3Mgbml2ZWxlcyBkZSBsYSB2YXJpYWJsZSAnTW9ydGFsaWRhZCcNCmhvcmFzX2hpcG94aWNhcyRNb3J0YWxpZGFkIDwtIGZhY3RvcigNCiAgaG9yYXNfaGlwb3hpY2FzJE1vcnRhbGlkYWQsDQogIGxldmVscyA9IGMoDQogICAgIk1vcnRhbGlkYWQgMjAxNSAtIEJhcnJhbmNvcyIsDQogICAgIk1vcnRhbGlkYWQgMjAxOSAtIENvbnN0YW50ZSIsDQogICAgIk1vcnRhbGlkYWQgMjAxNSAtIENvbnN0YW50ZSIsDQogICAgIk5vIE1vcnRhbGlkYWQiDQogICksDQogIGxhYmVscyA9IGMoDQogICAgIk1vcnRhbGlkYWQgMjAxNVxuQmFycmFuY29zIiwNCiAgICAiTW9ydGFsaWRhZCAyMDE5XG5Db25zdGFudGUiLA0KICAgICJNb3J0YWxpZGFkIDIwMTVcbkNvbnN0YW50ZSIsDQogICAgIk5vIE1vcnRhbGlkYWQiDQogICkNCikNCg0KIyBTdGF0cyArIGdyYXBoDQpnZ2JldHdlZW5zdGF0cygNCiAgZGF0YSA9IGhvcmFzX2hpcG94aWNhcywNCiAgeCA9IE1vcnRhbGlkYWQsDQogIHkgPSBIb3Jhc19IaXBveGlhLA0KICB0aXRsZSA9IE5VTEwsICMgRWxpbWluYSBlbCB0w610dWxvDQogIHJlc3VsdHMuc3VidGl0bGUgPSBGLCAjIEVsaW1pbmEgZWwgc3VidMOtdHVsbyBxdWUgY29udGllbmUgbGEgZWN1YWNpw7NuDQogIHhsYWIgPSAiIiwNCiAgeWxhYiA9ICJIb3JhcyBlbiBoaXBveGlhIGFsIGTDrWEiLA0KICB0eXBlID0gIm5vbnBhcmFtZXRyaWMiLCAjIFVzYSBLcnVza2FsLVdhbGxpcyBjb21vIHRlc3QgcHJpbmNpcGFsDQogIHBhaXJ3aXNlLmNvbXBhcmlzb25zID0gVFJVRSwgIyBDb21wYXJhY2lvbmVzIHBvc3QtaG9jIGVudHJlIGdydXBvcw0KICB2YXIuZXF1YWwgPSBGQUxTRSwNCiAgcGFpcndpc2UuZGlzcGxheSA9ICJzaWduaWZpY2FudCIsICMgU29sbyBtdWVzdHJhIHBhcmVzIHNpZ25pZmljYXRpdm9zDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiwgIyBDb3JyZWNjacOzbiBwYXJhIG3Dumx0aXBsZXMgY29tcGFyYWNpb25lcw0KICBnZ3RoZW1lID0gZ2dwbG90Mjo6dGhlbWVfbWluaW1hbCgpLCAjIFRlbWEgbWluaW1hbGlzdGENCiAgdmlvbGluLmFyZ3MgPSBsaXN0KHdpZHRoID0gMCwgbGluZXdpZHRoID0gMCkgIyBQYXJhIHF1aXRhciBlbCB2aW9saW4gcGxvdA0KKSArDQogICMgUGVyc29uYWxpemFjacOzbiBkZWwgdGVtYQ0KICBnZ3Bsb3QyOjp0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAwKSwgIyBRdWl0YSBlbCB0w610dWxvDQogICAgcGxvdC5zdWJ0aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMCksICMgUXVpdGEgZWwgc3VidMOtdHVsbw0KICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxMiksICMgVGFtYcOxbyBkZWwgdGV4dG8gZGUgbGEgbGV5ZW5kYQ0KICAgIGF4aXMudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImJsYWNrIiksICMgVGFtYcOxbyB5IGNvbG9yIGRlbCB0ZXh0byBkZSBsb3MgZWplcw0KICAgIGF4aXMudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwgIyBUYW1hw7FvIGRlIHTDrXR1bG8gZGUgbG9zIGVqZXMNCiAgICBheGlzLnRpY2tzLmxlbmd0aCA9IGdncGxvdDI6OnVuaXQoNSwgInB0IiksICMgTG9uZ2l0dWQgZGUgbG9zIHRpY2tzDQogICAgYXhpcy50aWNrcyA9IGdncGxvdDI6OmVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIpLCAjIENvbG9yIGRlIGxvcyB0aWNrcw0KICAgIGF4aXMubGluZSA9IGdncGxvdDI6OmVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjUpLCAjIEzDrW5lYXMgZGUgbG9zIGVqZXMNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCAjIEVsaW1pbmEgbGFzIGzDrW5lYXMgZGUgbGEgZ3JpbGxhIG1heW9yDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSAgIyBFbGltaW5hIGxhcyBsw61uZWFzIGRlIGxhIGdyaWxsYSBtZW5vcg0KICApICsNCiAgZ2dwbG90Mjo6c2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAicmVkIiwgImdyZWVuIiwgIiNENTVFMDAiKSkNCg0KDQoNCmBgYA0KDQojIyBQb3JjZW50YWplIGRlIHJlZ2lzdHJvcyBoaXDDs3hpY29zIGFsIGTDrWENCg0KKipQb3JjZW50YWplIGRlIHJlZ2lzdHJvcyBoaXDDs3hpY29zIGFsIGRpYToqKg0KDQpgYGB7ciwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGdW5jacOzbiBwYXJhIGNhbGN1bGFyIGVsIHBvcmNlbnRhamUgZGUgaG9yYXMgaGlww7N4aWNhcyBwb3IgZMOtYQ0KY2FsY3VsYXJfcG9yY2VudGFqZV9oaXBveGlhIDwtIGZ1bmN0aW9uKGRmKSB7DQogIGRmICU+JQ0KICAgIG11dGF0ZShEaWEgPSBhcy5EYXRlKEhvcmFfTGltYSkpICU+JQ0KICAgIGdyb3VwX2J5KERpYSwgTW9ydGFsaWRhZCkgJT4lDQogICAgc3VtbWFyaXNlKA0KICAgICAgSG9yYXNfSGlwb3hpYSA9IHN1bShIaXBveGlhKSwgICMgQ29udGFyIGxhcyBob3JhcyBoaXDDs3hpY2FzDQogICAgICBIb3Jhc19Ub3RhbGVzID0gbigpLCAgIyBDb250YXIgZWwgbsO6bWVybyB0b3RhbCBkZSByZWdpc3Ryb3MgcG9yIGTDrWENCiAgICAgIFBvcmNlbnRhamUgPSAoSG9yYXNfSGlwb3hpYSAvIEhvcmFzX1RvdGFsZXMpICogMTAwLCAgIyBDYWxjdWxhciBlbCBwb3JjZW50YWplIGRlIGhvcmFzIGhpcMOzeGljYXMNCiAgICAgIC5ncm91cHMgPSAnZHJvcCcNCiAgICApDQp9DQoNCiMgQXBsaWNhciBsYSBmdW5jacOzbiBhIHR1IGRhdGFmcmFtZQ0KcG9yY2VudGFqZV9oaXBveGlhIDwtIGNhbGN1bGFyX3BvcmNlbnRhamVfaGlwb3hpYSh0b3RhbCkNCg0KIyBOb3JtYWxpZGFkIGRlIGxvcyBkYXRvcw0KcG9yY2VudGFqZV9oaXBveGlhICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lbnNhamUgPSBwYXN0ZSgNCiAgICAgICJQcnVlYmEgZGUgU2hhcGlyby1XaWxrIHBhcmEiLCANCiAgICAgIGZpcnN0KE1vcnRhbGlkYWQpLCAjIE9idMOpbiBlbCBub21icmUgZGVsIGdydXBvDQogICAgICAiOiBwID0iLCBzaWduaWYoc2hhcGlyby50ZXN0KFBvcmNlbnRhamUpJHAudmFsdWUsIGRpZ2l0cyA9IDMpDQogICAgKQ0KICApICU+JQ0KICBwdWxsKG1lbnNhamUpICU+JSAjIEV4dHJhZSBzb2xvIGxvcyBtZW5zYWplcw0KICBjYXQoc2VwID0gIlxuIikgIyBMb3MgaW1wcmltZSBsw61uZWEgcG9yIGzDrW5lYQ0KDQojIEhvbW9nZW5laWRhZCBkZSBsb3MgZGF0b3MNCmxldmVuZV9yZXN1bHQ8LSBsZXZlbmVUZXN0KFBvcmNlbnRhamUgfiBNb3J0YWxpZGFkLCBkYXRhID0gcG9yY2VudGFqZV9oaXBveGlhKQ0KcF92YWx1ZV9sZXZlbmUgPC0gc2lnbmlmKGxldmVuZV9yZXN1bHQkYFByKD5GKWBbMV0sIGRpZ2l0cyA9IDMpDQpjYXQoIlBydWViYSBkZSBMZXZlbmUgcGFyYSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzOiBwID0iLCBwX3ZhbHVlX2xldmVuZSwgIlxuIikNCg0KIyBLcnVza2FsLVdhbGxpcw0Ka3J1c2thbF9yZXN1bHQgPC0ga3J1c2thbC50ZXN0KFBvcmNlbnRhamUgfiBNb3J0YWxpZGFkLCBkYXRhID0gcG9yY2VudGFqZV9oaXBveGlhKQ0KcHJpbnQoa3J1c2thbF9yZXN1bHQpDQoNCiMgUG9zdC1ob2MgY29uIER1bm4gcGFyYSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbnRyZSBwYXJlcyBkZSBncnVwb3MNCmR1bm5fcmVzdWx0IDwtIGR1bm5UZXN0KFBvcmNlbnRhamUgfiBNb3J0YWxpZGFkLCBkYXRhID0gcG9yY2VudGFqZV9oaXBveGlhLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQoNCiMgRXh0cmFlciBsb3MgcmVzdWx0YWRvcyBlbiBmb3JtYXRvIGRlIGRhdGFmcmFtZQ0KdGFibGFfZHVubiA8LSBhcy5kYXRhLmZyYW1lKGR1bm5fcmVzdWx0JHJlcykNCg0KIyBSZW5vbWJyYXIgY29sdW1uYXMgcGFyYSBxdWUgc2VhbiBtw6FzIGxlZ2libGVzDQpjb2xuYW1lcyh0YWJsYV9kdW5uKSA8LSBjKCJDb21wYXJhY2lvbiIsICJFc3RhZGlzdGljbyBaIiwgIlAgc2luIGFqdXN0YXIiLCAiUCBhanVzdGFkbyIpDQoNCiMgQ3JlYXIgbGEgdGFibGEgY29uIGd0DQp0YWJsYV9kdW5uICU+JQ0KICBndCgpICU+JQ0KICB0YWJfaGVhZGVyKA0KICAgIHRpdGxlID0gIlJlc3VsdGFkb3MgZGVsIFRlc3QgZGUgRHVubiIsDQogICAgc3VidGl0bGUgPSAiQ29tcGFyYWNpb25lcyBkZSBQb3JjZW50YWplIGRlIHJlZ2lzdHJvcyBoaXBveGljb3MgZW50cmUgZ3J1cG9zIGRlIE1vcnRhbGlkYWQiDQogICkgJT4lDQogIGZtdF9udW1iZXIoDQogICAgY29sdW1ucyA9IGMoIkVzdGFkaXN0aWNvIFoiLCAiUCBzaW4gYWp1c3RhciIsICJQIGFqdXN0YWRvIiksDQogICAgZGVjaW1hbHMgPSAzDQogICkgJT4lDQogIGNvbHNfbGFiZWwoDQogICAgYENvbXBhcmFjaW9uYCA9ICJHcnVwb3MgQ29tcGFyYWRvcyIsDQogICAgYEVzdGFkaXN0aWNvIFpgID0gIkVzdGFkw61zdGljbyBaIiwNCiAgICBgUCBzaW4gYWp1c3RhcmAgPSAiUC12YWxvciAoc2luIGFqdXN0YXIpIiwNCiAgICBgUCBhanVzdGFkb2AgPSAiUC12YWxvciAoYWp1c3RhZG8pIg0KICApDQoNCmBgYA0KDQpgYGB7ciwgZWNobz1UUlVFLCBmaWcud2lkdGg9MTAsbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmdncGxvdChwb3JjZW50YWplX2hpcG94aWEsIGFlcyh4ID0gTW9ydGFsaWRhZCwgeSA9IFBvcmNlbnRhamUsIGZpbGwgPSBNb3J0YWxpZGFkKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIG91dGxpZXIuc2hhcGUgPSBOQSkgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgc2l6ZSA9IDIsIGFscGhhID0gMC42LCBjb2xvciA9ICJibGFjayIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU2QjRFOSIsICIjRTY5RjAwIiwgIiMwMDlFNzMiLCAiI0Q1NUUwMCIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUmVnaXN0cm9zIEhpcMOzeGljb3MgYWwgZMOtYSIsDQogICAgeCA9ICIiLA0KICAgIHkgPSAiUG9yY2VudGFqZSAlIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICkNCg0KDQpnZ3Bsb3QocG9yY2VudGFqZV9oaXBveGlhLCBhZXMoeCA9IE1vcnRhbGlkYWQsIHkgPSBQb3JjZW50YWplLCBmaWxsID0gTW9ydGFsaWRhZCkpICsNCiAgZ2VvbV92aW9saW4odHJpbSA9IEZBTFNFLCBhbHBoYSA9IDAuNiwgY29sb3IgPSAiYmxhY2siKSArDQogIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSwgb3V0bGllci5zaGFwZSA9IE5BLCBhbHBoYSA9IDAuNSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjNTZCNEU5IiwgIiNFNjlGMDAiLCAiIzAwOUU3MyIsICIjRDU1RTAwIikpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSZWdpc3Ryb3MgSGlww7N4aWNvcyBhbCBkw61hIiwNCiAgICB4ID0gIiIsDQogICAgeSA9ICJQb3JjZW50YWplICUiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSINCiAgKQ0KDQojIFJlb3JkZW5hciBsb3Mgbml2ZWxlcyBkZSBsYSB2YXJpYWJsZSAnTW9ydGFsaWRhZCcNCnBvcmNlbnRhamVfaGlwb3hpYSRNb3J0YWxpZGFkIDwtIGZhY3RvcigNCiAgcG9yY2VudGFqZV9oaXBveGlhJE1vcnRhbGlkYWQsDQogIGxldmVscyA9IGMoDQogICAgIk1vcnRhbGlkYWQgMjAxNSAtIEJhcnJhbmNvcyIsDQogICAgIk1vcnRhbGlkYWQgMjAxOSAtIENvbnN0YW50ZSIsDQogICAgIk1vcnRhbGlkYWQgMjAxNSAtIENvbnN0YW50ZSIsDQogICAgIk5vIE1vcnRhbGlkYWQiDQogICksDQogIGxhYmVscyA9IGMoDQogICAgIk1vcnRhbGlkYWQgMjAxNVxuQmFycmFuY29zIiwNCiAgICAiTW9ydGFsaWRhZCAyMDE5XG5Db25zdGFudGUiLA0KICAgICJNb3J0YWxpZGFkIDIwMTVcbkNvbnN0YW50ZSIsDQogICAgIk5vIE1vcnRhbGlkYWQiDQogICkNCikNCg0KDQojIFN0YXRzICsgZ3JhcGgNCmdnYmV0d2VlbnN0YXRzKA0KICBkYXRhID0gcG9yY2VudGFqZV9oaXBveGlhLA0KICB4ID0gTW9ydGFsaWRhZCwNCiAgeSA9IFBvcmNlbnRhamUsDQogIHRpdGxlID0gTlVMTCwgIyBFbGltaW5hIGVsIHTDrXR1bG8NCiAgcmVzdWx0cy5zdWJ0aXRsZSA9RiwgIyBFbGltaW5hIGVsIHN1YnTDrXR1bG8gcXVlIGNvbnRpZW5lIGxhIGVjdWFjacOzbg0KICB4bGFiID0gIiIsDQogIHlsYWIgPSAiUmVnaXN0cm9zIGhpcMOzeGljb3MgYWwgZMOtYSAoJSkiLA0KICB0eXBlID0gIm5vbnBhcmFtZXRyaWMiLCAjIFVzYSBLcnVza2FsLVdhbGxpcyBjb21vIHRlc3QgcHJpbmNpcGFsDQogIHBhaXJ3aXNlLmNvbXBhcmlzb25zID0gVFJVRSwgIyBDb21wYXJhY2lvbmVzIHBvc3QtaG9jIGVudHJlIGdydXBvcw0KICB2YXIuZXF1YWwgPSBGQUxTRSwNCiAgcGFpcndpc2UuZGlzcGxheSA9ICJzaWduaWZpY2FudCIsICMgU29sbyBtdWVzdHJhIHBhcmVzIHNpZ25pZmljYXRpdm9zDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiwgIyBDb3JyZWNjacOzbiBwYXJhIG3Dumx0aXBsZXMgY29tcGFyYWNpb25lcw0KICBnZ3RoZW1lID0gZ2dwbG90Mjo6dGhlbWVfbWluaW1hbCgpLCAjIFRlbWEgbWluaW1hbGlzdGENCiAgdmlvbGluLmFyZ3MgPSBsaXN0KHdpZHRoID0gMCwgbGluZXdpZHRoID0gMCkgIyBQYXJhIHF1aXRhciBlbCB2aW9saW4gcGxvdA0KKSArDQogICMgUGFsZXRhIGRlIGNvbG9yZXMgcGVyc29uYWxpemFkYQ0KICBnZ3Bsb3QyOjpzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzU2QjRFOSIsICJyZWQiLCAiZ3JlZW4iLCAiI0Q1NUUwMCIpKSArDQogIA0KICAjIFBlcnNvbmFsaXphY2nDs24gZGVsIHRlbWENCiAgZ2dwbG90Mjo6dGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMCksICMgUXVpdGEgZWwgdMOtdHVsbw0KICAgIHBsb3Quc3VidGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDApLCAjIFF1aXRhIGVsIHN1YnTDrXR1bG8NCiAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTIpLCAjIFRhbWHDsW8gZGVsIHRleHRvIGRlIGxhIGxleWVuZGENCiAgICBheGlzLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpLCAjIFRhbWHDsW8geSBjb2xvciBkZWwgdGV4dG8gZGUgbG9zIGVqZXMNCiAgICBheGlzLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNCksICMgVGFtYcOxbyBkZWwgdMOtdHVsbyBkZSBsb3MgZWplcw0KICAgIGF4aXMudGlja3MubGVuZ3RoID0gZ2dwbG90Mjo6dW5pdCg1LCAicHQiKSwgIyBMb25naXR1ZCBkZSBsb3MgdGlja3MNCiAgICBheGlzLnRpY2tzID0gZ2dwbG90Mjo6ZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiksICMgQ29sb3IgZGUgbG9zIHRpY2tzDQogICAgYXhpcy5saW5lID0gZ2dwbG90Mjo6ZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSksICMgTMOtbmVhcyBkZSBsb3MgZWplcw0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBnZ3Bsb3QyOjplbGVtZW50X2JsYW5rKCksICMgRWxpbWluYSBsYXMgbMOtbmVhcyBkZSBsYSBncmlsbGEgbWF5b3INCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpICAjIEVsaW1pbmEgbGFzIGzDrW5lYXMgZGUgbGEgZ3JpbGxhIG1lbm9yDQogICkNCg0KDQpgYGANCg0KIyMgTWluaW1vIGRlIFNhdCBPRCBhbCBkaWENCg0KKipNaW5pbW8gZGUgU2F0dXJhY2lvbiBkZSBveMOtZ2VubyBhbCBkw61hOioqDQpgYGB7ciwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGdW5jacOzbiBwYXJhIGNhbGN1bGFyIG3DrW5pbW8gZGUgRE9fc2F0IHBvciBkw61hIA0KY2FsY3VsYXJfbWluX29kIDwtIGZ1bmN0aW9uKGRmKSB7DQogIGRmICU+JQ0KICAgIG11dGF0ZShEaWEgPSBhcy5EYXRlKEhvcmFfTGltYSkpICU+JQ0KICAgIGdyb3VwX2J5KERpYSwgTW9ydGFsaWRhZCkgJT4lDQogICAgc3VtbWFyaXNlKG1pbmltbyA9IG1pbihET19zYXQpLCAuZ3JvdXBzID0gJ2Ryb3AnKQ0KfQ0KDQojIEFwbGljYXIgY2FsY3VsYXJfbWluX29kIGEgY2FkYSBjb25qdW50byBkZSBkYXRvcw0KbWluX29kIDwtIGNhbGN1bGFyX21pbl9vZCh0b3RhbCkNCg0KIyBOb3JtYWxpZGFkIGRlIGxvcyBkYXRvcw0KbWluX29kICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lbnNhamUgPSBwYXN0ZSgNCiAgICAgICJQcnVlYmEgZGUgU2hhcGlyby1XaWxrIHBhcmEiLCANCiAgICAgIGZpcnN0KE1vcnRhbGlkYWQpLCAjIE9idMOpbiBlbCBub21icmUgZGVsIGdydXBvDQogICAgICAiOiBwID0iLCBzaWduaWYoc2hhcGlyby50ZXN0KG1pbmltbykkcC52YWx1ZSwgZGlnaXRzID0gMykNCiAgICApDQogICkgJT4lDQogIHB1bGwobWVuc2FqZSkgJT4lICMgRXh0cmFlIHNvbG8gbG9zIG1lbnNhamVzDQogIGNhdChzZXAgPSAiXG4iKSAjIExvcyBpbXByaW1lIGzDrW5lYSBwb3IgbMOtbmVhDQoNCiMgSG9tb2dlbmVpZGFkIGRlIGxvcyBkYXRvcw0KbGV2ZW5lX3Jlc3VsdDwtIGxldmVuZVRlc3QobWluaW1vIH4gTW9ydGFsaWRhZCwgZGF0YSA9IG1pbl9vZCkNCnBfdmFsdWVfbGV2ZW5lIDwtIHNpZ25pZihsZXZlbmVfcmVzdWx0JGBQcig+RilgWzFdLCBkaWdpdHMgPSAzKQ0KY2F0KCJQcnVlYmEgZGUgTGV2ZW5lIHBhcmEgaG9tb2dlbmVpZGFkIGRlIHZhcmlhbnphczogcCA9IiwgcF92YWx1ZV9sZXZlbmUsICJcbiIpDQoNCiMgS3J1c2thbC1XYWxsaXMNCmtydXNrYWxfcmVzdWx0IDwtIGtydXNrYWwudGVzdChtaW5pbW8gfiBNb3J0YWxpZGFkLCBkYXRhID0gbWluX29kKQ0KcHJpbnQoa3J1c2thbF9yZXN1bHQpDQoNCiMgUG9zdC1ob2MgY29uIER1bm4gcGFyYSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbnRyZSBwYXJlcyBkZSBncnVwb3MNCmR1bm5fcmVzdWx0IDwtIGR1bm5UZXN0KG1pbmltbyB+IE1vcnRhbGlkYWQsIGRhdGEgPSBtaW5fb2QsIG1ldGhvZCA9ICJib25mZXJyb25pIikNCg0KIyBFeHRyYWVyIGxvcyByZXN1bHRhZG9zIGVuIGZvcm1hdG8gZGUgZGF0YWZyYW1lDQp0YWJsYV9kdW5uIDwtIGFzLmRhdGEuZnJhbWUoZHVubl9yZXN1bHQkcmVzKQ0KDQojIFJlbm9tYnJhciBjb2x1bW5hcyBwYXJhIHF1ZSBzZWFuIG3DoXMgbGVnaWJsZXMNCmNvbG5hbWVzKHRhYmxhX2R1bm4pIDwtIGMoIkNvbXBhcmFjaW9uIiwgIkVzdGFkaXN0aWNvIFoiLCAiUCBzaW4gYWp1c3RhciIsICJQIGFqdXN0YWRvIikNCg0KIyBDcmVhciBsYSB0YWJsYSBjb24gZ3QNCnRhYmxhX2R1bm4gJT4lDQogIGd0KCkgJT4lDQogIHRhYl9oZWFkZXIoDQogICAgdGl0bGUgPSAiUmVzdWx0YWRvcyBkZWwgVGVzdCBkZSBEdW5uIiwNCiAgICBzdWJ0aXRsZSA9ICJDb21wYXJhY2lvbmVzIGRlIFBvcmNlbnRhamUgZGUgcmVnaXN0cm9zIGhpcG94aWNvcyBlbnRyZSBncnVwb3MgZGUgTW9ydGFsaWRhZCINCiAgKSAlPiUNCiAgZm10X251bWJlcigNCiAgICBjb2x1bW5zID0gYygiRXN0YWRpc3RpY28gWiIsICJQIHNpbiBhanVzdGFyIiwgIlAgYWp1c3RhZG8iKSwNCiAgICBkZWNpbWFscyA9IDMNCiAgKSAlPiUNCiAgY29sc19sYWJlbCgNCiAgICBgQ29tcGFyYWNpb25gID0gIkdydXBvcyBDb21wYXJhZG9zIiwNCiAgICBgRXN0YWRpc3RpY28gWmAgPSAiRXN0YWTDrXN0aWNvIFoiLA0KICAgIGBQIHNpbiBhanVzdGFyYCA9ICJQLXZhbG9yIChzaW4gYWp1c3RhcikiLA0KICAgIGBQIGFqdXN0YWRvYCA9ICJQLXZhbG9yIChhanVzdGFkbykiDQogICkNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy53aWR0aD0xMCxtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpnZ3Bsb3QobWluX29kLCBhZXMoeCA9IE1vcnRhbGlkYWQsIHkgPSBtaW5pbW8sIGZpbGwgPSBNb3J0YWxpZGFkKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIG91dGxpZXIuc2hhcGUgPSBOQSkgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgc2l6ZSA9IDIsIGFscGhhID0gMC42LCBjb2xvciA9ICJibGFjayIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU2QjRFOSIsICIjRTY5RjAwIiwgIiMwMDlFNzMiLCAiI0Q1NUUwMCIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTWluaW1hIHNhdHVyYWNpb24gZGUgb3jDrWdlbm8gYWwgZMOtYSIsDQogICAgeCA9ICIiLA0KICAgIHkgPSAiU2F0dXJhY2lvbiBPRCAoJSkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSINCiAgKQ0KDQoNCmdncGxvdChtaW5fb2QsIGFlcyh4ID0gTW9ydGFsaWRhZCwgeSA9IG1pbmltbywgZmlsbCA9IE1vcnRhbGlkYWQpKSArDQogIGdlb21fdmlvbGluKHRyaW0gPSBGQUxTRSwgYWxwaGEgPSAwLjYsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjEsIG91dGxpZXIuc2hhcGUgPSBOQSwgYWxwaGEgPSAwLjUpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU2QjRFOSIsICIjRTY5RjAwIiwgIiMwMDlFNzMiLCAiI0Q1NUUwMCIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTWluaW1hIHNhdHVyYWNpb24gZGUgb3jDrWdlbm8gYWwgZMOtYSIsDQogICAgeCA9ICIiLA0KICAgIHkgPSAiU2F0dXJhY2lvbiBkZSBPRCAoJSkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDE2KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSINCiAgKQ0KDQoNCiMgUmVvcmRlbmFyIGxvcyBuaXZlbGVzIGRlIGxhIHZhcmlhYmxlICdNb3J0YWxpZGFkJw0KbWluX29kJE1vcnRhbGlkYWQgPC0gZmFjdG9yKA0KICBtaW5fb2QkTW9ydGFsaWRhZCwNCiAgbGV2ZWxzID0gYygNCiAgICAiTW9ydGFsaWRhZCAyMDE1IC0gQmFycmFuY29zIiwNCiAgICAiTW9ydGFsaWRhZCAyMDE5IC0gQ29uc3RhbnRlIiwNCiAgICAiTW9ydGFsaWRhZCAyMDE1IC0gQ29uc3RhbnRlIiwNCiAgICAiTm8gTW9ydGFsaWRhZCINCiAgKSwNCiAgbGFiZWxzID0gYygNCiAgICAiTW9ydGFsaWRhZCAyMDE1XG5CYXJyYW5jb3MiLA0KICAgICJNb3J0YWxpZGFkIDIwMTlcbkNvbnN0YW50ZSIsDQogICAgIk1vcnRhbGlkYWQgMjAxNVxuQ29uc3RhbnRlIiwNCiAgICAiTm8gTW9ydGFsaWRhZCINCiAgKQ0KKQ0KDQojIFN0YXRzICsgZ3JhcGgNCmdnYmV0d2VlbnN0YXRzKA0KICBkYXRhID0gbWluX29kLA0KICB4ID0gTW9ydGFsaWRhZCwNCiAgeSA9IG1pbmltbywNCiAgdGl0bGUgPSBOVUxMLCAjIEVsaW1pbmEgZWwgdMOtdHVsbw0KICByZXN1bHRzLnN1YnRpdGxlID0gRiwgIyBFbGltaW5hIGVsIHN1YnTDrXR1bG8gcXVlIGNvbnRpZW5lIGxhIGVjdWFjacOzbg0KICB4bGFiID0gIiIsDQogIHlsYWIgPSAiTWluaW1hIHNhdHVyYWNpw7NuIE9EIGFsIGTDrWEgKCUpIiwNCiAgdHlwZSA9ICJub25wYXJhbWV0cmljIiwgIyBVc2EgS3J1c2thbC1XYWxsaXMgY29tbyB0ZXN0IHByaW5jaXBhbA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IFRSVUUsICMgQ29tcGFyYWNpb25lcyBwb3N0LWhvYyBlbnRyZSBncnVwb3MNCiAgdmFyLmVxdWFsID0gRkFMU0UsDQogIHBhaXJ3aXNlLmRpc3BsYXkgPSAic2lnbmlmaWNhbnQiLCAjIFNvbG8gbXVlc3RyYSBwYXJlcyBzaWduaWZpY2F0aXZvcw0KICBwLmFkanVzdC5tZXRob2QgPSAiYm9uZmVycm9uaSIsICMgQ29ycmVjY2nDs24gcGFyYSBtw7psdGlwbGVzIGNvbXBhcmFjaW9uZXMNCiAgZ2d0aGVtZSA9IGdncGxvdDI6OnRoZW1lX21pbmltYWwoKSwgIyBUZW1hIG1pbmltYWxpc3RhDQogIHZpb2xpbi5hcmdzID0gbGlzdCh3aWR0aCA9IDAsIGxpbmV3aWR0aCA9IDApICMgUGFyYSBxdWl0YXIgZWwgdmlvbGluIHBsb3QNCikgKw0KICAjIFBhbGV0YSBkZSBjb2xvcmVzIHBlcnNvbmFsaXphZGENCiAgZ2dwbG90Mjo6c2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAicmVkIiwgImdyZWVuIiwgIiNENTVFMDAiKSkgKw0KICANCiAgIyBQZXJzb25hbGl6YWNpw7NuIGRlbCB0ZW1hDQogIGdncGxvdDI6OnRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDApLCAjIFF1aXRhIGVsIHTDrXR1bG8NCiAgICBwbG90LnN1YnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAwKSwgIyBRdWl0YSBlbCBzdWJ0w610dWxvDQogICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgIyBUYW1hw7FvIGRlbCB0ZXh0byBkZSBsYSBsZXllbmRhDQogICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSwgIyBUYW1hw7FvIHkgY29sb3IgZGVsIHRleHRvIGRlIGxvcyBlamVzDQogICAgYXhpcy50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpLCAjIFRhbWHDsW8gZGVsIHTDrXR1bG8gZGUgbG9zIGVqZXMNCiAgICBheGlzLnRpY2tzLmxlbmd0aCA9IGdncGxvdDI6OnVuaXQoNSwgInB0IiksICMgTG9uZ2l0dWQgZGUgbG9zIHRpY2tzDQogICAgYXhpcy50aWNrcyA9IGdncGxvdDI6OmVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIpLCAjIENvbG9yIGRlIGxvcyB0aWNrcw0KICAgIGF4aXMubGluZSA9IGdncGxvdDI6OmVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjUpLCAjIEzDrW5lYXMgZGUgbG9zIGVqZXMNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCAjIEVsaW1pbmEgbGFzIGzDrW5lYXMgZGUgbGEgZ3JpbGxhIG1heW9yDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSAgIyBFbGltaW5hIGxhcyBsw61uZWFzIGRlIGxhIGdyaWxsYSBtZW5vcg0KICApDQoNCg0KDQoNCmBgYA0KDQojIyBNZWRpYW5hIGRlIFNhdCBPRCBhbCBkaWENCg0KKipNZWRpYW5hIGRlIFNhdHVyYWNpb24gZGUgb3hpZ2VubyBhbCBkaWE6KioNCg0KYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgRnVuY2nDs24gcGFyYSBjYWxjdWxhciBtZWRpYW5hIGRlIERPX3NhdCBwb3IgZMOtYSB5IHpvbmENCmNhbGN1bGFyX21lZGlhbl9vZCA8LSBmdW5jdGlvbihkZikgew0KICBkZiAlPiUNCiAgICBtdXRhdGUoRGlhID0gYXMuRGF0ZShIb3JhX0xpbWEpKSAlPiUNCiAgICBncm91cF9ieShEaWEsIE1vcnRhbGlkYWQpICU+JQ0KICAgIHN1bW1hcmlzZShtZWRpYW49IG1lZGlhbihET19zYXQpLCAuZ3JvdXBzID0gJ2Ryb3AnKQ0KfQ0KDQojIEFwbGljYXIgY2FsY3VsYXJfbWluX29kIGEgY2FkYSBjb25qdW50byBkZSBkYXRvcw0KbWVkX29kIDwtIGNhbGN1bGFyX21lZGlhbl9vZCh0b3RhbCkNCg0KIyBOb3JtYWxpZGFkIGRlIGxvcyBkYXRvcw0KbWVkX29kICU+JQ0KICBncm91cF9ieShNb3J0YWxpZGFkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIG1lbnNhamUgPSBwYXN0ZSgNCiAgICAgICJQcnVlYmEgZGUgU2hhcGlyby1XaWxrIHBhcmEiLCANCiAgICAgIGZpcnN0KE1vcnRhbGlkYWQpLCAjIE9idMOpbiBlbCBub21icmUgZGVsIGdydXBvDQogICAgICAiOiBwID0iLCBzaWduaWYoc2hhcGlyby50ZXN0KG1lZGlhbikkcC52YWx1ZSwgZGlnaXRzID0gMykNCiAgICApDQogICkgJT4lDQogIHB1bGwobWVuc2FqZSkgJT4lICMgRXh0cmFlIHNvbG8gbG9zIG1lbnNhamVzDQogIGNhdChzZXAgPSAiXG4iKSAjIExvcyBpbXByaW1lIGzDrW5lYSBwb3IgbMOtbmVhDQoNCiMgSG9tb2dlbmVpZGFkIGRlIGxvcyBkYXRvcw0KbGV2ZW5lX3Jlc3VsdDwtIGxldmVuZVRlc3QobWVkaWFuIH4gTW9ydGFsaWRhZCwgZGF0YSA9IG1lZF9vZCkNCnBfdmFsdWVfbGV2ZW5lIDwtIHNpZ25pZihsZXZlbmVfcmVzdWx0JGBQcig+RilgWzFdLCBkaWdpdHMgPSAzKQ0KY2F0KCJQcnVlYmEgZGUgTGV2ZW5lIHBhcmEgaG9tb2dlbmVpZGFkIGRlIHZhcmlhbnphczogcCA9IiwgcF92YWx1ZV9sZXZlbmUsICJcbiIpDQoNCiMgS3J1c2thbC1XYWxsaXMNCmtydXNrYWxfcmVzdWx0IDwtIGtydXNrYWwudGVzdChtZWRpYW4gfiBNb3J0YWxpZGFkLCBkYXRhID0gbWVkX29kKQ0KcHJpbnQoa3J1c2thbF9yZXN1bHQpDQoNCiMgUG9zdC1ob2MgY29uIER1bm4gcGFyYSBpZGVudGlmaWNhciBkaWZlcmVuY2lhcyBlbnRyZSBwYXJlcyBkZSBncnVwb3MNCmR1bm5fcmVzdWx0IDwtIGR1bm5UZXN0KG1lZGlhbiB+IE1vcnRhbGlkYWQsIGRhdGEgPSBtZWRfb2QsIG1ldGhvZCA9ICJib25mZXJyb25pIikNCg0KIyBFeHRyYWVyIGxvcyByZXN1bHRhZG9zIGVuIGZvcm1hdG8gZGUgZGF0YWZyYW1lDQp0YWJsYV9kdW5uIDwtIGFzLmRhdGEuZnJhbWUoZHVubl9yZXN1bHQkcmVzKQ0KDQojIFJlbm9tYnJhciBjb2x1bW5hcyBwYXJhIHF1ZSBzZWFuIG3DoXMgbGVnaWJsZXMNCmNvbG5hbWVzKHRhYmxhX2R1bm4pIDwtIGMoIkNvbXBhcmFjaW9uIiwgIkVzdGFkaXN0aWNvIFoiLCAiUCBzaW4gYWp1c3RhciIsICJQIGFqdXN0YWRvIikNCg0KIyBDcmVhciBsYSB0YWJsYSBjb24gZ3QNCnRhYmxhX2R1bm4gJT4lDQogIGd0KCkgJT4lDQogIHRhYl9oZWFkZXIoDQogICAgdGl0bGUgPSAiUmVzdWx0YWRvcyBkZWwgVGVzdCBkZSBEdW5uIiwNCiAgICBzdWJ0aXRsZSA9ICJDb21wYXJhY2lvbmVzIGRlIFBvcmNlbnRhamUgZGUgcmVnaXN0cm9zIGhpcG94aWNvcyBlbnRyZSBncnVwb3MgZGUgTW9ydGFsaWRhZCINCiAgKSAlPiUNCiAgZm10X251bWJlcigNCiAgICBjb2x1bW5zID0gYygiRXN0YWRpc3RpY28gWiIsICJQIHNpbiBhanVzdGFyIiwgIlAgYWp1c3RhZG8iKSwNCiAgICBkZWNpbWFscyA9IDMNCiAgKSAlPiUNCiAgY29sc19sYWJlbCgNCiAgICBgQ29tcGFyYWNpb25gID0gIkdydXBvcyBDb21wYXJhZG9zIiwNCiAgICBgRXN0YWRpc3RpY28gWmAgPSAiRXN0YWTDrXN0aWNvIFoiLA0KICAgIGBQIHNpbiBhanVzdGFyYCA9ICJQLXZhbG9yIChzaW4gYWp1c3RhcikiLA0KICAgIGBQIGFqdXN0YWRvYCA9ICJQLXZhbG9yIChhanVzdGFkbykiDQogICkNCmBgYA0KDQoNCg0KYGBge3IsIGVjaG89VFJVRSwgZmlnLndpZHRoPTEwLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpnZ3Bsb3QobWVkX29kLCBhZXMoeCA9IE1vcnRhbGlkYWQsIHkgPSBtZWRpYW4sIGZpbGwgPSBNb3J0YWxpZGFkKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjcsIG91dGxpZXIuc2hhcGUgPSBOQSkgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgc2l6ZSA9IDIsIGFscGhhID0gMC42LCBjb2xvciA9ICJibGFjayIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU2QjRFOSIsICIjRTY5RjAwIiwgIiMwMDlFNzMiLCAiI0Q1NUUwMCIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiTWVkaWFuYSBkZSBsYSBzYXR1cmFjaW9uIGRlIG94w61nZW5vIGFsIGTDrWEiLA0KICAgIHggPSAiIiwNCiAgICB5ID0gIlNhdHVyYWNpb24gT0QgKCUpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxNiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiDQogICkNCg0KDQpnZ3Bsb3QobWVkX29kLCBhZXMoeCA9IE1vcnRhbGlkYWQsIHkgPSBtZWRpYW4sIGZpbGwgPSBNb3J0YWxpZGFkKSkgKw0KICBnZW9tX3Zpb2xpbih0cmltID0gRkFMU0UsIGFscGhhID0gMC42LCBjb2xvciA9ICJibGFjayIpICsNCiAgZ2VvbV9ib3hwbG90KHdpZHRoID0gMC4xLCBvdXRsaWVyLnNoYXBlID0gTkEsIGFscGhhID0gMC41KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM1NkI0RTkiLCAiI0U2OUYwMCIsICIjMDA5RTczIiwgIiNENTVFMDAiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1lZGlhbmEgZGUgbGEgc2F0dXJhY2lvbiBkZSBveMOtZ2VubyBhbCBkw61hIiwNCiAgICB4ID0gIiIsDQogICAgeSA9ICJTYXR1cmFjaW9uIGRlIE9EICglKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTYpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIg0KICApDQoNCg0KDQoNCg0KDQoNCiMgQ3JlYXIgZWwgZ3LDoWZpY08NCg0KbWVkX29kJE1vcnRhbGlkYWQgPC0gZmFjdG9yKA0KICBtZWRfb2QkTW9ydGFsaWRhZCwNCiAgbGV2ZWxzID0gYygNCiAgICAiTW9ydGFsaWRhZCAyMDE1IC0gQmFycmFuY29zIiwNCiAgICAiTW9ydGFsaWRhZCAyMDE5IC0gQ29uc3RhbnRlIiwNCiAgICAiTW9ydGFsaWRhZCAyMDE1IC0gQ29uc3RhbnRlIiwNCiAgICAiTm8gTW9ydGFsaWRhZCINCiAgKSwNCiAgbGFiZWxzID0gYygNCiAgICAiTW9ydGFsaWRhZCAyMDE1XG5CYXJyYW5jb3MiLA0KICAgICJNb3J0YWxpZGFkIDIwMTlcbkNvbnN0YW50ZSIsDQogICAgIk1vcnRhbGlkYWQgMjAxNVxuQ29uc3RhbnRlIiwNCiAgICAiTm8gTW9ydGFsaWRhZCINCiAgKQ0KKQ0KDQoNCiMgU3RhdHMgKyBncmFwaA0KZ2diZXR3ZWVuc3RhdHMoDQogIGRhdGEgPSBtZWRfb2QsDQogIHggPSBNb3J0YWxpZGFkLA0KICB5ID0gbWVkaWFuLA0KICB0aXRsZSA9IE5VTEwsICMgRWxpbWluYSBlbCB0w610dWxvDQogIHJlc3VsdHMuc3VidGl0bGUgPSBGQUxTRSwgIyBFbGltaW5hIGVsIHN1YnTDrXR1bG8gcXVlIGNvbnRpZW5lIGxhIGVjdWFjacOzbg0KICB4bGFiID0gIiIsDQogIHlsYWIgPSAiTWVkaWFuYSBkZSBTYXR1cmFjacOzbiBPRCBhbCBkw61hICglKSIsDQogIHR5cGUgPSAibm9ucGFyYW1ldHJpYyIsICMgVXNhIEtydXNrYWwtV2FsbGlzIGNvbW8gdGVzdCBwcmluY2lwYWwNCiAgcGFpcndpc2UuY29tcGFyaXNvbnMgPSBUUlVFLCAjIENvbXBhcmFjaW9uZXMgcG9zdC1ob2MgZW50cmUgZ3J1cG9zDQogIHZhci5lcXVhbCA9IEZBTFNFLA0KICBwYWlyd2lzZS5kaXNwbGF5ID0gInNpZ25pZmljYW50IiwgIyBTb2xvIG11ZXN0cmEgcGFyZXMgc2lnbmlmaWNhdGl2b3MNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLCAjIENvcnJlY2Npw7NuIHBhcmEgbcO6bHRpcGxlcyBjb21wYXJhY2lvbmVzDQogIGdndGhlbWUgPSBnZ3Bsb3QyOjp0aGVtZV9taW5pbWFsKCksICMgVGVtYSBtaW5pbWFsaXN0YQ0KICB2aW9saW4uYXJncyA9IGxpc3Qod2lkdGggPSAwLCBsaW5ld2lkdGggPSAwKSAjIFBhcmEgcXVpdGFyIGVsIHZpb2xpbiBwbG90DQopICsNCiAgIyBQYWxldGEgZGUgY29sb3JlcyBwZXJzb25hbGl6YWRhDQogIGdncGxvdDI6OnNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjNTZCNEU5IiwgInJlZCIsICJncmVlbiIsICIjRDU1RTAwIikpICsNCiAgDQogICMgUGVyc29uYWxpemFjacOzbiBkZWwgdGVtYQ0KICBnZ3Bsb3QyOjp0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAwKSwgIyBRdWl0YSBlbCB0w610dWxvDQogICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgIyBUYW1hw7FvIGRlbCB0ZXh0byBkZSBsYSBsZXllbmRhDQogICAgYXhpcy50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSwgIyBUYW1hw7FvIHkgY29sb3IgZGVsIHRleHRvIGRlIGxvcyBlamVzDQogICAgYXhpcy50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpLCAjIFRhbWHDsW8gZGVsIHTDrXR1bG8gZGUgbG9zIGVqZXMNCiAgICBheGlzLnRpY2tzLmxlbmd0aCA9IGdncGxvdDI6OnVuaXQoNSwgInB0IiksICMgTG9uZ2l0dWQgZGUgbG9zIHRpY2tzDQogICAgYXhpcy50aWNrcyA9IGdncGxvdDI6OmVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIpLCAjIENvbG9yIGRlIGxvcyB0aWNrcw0KICAgIGF4aXMubGluZSA9IGdncGxvdDI6OmVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjUpLCAjIEzDrW5lYXMgZGUgbG9zIGVqZXMNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZ2dwbG90Mjo6ZWxlbWVudF9ibGFuaygpLCAjIEVsaW1pbmEgbGFzIGzDrW5lYXMgZGUgbGEgZ3JpbGxhIG1heW9yDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGdncGxvdDI6OmVsZW1lbnRfYmxhbmsoKSAgIyBFbGltaW5hIGxhcyBsw61uZWFzIGRlIGxhIGdyaWxsYSBtZW5vcg0KICApDQoNCmBgYA0KDQoNCiMgRGVzYXJyb2xsbyBkZSB1bmEgbWF0cml6IGRlIHJlc3B1ZXNhcyBiaW9sb2dpY2FzIGRlICpBLiBwdXJwdXJhdHVzKiBmcmVudGUgYSBsYSB0ZW1wZXJhdHVyYSBlIGhpcG94aWENCg0KYGBge3IgcHJlc3N1cmUsIGVjaG89RkFMU0UsIGZpZy5jYXA9IiIsIG91dC53aWR0aCA9ICc3MCUnfQ0KaW5jbHVkZV9ncmFwaGljcygiSW5kaWNlMS5wbmciKQ0KaW5jbHVkZV9ncmFwaGljcygiSW5kaWNlMi5wbmciKQ0KaW5jbHVkZV9ncmFwaGljcygiSW5kaWNlMy5wbmciKQ0KaW5jbHVkZV9ncmFwaGljcygiSW5kaWNlNC5wbmciKQ0KYGBgDQoNCioqQkFSUkFOQ09TIE1PUlRBTElEQUQgMjAxNSoqDQoNCmBgYHtyLCBlY2hvPVRSVUUsZmlnLndpZHRoPTgsICBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojIEFob3JhIGFzaWduYW1vcyBsYSBjYXRlZ29yaWEgZGUgVGVtcF9mb25kIHkgRE9fc2F0DQpkZl9pbmRpY2UgPC0gYmFycmFuY29zXzIwMTUNCg0KZGZfaW5kaWNlIDwtIGRmX2luZGljZSAlPiUNCiAgbXV0YXRlKA0KICAgIENhdGVnb3JpYV9UID0gY2FzZV93aGVuKA0KICAgICAgVGVtcF9mb25kIDw9IDE2IH4gIjw9MTYiLA0KICAgICAgVGVtcF9mb25kID4gMTYgJiBUZW1wX2ZvbmQgPD0gMjAgfiAiXTE2LTIwXSIsDQogICAgICBUZW1wX2ZvbmQgPiAyMCAmIFRlbXBfZm9uZCA8PSAyNSB+ICJdMjAtMjVdIiwNCiAgICAgIFRlbXBfZm9uZCA+IDI1ICYgVGVtcF9mb25kIDw9IDI5IH4gIl0yNS0yOV0iLA0KICAgICAgVGVtcF9mb25kID4gMjkgfiAiPjI5Ig0KICAgICksDQogICAgQ2F0ZWdvcmlhX0RPID0gY2FzZV93aGVuKA0KICAgICAgRE9fc2F0IDw9IDIgfiAiPD0yIiwNCiAgICAgIERPX3NhdCA+IDIgJiBET19zYXQgPD0gNSB+ICJdMi01XSIsDQogICAgICBET19zYXQgPiA1ICYgRE9fc2F0IDw9IDI0LjQgfiAiXTUtMjRdIiwNCiAgICAgIERPX3NhdCA+IDI0LjQgfiAiPjI0Ig0KICAgICksDQogICAgQ2F0ZWdvcmlhX3RvdGFsID0gcGFzdGUoQ2F0ZWdvcmlhX1QsIENhdGVnb3JpYV9ETywgc2VwID0gIjsiKQ0KICApDQoNCiMgSWRlbnRpZmljYXIgbG9zIGNhbWJpb3MgZW4gbGFzIGNhdGVnb3LDrWFzIGRlIENhdGVnb3JpYV90b3RhbCBkZW50cm8gZGUgY2FkYSBncm91cCANCmRmX2luZGljZSA8LSBkZl9pbmRpY2UgJT4lDQogIGdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgbXV0YXRlKGNoYW5nZSA9IENhdGVnb3JpYV90b3RhbCAhPSBsYWcoQ2F0ZWdvcmlhX3RvdGFsLCBkZWZhdWx0ID0gZmlyc3QoQ2F0ZWdvcmlhX3RvdGFsKSkpICU+JQ0KICBtdXRhdGUoZ3JvdXBfaWQgPSBjdW1zdW0oY2hhbmdlKSkgJT4lDQogIHVuZ3JvdXAgKCkNCg0KIyBDYWxjdWxhciBsYSBmZWNoYSBkZSBpbmljaW8geSBmaW4gZGUgY2FkYSBncnVwbyBkZSBjYXRlZ29yw61hcyBjb250aW51YXMNCmRmX2FncnVwYWRvIDwtIGRmX2luZGljZSAlPiUNCiAgZ3JvdXBfYnkoDQogICAgZ3JvdXAsDQogICAgZ3JvdXBfaWQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgZmVjaGFfaW5pY2lvID0gbWluKEhvcmFfTGltYSksDQogICAgZmVjaGFfZmluID0gbWF4KEhvcmFfTGltYSksDQogICAgZHVyYWNpb24gPSBhcy5udW1lcmljKGRpZmZ0aW1lKG1heChIb3JhX0xpbWEpLCBtaW4oSG9yYV9MaW1hKSwgdW5pdHMgPSAiaG91cnMiKSkrMSwNCiAgICBDYXRlZ29yaWFfdG90YWwgPSBmaXJzdChDYXRlZ29yaWFfdG90YWwpLA0KICAgIENhdGVnb3JpYV9ETyA9IGZpcnN0IChDYXRlZ29yaWFfRE8pKQ0KDQojIEFncmVnYXIgY29sdW1uYSBIaXBveGljbyBjb24gdmFsb3JlcyBIaXBveGlhIG8gTm9ybW94aWENCmRmX2FncnVwYWRvIDwtIGRmX2FncnVwYWRvICU+JQ0KIG11dGF0ZShIaXBveGlhID0gaWZlbHNlKENhdGVnb3JpYV9ETyAlaW4lIGMoIjw9MiIsICJdMi01XSIsIl01LTI0XSIpLCAiSGlwb3hpYSIsICJOb3Jtb3hpYSIpKSAjJT4lDQogICN1bmdyb3VwKCkgIyU+JSAjIEVsaW1pbmFyIGFncnVwYWNpb25lcyBhY3RpdmFzDQogICNzZWxlY3QoLWdyb3VwKQ0KDQojIENyZWFyIHVuYSBjb3BpYSBkZWwgZGF0YWZyYW1lIG9yaWdpbmFsDQpkZl9yZXN1bHRhZG8gPC0gZGZfYWdydXBhZG8NCg0KIyBJZGVudGlmaWNhciBwZXJpb2RvcyBtZW5vcmVzIGEgNiBob3Jhcw0KZGZfcmVzdWx0YWRvIDwtIGRmX3Jlc3VsdGFkbyAlPiUNCiAgbXV0YXRlKGlzX3Nob3J0ID0gZHVyYWNpb24gPCA2KQ0KDQojIFByb2Nlc2FyIGxvcyBibG9xdWVzDQpwcm9jZXNhcl9ibG9xdWVzIDwtIGZ1bmN0aW9uKGRmKSB7DQogIGJsb3F1ZV9pZCA8LSAxDQogIGRmIDwtIGRmICU+JQ0KICAgIG11dGF0ZShibG9xdWUgPSAwKSAgIyBJbmljaWFsaXphbW9zIGNvbiAwIHBhcmEgbG9zIGJsb3F1ZXMNCiAgDQogIGZvciAoaSBpbiAxOm5yb3coZGYpKSB7DQogICAgaWYgKGkgPT0gMSkgew0KICAgICAgIyBBc2lnbmFyIGVsIHByaW1lciBibG9xdWUNCiAgICAgIGRmJGJsb3F1ZVtpXSA8LSBibG9xdWVfaWQNCiAgICB9IGVsc2UgaWYgKGRmJGdyb3VwW2ldICE9IGRmJGdyb3VwW2kgLSAxXSkgew0KICAgICAgIyBTaSBjYW1iaWEgZWwgZ3J1cG8sIGNyZWFyIHVuIG51ZXZvIGJsb3F1ZQ0KICAgICAgYmxvcXVlX2lkIDwtIGJsb3F1ZV9pZCArIDENCiAgICAgIGRmJGJsb3F1ZVtpXSA8LSBibG9xdWVfaWQNCiAgICB9IGVsc2UgaWYgKGRmJGlzX3Nob3J0W2kgLSAxXSAmJiBkZiRpc19zaG9ydFtpXSkgew0KICAgICAgIyBTaSBlbCBwZXJpb2RvIGFjdHVhbCB5IGVsIGFudGVyaW9yIHNvbiBjb3J0b3MsIHBlcnRlbmVjZW4gYWwgbWlzbW8gYmxvcXVlDQogICAgICBkZiRibG9xdWVbaV0gPC0gYmxvcXVlX2lkDQogICAgfSBlbHNlIGlmIChkZiRpc19zaG9ydFtpIC0gMV0gJiYgIWRmJGlzX3Nob3J0W2ldKSB7DQogICAgICAjIFNpIGVsIHBlcmlvZG8gYW50ZXJpb3IgZXJhIGNvcnRvIHBlcm8gZXN0ZSBubywgdmVyaWZpY2Ftb3MgbGEgZHVyYWNpw7NuIGFjdW11bGFkYQ0KICAgICAgYmxvcXVlX2R1cmFjaW9uIDwtIHN1bShkZiRkdXJhY2lvbltkZiRibG9xdWUgPT0gYmxvcXVlX2lkXSkNCiAgICAgIGlmIChibG9xdWVfZHVyYWNpb24gPCA2KSB7DQogICAgICAgICMgVsOtYSBCOiBJZ25vcmFyIGxhIGludGVycnVwY2nDs24geSBleHRlbmRlciBlbCBibG9xdWUgYWwgc2lndWllbnRlDQogICAgICAgIGRmJGJsb3F1ZVtpXSA8LSBibG9xdWVfaWQNCiAgICAgIH0gZWxzZSB7DQogICAgICAgICMgVsOtYSBBOiBDcmVhciB1biBudWV2byBibG9xdWUNCiAgICAgICAgYmxvcXVlX2lkIDwtIGJsb3F1ZV9pZCArIDENCiAgICAgICAgZGYkYmxvcXVlW2ldIDwtIGJsb3F1ZV9pZA0KICAgICAgfQ0KICAgIH0gZWxzZSB7DQogICAgICAjIENyZWFyIHVuIG51ZXZvIGJsb3F1ZQ0KICAgICAgYmxvcXVlX2lkIDwtIGJsb3F1ZV9pZCArIDENCiAgICAgIGRmJGJsb3F1ZVtpXSA8LSBibG9xdWVfaWQNCiAgICB9DQogIH0NCiAgDQogIHJldHVybihkZikNCn0NCg0KZGZfcmVzdWx0YWRvIDwtIHByb2Nlc2FyX2Jsb3F1ZXMoZGZfcmVzdWx0YWRvKQ0KDQojIENhbGN1bGFyIHJlc3VsdGFkb3MgZmluYWxlcyBwb3IgYmxvcXVlDQpkZl9maW5hbCA8LSBkZl9yZXN1bHRhZG8gJT4lDQogIGdyb3VwX2J5KGJsb3F1ZSwgZ3JvdXApICU+JQ0KICBzdW1tYXJpemUoDQogICAgZmVjaGFfaW5pY2lvID0gbWluKGZlY2hhX2luaWNpbyksDQogICAgZmVjaGFfZmluID0gbWF4KGZlY2hhX2ZpbiksDQogICAgZHVyYWNpb25fdG90YWwgPSBzdW0oZHVyYWNpb24pLA0KICAgIENhdGVnb3JpYV90b3RhbCA9IENhdGVnb3JpYV90b3RhbFt3aGljaC5tYXgoZHVyYWNpb24pXSwNCiAgICBDYXRlZ29yaWFfRE8gPSBDYXRlZ29yaWFfRE9bd2hpY2gubWF4KGR1cmFjaW9uKV0NCiAgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgQWdydXBhciBwb3IgYmxvcXVlcyBjb25zZWN1dGl2b3MgY29uIGVsIG1pc21vIENhdGVnb3JpYV90b3RhbA0KZGZfY29uc29saWRhZG8gPC0gZGZfZmluYWwgJT4lDQogIG11dGF0ZSgNCiAgICBncnVwb19jYXRlZ29yaWEgPSBjdW1zdW0oQ2F0ZWdvcmlhX3RvdGFsICE9IGxhZyhDYXRlZ29yaWFfdG90YWwsIGRlZmF1bHQgPSBmaXJzdChDYXRlZ29yaWFfdG90YWwpKSkNCiAgKSAlPiUNCiAgZ3JvdXBfYnkoZ3J1cG9fY2F0ZWdvcmlhLGdyb3VwKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIGZlY2hhX2luaWNpbyA9IG1pbihmZWNoYV9pbmljaW8pLA0KICAgIGZlY2hhX2ZpbiA9IG1heChmZWNoYV9maW4pLA0KICAgIGR1cmFjaW9uID0gc3VtKGR1cmFjaW9uX3RvdGFsKSwNCiAgICBDYXRlZ29yaWFfdG90YWwgPSBmaXJzdChDYXRlZ29yaWFfdG90YWwpLA0KICAgIENhdGVnb3JpYV9ETyA9IGZpcnN0KENhdGVnb3JpYV9ETykgIyBDb25zaWRlcmFtb3MgbGEgbWlzbWEgbMOzZ2ljYSBwYXJhIENhdGVnb3JpYV9ETw0KICApICU+JQ0KICB1bmdyb3VwKCkNCg0KDQojIEFzaWduYXIgbGFzIGNhdGVnb3JpYXMNCmRmX2NvbnNvbGlkYWRvIDwtIGRmX2NvbnNvbGlkYWRvICU+JQ0KICBtdXRhdGUoDQogICAgSW5kaWNlID0gY2FzZV93aGVuKA0KICAgICAgZHVyYWNpb24gPCAxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjs+MjQiIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA8IDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2O101LTI0XSIgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2O10yLTVdIn4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSI8PTE2Ozw9MiIgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdO101LTI0XSIgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09Il0xNi0yMF07XTItNV0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTs8PTIiIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTs+MjQiIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA8MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTUtMjRdIn4iRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdO10yLTVdIiB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PD0yIiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiMjUtMjldOz4yNCIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uIDwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdNS0yNF0ifiJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07XTItNV0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTs8PTIiIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7PjI0IiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA8MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTs1LTI0XSJ+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbD09ICI+Mjk7XTItNV0iIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7PD0yIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2O101LTI0XSIgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTItNV0iICB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjs8PTIiICB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07XTUtMjRdIiAgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTtdMi01XSIgIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07PD0yIiAgfiAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdOz4yNCIgIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTUtMjRdIiAgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTtdMi01XSIgIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PD0yIiAgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldOz4yNCIgICB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICZDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07XTUtMjRdIiAgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdMi01XSIgICB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldOzw9MiIgIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5Oz4yNCIgIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5OzUtMjRdIiAgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7XTItNV0iICB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgID09ICI+Mjk7PD0yIiAgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Oz4yNCIgIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTUtMjRdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2O10yLTVdIiAgfiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjs8PTIiIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTs+MjQiIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07XTUtMjRdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdO10yLTVdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOzw9MiIgIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTs+MjQiIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTUtMjRdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdO10yLTVdIiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PD0yIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07PjI0IiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07XTUtMjRdIiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07XTItNV0iIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5Oz4yNCJ+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTs1LTI0XSJ+IkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5O10yLTVdIn4iTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7PD0yIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Oz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTUtMjRdIiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2O10yLTVdIiB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Ozw9MiIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTtdNS0yNF0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdO10yLTVdIiB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdO101LTI0XSIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTItNV0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdOzw9MiIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTs+MjQiIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07XTUtMjRdIiB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdMi01XSIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5Oz4yNCIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5OzUtMjRdIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7XTItNV0iIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49MTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Oz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49MTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49MTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIFRSVUUgfiAiU2luIGluZm9ybWFjaW9uIg0KICAgICkNCiAgKQ0KDQojIE9yZGVuYXIgZWwgZGF0YWZyYW1lIHBvciBmZWNoYSBkZSBpbmljaW8NCmRmX2NvbnNvbGlkYWRvIDwtIGRmX2NvbnNvbGlkYWRvICU+JSBhcnJhbmdlKGZlY2hhX2luaWNpbykNCg0KIyBDb252ZXJ0aXIgbGFzIGNvbHVtbmFzIGRlIGZlY2hhIGEgUE9TSVhjdCBzaSBubyBsbyBlc3TDoW4NCmRmX2NvbnNvbGlkYWRvJGZlY2hhX2luaWNpbyA8LSBhcy5QT1NJWGN0KGRmX2NvbnNvbGlkYWRvJGZlY2hhX2luaWNpbywgdHo9IlVUQyIpDQpkZl9jb25zb2xpZGFkbyRmZWNoYV9maW4gPC0gYXMuUE9TSVhjdChkZl9jb25zb2xpZGFkbyRmZWNoYV9maW4sIHR6PSJVVEMiKQ0KDQojRnVuY2nDs24gcGFyYSBjYWxjdWxhciBlbCBwdW50byBtZWRpbyBkZSB1biBpbnRlcnZhbG8gZGUgZmVjaGFzDQppbnRlcnZhbF9taWRwb2ludCA8LSBmdW5jdGlvbihzdGFydCwgZW5kKSB7DQogIHJldHVybihzdGFydCArIChlbmQgLSBzdGFydCkgLyAyKQ0KfQ0KDQojIEFncmVnYXIgbGEgY29sdW1uYSBIb3JhX0xpbWEgYSBkZl9hZ3J1cGFkbyB1c2FuZG8gaW50ZXJ2YWxfbWlkcG9pbnQNCmRmX2NvbnNvbGlkYWRvIDwtIGRmX2NvbnNvbGlkYWRvICU+JQ0KICBtdXRhdGUoSG9yYV9MaW1hID0gaW50ZXJ2YWxfbWlkcG9pbnQoZmVjaGFfaW5pY2lvLCBmZWNoYV9maW4pKQ0KDQojIERlZmluaXIgbG9zIGNvbG9yZXMgZGUgbGFzIGNhdGVnb3LDrWFzDQpjb2xvcmVzX2NhdGVnb3JpYXMgPC0gYygiTGV0YWwiID0gIiM4MDAwMDAiLCAgIyBSb2pvIG9zY3Vybw0KICAgICAgICAgICAgICAgICAgICAgICAgIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiA9ICJyZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIkVzdHJlcyBmaXNpb2xvZ2ljbyIgPSAib3JhbmdlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJJbm9jdW8iID0gImdyZWVuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJTaW4gaW5mb3JtYWNpb24iID0gImdyZXkiKQ0KDQoNCmdncGxvdCgpICsNCiAgIyBDYXBhIDE6IGZvbmRvIGNvbiByZWN0w6FuZ3Vsb3MgZGUgZGZfY29uc29saWRhZG8NCiAgZ2VvbV9yZWN0KA0KICAgIGRhdGEgPSBkZl9jb25zb2xpZGFkbywNCiAgICBhZXMoDQogICAgICB4bWluID0gYXMuUE9TSVhjdChmZWNoYV9pbmljaW8sIHR6ID0gIlVUQyIpLA0KICAgICAgeG1heCA9IGFzLlBPU0lYY3QoZmVjaGFfZmluLCB0eiA9ICJVVEMiKSwNCiAgICAgIHltaW4gPSAtSW5mLA0KICAgICAgeW1heCA9IEluZiwNCiAgICAgIGZpbGwgPSBJbmRpY2UNCiAgICApLA0KICAgIGFscGhhID0gMC44LA0KICAgIGNvbG9yID0gTkENCiAgKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfY2F0ZWdvcmlhcykgKw0KICANCiAgIyBDYXBhIDI6IGzDrW5lYXMgZGUgYmFycmFuY29zXzIwMTUgY29uIGFncnVwYWNpw7NuDQogIGdlb21fbGluZSgNCiAgICBkYXRhID0gYmFycmFuY29zXzIwMTUsDQogICAgYWVzKHggPSBIb3JhX0xpbWEsIHkgPSBET19zYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgIGNvbG9yID0gImJsYWNrIg0KICApICsNCiAgDQogICMgQ2FwYSAzOiBwdW50byBjcsOtdGljbyBkZSBveMOtZ2Vubw0KICBnZW9tX3RleHQoDQogICAgZGF0YSA9IGRhdGEuZnJhbWUoDQogICAgICB4ID0gYXMuUE9TSVhjdCgiMjAxNS0wMS0xNSIsIHR6ID0gIlVUQyIpLA0KICAgICAgeSA9IDI3LA0KICAgICAgbGFiZWwgPSAiUHVudG8gY3LDrXRpY28gZGUgb3jDrWdlbm8iDQogICAgKSwNCiAgICBhZXMoeCA9IHgsIHkgPSB5LCBsYWJlbCA9IGxhYmVsKSwNCiAgICBjb2xvciA9ICJyZWQiLA0KICAgIHNpemUgPSAzLjUNCiAgKSArDQogIA0KICAjIENhcGEgNDogbMOtbmVhIGhvcml6b250YWwgY3LDrXRpY2ENCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMjQsIGNvbG9yID0gInJlZCIpICsNCiAgDQogICMgVGVtYSB5IHBlcnNvbmFsaXphY2nDs24NCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfeF9kYXRldGltZShicmVha3MgPSAiMSB3ZWVrIiwgZGF0ZV9sYWJlbHMgPSAiJWQvJWIiKSArDQogIGxhYnMoeCA9ICIiLCB5ID0gIlNhdHVyYWNpw7NuIGRlIG94w61nZW5vICglKSIsIHRpdGxlID0gIk1vcnRhbGlkYWQgMjAxNSAtIEJhcnJhbmNvcyIpICsNCiAgdGhlbWUoDQogICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImJsYWNrIiksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsDQogICAgYXhpcy50aWNrcy5sZW5ndGggPSB1bml0KDUsICJwdCIpLCAjIExvbmdpdHVkIGRlIGxvcyB0aWNrcw0KICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIpLCAjIENvbG9yIGRlIGxvcyB0aWNrcyBYDQogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiksICAjIENvbG9yIGRlIGxvcyB0aWNrcyBZDQogICAgYXhpcy5saW5lLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC41KSwgIyBMw61uZWEgaG9yaXpvbnRhbCBkZWwgZWplDQogICAgYXhpcy5saW5lLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC41KSAgIyBMw61uZWEgdmVydGljYWwgZGVsIGVqZQ0KICApICsNCiAgDQogICMgQW5vdGFjaW9uZXMgYWRpY2lvbmFsZXMNCiAgYW5ub3RhdGUoDQogICAgInJlY3QiLA0KICAgIHhtaW4gPSBhcy5QT1NJWGN0KCIyMDE1LTAzLTAyIiwgdHogPSAiVVRDIiksDQogICAgeG1heCA9IGFzLlBPU0lYY3QoIjIwMTUtMDMtMTUiLCB0eiA9ICJVVEMiKSwNCiAgICB5bWluID0gLUluZiwNCiAgICB5bWF4ID0gSW5mLA0KICAgIGFscGhhID0gMCwNCiAgICBjb2xvciA9ICIjNjM2MzYzIiwNCiAgICBzaXplID0gMC43LA0KICAgIGxpbmV0eXBlID0gImRhc2hlZCINCiAgKSArDQogIGdlb21fdGV4dCgNCiAgICBkYXRhID0gZGF0YS5mcmFtZSgNCiAgICAgIHggPSBhcy5QT1NJWGN0KCIyMDE1LTAzLTA5IiwgdHogPSAiVVRDIiksDQogICAgICB5ID0gOTgsDQogICAgICBsYWJlbCA9ICJNb3J0YWxpZGFkIg0KICAgICksDQogICAgYWVzKHggPSB4LCB5ID0geSwgbGFiZWwgPSBsYWJlbCksDQogICAgY29sb3IgPSAiIzYzNjM2MyIsDQogICAgc2l6ZSA9IDQNCiAgKQ0KDQpgYGANCg0KKipDT05TVEFOVEUgTU9SVEFMSURBRCAyMDE5KioNCg0KYGBge3IsIGVjaG89VFJVRSxmaWcud2lkdGg9OCwgIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiMgQWhvcmEgYXNpZ25hbW9zIGxhIGNhdGVnb3JpYSBkZSBUZW1wX2ZvbmQgeSBET19zYXQNCmRmX2luZGljZSA8LSBjb25zdGFudGVfMjAxOQ0KDQpkZl9pbmRpY2UgPC0gZGZfaW5kaWNlICU+JQ0KICBtdXRhdGUoDQogICAgQ2F0ZWdvcmlhX1QgPSBjYXNlX3doZW4oDQogICAgICBUZW1wX2ZvbmQgPD0gMTYgfiAiPD0xNiIsDQogICAgICBUZW1wX2ZvbmQgPiAxNiAmIFRlbXBfZm9uZCA8PSAyMCB+ICJdMTYtMjBdIiwNCiAgICAgIFRlbXBfZm9uZCA+IDIwICYgVGVtcF9mb25kIDw9IDI1IH4gIl0yMC0yNV0iLA0KICAgICAgVGVtcF9mb25kID4gMjUgJiBUZW1wX2ZvbmQgPD0gMjkgfiAiXTI1LTI5XSIsDQogICAgICBUZW1wX2ZvbmQgPiAyOSB+ICI+MjkiDQogICAgKSwNCiAgICBDYXRlZ29yaWFfRE8gPSBjYXNlX3doZW4oDQogICAgICBET19zYXQgPD0gMiB+ICI8PTIiLA0KICAgICAgRE9fc2F0ID4gMiAmIERPX3NhdCA8PSA1IH4gIl0yLTVdIiwNCiAgICAgIERPX3NhdCA+IDUgJiBET19zYXQgPD0gMjQuNCB+ICJdNS0yNF0iLA0KICAgICAgRE9fc2F0ID4gMjQuNCB+ICI+MjQiDQogICAgKSwNCiAgICBDYXRlZ29yaWFfdG90YWwgPSBwYXN0ZShDYXRlZ29yaWFfVCwgQ2F0ZWdvcmlhX0RPLCBzZXAgPSAiOyIpDQogICkNCg0KIyBJZGVudGlmaWNhciBsb3MgY2FtYmlvcyBlbiBsYXMgY2F0ZWdvcsOtYXMgZGUgQ2F0ZWdvcmlhX3RvdGFsIGRlbnRybyBkZSBjYWRhIGdyb3VwIA0KZGZfaW5kaWNlIDwtIGRmX2luZGljZSAlPiUNCiAgZ3JvdXBfYnkoZ3JvdXApICU+JQ0KICBtdXRhdGUoY2hhbmdlID0gQ2F0ZWdvcmlhX3RvdGFsICE9IGxhZyhDYXRlZ29yaWFfdG90YWwsIGRlZmF1bHQgPSBmaXJzdChDYXRlZ29yaWFfdG90YWwpKSkgJT4lDQogIG11dGF0ZShncm91cF9pZCA9IGN1bXN1bShjaGFuZ2UpKSAlPiUNCiAgdW5ncm91cCAoKQ0KDQojIENhbGN1bGFyIGxhIGZlY2hhIGRlIGluaWNpbyB5IGZpbiBkZSBjYWRhIGdydXBvIGRlIGNhdGVnb3LDrWFzIGNvbnRpbnVhcw0KZGZfYWdydXBhZG8gPC0gZGZfaW5kaWNlICU+JQ0KICBncm91cF9ieSgNCiAgICBncm91cCwNCiAgICBncm91cF9pZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBmZWNoYV9pbmljaW8gPSBtaW4oSG9yYV9MaW1hKSwNCiAgICBmZWNoYV9maW4gPSBtYXgoSG9yYV9MaW1hKSwNCiAgICBkdXJhY2lvbiA9IGFzLm51bWVyaWMoZGlmZnRpbWUobWF4KEhvcmFfTGltYSksIG1pbihIb3JhX0xpbWEpLCB1bml0cyA9ICJob3VycyIpKSsxLA0KICAgIENhdGVnb3JpYV90b3RhbCA9IGZpcnN0KENhdGVnb3JpYV90b3RhbCksDQogICAgQ2F0ZWdvcmlhX0RPID0gZmlyc3QgKENhdGVnb3JpYV9ETykpDQoNCiMgQWdyZWdhciBjb2x1bW5hIEhpcG94aWNvIGNvbiB2YWxvcmVzIEhpcG94aWEgbyBOb3Jtb3hpYQ0KZGZfYWdydXBhZG8gPC0gZGZfYWdydXBhZG8gJT4lDQogbXV0YXRlKEhpcG94aWEgPSBpZmVsc2UoQ2F0ZWdvcmlhX0RPICVpbiUgYygiPD0yIiwgIl0yLTVdIiwiXTUtMjRdIiksICJIaXBveGlhIiwgIk5vcm1veGlhIikpICMlPiUNCiAgI3VuZ3JvdXAoKSAjJT4lICMgRWxpbWluYXIgYWdydXBhY2lvbmVzIGFjdGl2YXMNCiAgI3NlbGVjdCgtZ3JvdXApDQoNCiMgQ3JlYXIgdW5hIGNvcGlhIGRlbCBkYXRhZnJhbWUgb3JpZ2luYWwNCmRmX3Jlc3VsdGFkbyA8LSBkZl9hZ3J1cGFkbw0KDQojIElkZW50aWZpY2FyIHBlcmlvZG9zIG1lbm9yZXMgYSA2IGhvcmFzDQpkZl9yZXN1bHRhZG8gPC0gZGZfcmVzdWx0YWRvICU+JQ0KICBtdXRhdGUoaXNfc2hvcnQgPSBkdXJhY2lvbiA8IDYpDQoNCiMgUHJvY2VzYXIgbG9zIGJsb3F1ZXMNCnByb2Nlc2FyX2Jsb3F1ZXMgPC0gZnVuY3Rpb24oZGYpIHsNCiAgYmxvcXVlX2lkIDwtIDENCiAgZGYgPC0gZGYgJT4lDQogICAgbXV0YXRlKGJsb3F1ZSA9IDApICAjIEluaWNpYWxpemFtb3MgY29uIDAgcGFyYSBsb3MgYmxvcXVlcw0KICANCiAgZm9yIChpIGluIDE6bnJvdyhkZikpIHsNCiAgICBpZiAoaSA9PSAxKSB7DQogICAgICAjIEFzaWduYXIgZWwgcHJpbWVyIGJsb3F1ZQ0KICAgICAgZGYkYmxvcXVlW2ldIDwtIGJsb3F1ZV9pZA0KICAgIH0gZWxzZSBpZiAoZGYkZ3JvdXBbaV0gIT0gZGYkZ3JvdXBbaSAtIDFdKSB7DQogICAgICAjIFNpIGNhbWJpYSBlbCBncnVwbywgY3JlYXIgdW4gbnVldm8gYmxvcXVlDQogICAgICBibG9xdWVfaWQgPC0gYmxvcXVlX2lkICsgMQ0KICAgICAgZGYkYmxvcXVlW2ldIDwtIGJsb3F1ZV9pZA0KICAgIH0gZWxzZSBpZiAoZGYkaXNfc2hvcnRbaSAtIDFdICYmIGRmJGlzX3Nob3J0W2ldKSB7DQogICAgICAjIFNpIGVsIHBlcmlvZG8gYWN0dWFsIHkgZWwgYW50ZXJpb3Igc29uIGNvcnRvcywgcGVydGVuZWNlbiBhbCBtaXNtbyBibG9xdWUNCiAgICAgIGRmJGJsb3F1ZVtpXSA8LSBibG9xdWVfaWQNCiAgICB9IGVsc2UgaWYgKGRmJGlzX3Nob3J0W2kgLSAxXSAmJiAhZGYkaXNfc2hvcnRbaV0pIHsNCiAgICAgICMgU2kgZWwgcGVyaW9kbyBhbnRlcmlvciBlcmEgY29ydG8gcGVybyBlc3RlIG5vLCB2ZXJpZmljYW1vcyBsYSBkdXJhY2nDs24gYWN1bXVsYWRhDQogICAgICBibG9xdWVfZHVyYWNpb24gPC0gc3VtKGRmJGR1cmFjaW9uW2RmJGJsb3F1ZSA9PSBibG9xdWVfaWRdKQ0KICAgICAgaWYgKGJsb3F1ZV9kdXJhY2lvbiA8IDYpIHsNCiAgICAgICAgIyBWw61hIEI6IElnbm9yYXIgbGEgaW50ZXJydXBjacOzbiB5IGV4dGVuZGVyIGVsIGJsb3F1ZSBhbCBzaWd1aWVudGUNCiAgICAgICAgZGYkYmxvcXVlW2ldIDwtIGJsb3F1ZV9pZA0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgIyBWw61hIEE6IENyZWFyIHVuIG51ZXZvIGJsb3F1ZQ0KICAgICAgICBibG9xdWVfaWQgPC0gYmxvcXVlX2lkICsgMQ0KICAgICAgICBkZiRibG9xdWVbaV0gPC0gYmxvcXVlX2lkDQogICAgICB9DQogICAgfSBlbHNlIHsNCiAgICAgICMgQ3JlYXIgdW4gbnVldm8gYmxvcXVlDQogICAgICBibG9xdWVfaWQgPC0gYmxvcXVlX2lkICsgMQ0KICAgICAgZGYkYmxvcXVlW2ldIDwtIGJsb3F1ZV9pZA0KICAgIH0NCiAgfQ0KICANCiAgcmV0dXJuKGRmKQ0KfQ0KDQpkZl9yZXN1bHRhZG8gPC0gcHJvY2VzYXJfYmxvcXVlcyhkZl9yZXN1bHRhZG8pDQoNCiMgQ2FsY3VsYXIgcmVzdWx0YWRvcyBmaW5hbGVzIHBvciBibG9xdWUNCmRmX2ZpbmFsIDwtIGRmX3Jlc3VsdGFkbyAlPiUNCiAgZ3JvdXBfYnkoYmxvcXVlLCBncm91cCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBmZWNoYV9pbmljaW8gPSBtaW4oZmVjaGFfaW5pY2lvKSwNCiAgICBmZWNoYV9maW4gPSBtYXgoZmVjaGFfZmluKSwNCiAgICBkdXJhY2lvbl90b3RhbCA9IHN1bShkdXJhY2lvbiksDQogICAgQ2F0ZWdvcmlhX3RvdGFsID0gQ2F0ZWdvcmlhX3RvdGFsW3doaWNoLm1heChkdXJhY2lvbildLA0KICAgIENhdGVnb3JpYV9ETyA9IENhdGVnb3JpYV9ET1t3aGljaC5tYXgoZHVyYWNpb24pXQ0KICApICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBBZ3J1cGFyIHBvciBibG9xdWVzIGNvbnNlY3V0aXZvcyBjb24gZWwgbWlzbW8gQ2F0ZWdvcmlhX3RvdGFsDQpkZl9jb25zb2xpZGFkbyA8LSBkZl9maW5hbCAlPiUNCiAgbXV0YXRlKA0KICAgIGdydXBvX2NhdGVnb3JpYSA9IGN1bXN1bShDYXRlZ29yaWFfdG90YWwgIT0gbGFnKENhdGVnb3JpYV90b3RhbCwgZGVmYXVsdCA9IGZpcnN0KENhdGVnb3JpYV90b3RhbCkpKQ0KICApICU+JQ0KICBncm91cF9ieShncnVwb19jYXRlZ29yaWEsZ3JvdXApICU+JQ0KICBzdW1tYXJpemUoDQogICAgZmVjaGFfaW5pY2lvID0gbWluKGZlY2hhX2luaWNpbyksDQogICAgZmVjaGFfZmluID0gbWF4KGZlY2hhX2ZpbiksDQogICAgZHVyYWNpb24gPSBzdW0oZHVyYWNpb25fdG90YWwpLA0KICAgIENhdGVnb3JpYV90b3RhbCA9IGZpcnN0KENhdGVnb3JpYV90b3RhbCksDQogICAgQ2F0ZWdvcmlhX0RPID0gZmlyc3QoQ2F0ZWdvcmlhX0RPKSAjIENvbnNpZGVyYW1vcyBsYSBtaXNtYSBsw7NnaWNhIHBhcmEgQ2F0ZWdvcmlhX0RPDQogICkgJT4lDQogIHVuZ3JvdXAoKQ0KDQoNCiMgQXNpZ25hciBsYXMgY2F0ZWdvcmlhcw0KZGZfY29uc29saWRhZG8gPC0gZGZfY29uc29saWRhZG8gJT4lDQogIG11dGF0ZSgNCiAgICBJbmRpY2UgPSBjYXNlX3doZW4oDQogICAgICBkdXJhY2lvbiA8IDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Oz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uIDwgMTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTUtMjRdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTItNV0ifiAiRXN0cmVzIGZpc2lvbG9naWNvIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09Ijw9MTY7PD0yIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07XTUtMjRdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0iXTE2LTIwXTtdMi01XSIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOzw9MiIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uIDwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTtdNS0yNF0ifiJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTItNV0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTs8PTIiIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICIyNS0yOV07PjI0IiB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldO101LTI0XSJ+IlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbjwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdMi01XSIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldOzw9MiIgfiAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTs+MjQiIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uIDwxMiAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5OzUtMjRdIn4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uPDEyICYgQ2F0ZWdvcmlhX3RvdGFsPT0gIj4yOTtdMi01XSIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb248MTIgJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjs+MjQiIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTUtMjRdIiB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjtdMi01XSIgIH4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Ozw9MiIgIH4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTtdNS0yNF0iICB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdO10yLTVdIiAgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTs8PTIiICB+ICJQcm9iYWJpbGlkYWQgZGUgbW9ydGFsaWRhZCIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PjI0IiAgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTtdNS0yNF0iICB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdO10yLTVdIiAgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTs8PTIiICB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07PjI0IiAgIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJkNhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdNS0yNF0iICB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldO10yLTVdIiAgIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yNS0yOV07PD0yIiAgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7PjI0IiAgfiAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiLA0KICAgICAgZHVyYWNpb24gPj0gMTIgJiBkdXJhY2lvbiA8IDI0ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7NS0yNF0iICB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAxMiAmIGR1cmFjaW9uIDwgMjQgJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTtdMi01XSIgIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDEyICYgZHVyYWNpb24gPCAyNCAmIENhdGVnb3JpYV90b3RhbCAgPT0gIj4yOTs8PTIiICB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7PjI0IiAgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjtdNS0yNF0iIH4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTItNV0iICB+ICJFc3RyZXMgZmlzaW9sb2dpY28iLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI8PTE2Ozw9MiIgfiAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTE2LTIwXTtdNS0yNF0iIH4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07XTItNV0iIH4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07PD0yIiAgfiAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjAtMjVdOz4yNCIgfiAiSW5vY3VvIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTtdNS0yNF0iIH4gIkVzdHJlcyBmaXNpb2xvZ2ljbyIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTItNV0iIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTs+MjQiIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdNS0yNF0iIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdMi01XSIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldOzw9MiIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7PjI0In4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDI0ICYgZHVyYWNpb24gPCA0OCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5OzUtMjRdIn4iTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gMjQgJiBkdXJhY2lvbiA8IDQ4ICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7XTItNV0ifiJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSAyNCAmIGR1cmFjaW9uIDwgNDggJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTs8PTIiIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPD0xNjtdNS0yNF0iIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7XTItNV0iIH4gIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7PD0yIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdO101LTI0XSIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07XTItNV0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMTYtMjBdOzw9MiIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTs+MjQiIH4gIklub2N1byIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07XTUtMjRdIiB+ICJTaW4gaW5mb3JtYWNpb24iLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTIwLTI1XTtdMi01XSIgfiAiU2luIGluZm9ybWFjaW9uIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PD0yIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldOz4yNCIgfiAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiXTI1LTI5XTtdNS0yNF0iIH4gIlNpbiBpbmZvcm1hY2lvbiIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldO10yLTVdIiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICJdMjUtMjldOzw9MiIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7PjI0IiB+ICJMZXRhbCIsDQogICAgICBkdXJhY2lvbiA+PSA0OCAmIGR1cmFjaW9uIDwgMTIwICYgQ2F0ZWdvcmlhX3RvdGFsID09ICI+Mjk7NS0yNF0iIH4gIkxldGFsIiwNCiAgICAgIGR1cmFjaW9uID49IDQ4ICYgZHVyYWNpb24gPCAxMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIj4yOTtdMi01XSIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0gNDggJiBkdXJhY2lvbiA8IDEyMCAmIENhdGVnb3JpYV90b3RhbCA9PSAiPjI5Ozw9MiIgfiAiTGV0YWwiLA0KICAgICAgZHVyYWNpb24gPj0xMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIjw9MTY7PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0xMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0xNi0yMF07PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgZHVyYWNpb24gPj0xMjAgJiBDYXRlZ29yaWFfdG90YWwgPT0gIl0yMC0yNV07PjI0IiB+ICJJbm9jdW8iLA0KICAgICAgVFJVRSB+ICJTaW4gaW5mb3JtYWNpb24iDQogICAgKQ0KICApDQoNCiMgT3JkZW5hciBlbCBkYXRhZnJhbWUgcG9yIGZlY2hhIGRlIGluaWNpbw0KZGZfY29uc29saWRhZG8gPC0gZGZfY29uc29saWRhZG8gJT4lIGFycmFuZ2UoZmVjaGFfaW5pY2lvKQ0KDQojIENvbnZlcnRpciBsYXMgY29sdW1uYXMgZGUgZmVjaGEgYSBQT1NJWGN0IHNpIG5vIGxvIGVzdMOhbg0KZGZfY29uc29saWRhZG8kZmVjaGFfaW5pY2lvIDwtIGFzLlBPU0lYY3QoZGZfY29uc29saWRhZG8kZmVjaGFfaW5pY2lvLCB0ej0iVVRDIikNCmRmX2NvbnNvbGlkYWRvJGZlY2hhX2ZpbiA8LSBhcy5QT1NJWGN0KGRmX2NvbnNvbGlkYWRvJGZlY2hhX2ZpbiwgdHo9IlVUQyIpDQoNCiNGdW5jacOzbiBwYXJhIGNhbGN1bGFyIGVsIHB1bnRvIG1lZGlvIGRlIHVuIGludGVydmFsbyBkZSBmZWNoYXMNCmludGVydmFsX21pZHBvaW50IDwtIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHsNCiAgcmV0dXJuKHN0YXJ0ICsgKGVuZCAtIHN0YXJ0KSAvIDIpDQp9DQoNCiMgQWdyZWdhciBsYSBjb2x1bW5hIEhvcmFfTGltYSBhIGRmX2FncnVwYWRvIHVzYW5kbyBpbnRlcnZhbF9taWRwb2ludA0KZGZfY29uc29saWRhZG8gPC0gZGZfY29uc29saWRhZG8gJT4lDQogIG11dGF0ZShIb3JhX0xpbWEgPSBpbnRlcnZhbF9taWRwb2ludChmZWNoYV9pbmljaW8sIGZlY2hhX2ZpbikpDQoNCiMgRGVmaW5pciBsb3MgY29sb3JlcyBkZSBsYXMgY2F0ZWdvcsOtYXMNCmNvbG9yZXNfY2F0ZWdvcmlhcyA8LSBjKCJMZXRhbCIgPSAiIzgwMDAwMCIsICAjIFJvam8gb3NjdXJvDQogICAgICAgICAgICAgICAgICAgICAgICAiUHJvYmFiaWxpZGFkIGRlIG1vcnRhbGlkYWQiID0gInJlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAiRXN0cmVzIGZpc2lvbG9naWNvIiA9ICJvcmFuZ2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIklub2N1byIgPSAiZ3JlZW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgIlNpbiBpbmZvcm1hY2lvbiIgPSAiZ3JleSIpDQoNCmRmX2NvbnNvbGlkYWRvIDwtIGRmX2NvbnNvbGlkYWRvICU+JQ0KICBtdXRhdGUoZmVjaGFfZmluID0gZmVjaGFfZmluIC0gbWljcm9zZWNvbmRzKDEpKSAgIyBSZXN0YW1vcyAxIHNlZ3VuZG8gcGFyYSBxdWUgZmVjaGFfZmluIHNlYSBpbmNsdXNpdmENCg0KZ2dwbG90KCkgKw0KICAjIENhcGEgMTogZm9uZG8gY29uIHJlY3TDoW5ndWxvcyBkZSBkZl9jb25zb2xpZGFkbw0KICBnZW9tX3JlY3QoDQogICAgZGF0YSA9IGRmX2NvbnNvbGlkYWRvLA0KICAgIGFlcygNCiAgICAgIHhtaW4gPSBhcy5QT1NJWGN0KGZlY2hhX2luaWNpbywgdHogPSAiVVRDIiksDQogICAgICB4bWF4ID0gYXMuUE9TSVhjdChmZWNoYV9maW4sIHR6ID0gIlVUQyIpLA0KICAgICAgeW1pbiA9IC1JbmYsDQogICAgICB5bWF4ID0gSW5mLA0KICAgICAgZmlsbCA9IEluZGljZQ0KICAgICksDQogICAgYWxwaGEgPSAwLjgsDQogICAgY29sb3IgPSBOQQ0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3Jlc19jYXRlZ29yaWFzKSArDQogIA0KICAjIENhcGEgMjogbMOtbmVhcyBkZSBjb25zdG5hdGVfMjAxOSBjb24gYWdydXBhY2nDs24NCiAgZ2VvbV9saW5lKA0KICAgIGRhdGEgPSBjb25zdGFudGVfMjAxOSwNCiAgICBhZXMoeCA9IEhvcmFfTGltYSwgeSA9IERPX3NhdCwgZ3JvdXAgPSBncm91cCksDQogICAgY29sb3IgPSAiYmxhY2siDQogICkgKw0KICANCiAgIyBDYXBhIDM6IHB1bnRvIGNyw610aWNvIGRlIG94w61nZW5vDQogIGdlb21fdGV4dCgNCiAgICBkYXRhID0gZGF0YS5mcmFtZSgNCiAgICAgIHggPSBhcy5QT1NJWGN0KCIyMDE5LTAxLTE1IiwgdHogPSAiVVRDIiksDQogICAgICB5ID0gMjcsDQogICAgICBsYWJlbCA9ICJQdW50byBjcsOtdGljbyBkZSBveMOtZ2VubyINCiAgICApLA0KICAgIGFlcyh4ID0geCwgeSA9IHksIGxhYmVsID0gbGFiZWwpLA0KICAgIGNvbG9yID0gInJlZCIsDQogICAgc2l6ZSA9IDMuNQ0KICApICsNCiAgDQogICMgQ2FwYSA0OiBsw61uZWEgaG9yaXpvbnRhbCBjcsOtdGljYQ0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAyNCwgY29sb3IgPSAicmVkIikgKw0KICANCiAgIyBUZW1hIHkgcGVyc29uYWxpemFjacOzbg0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBzY2FsZV94X2RhdGV0aW1lKGJyZWFrcyA9ICIxIHdlZWsiLCBkYXRlX2xhYmVscyA9ICIlZC8lYiIpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiU2F0dXJhY2nDs24gZGUgb3jDrWdlbm8gKCUpIiwgdGl0bGUgPSAiTW9ydGFsaWRhZCAyMDE5IC0gQ29uc3RhbnRlIikgKw0KICB0aGVtZSgNCiAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksDQogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICBheGlzLnRpY2tzLmxlbmd0aCA9IHVuaXQoNSwgInB0IiksICMgTG9uZ2l0dWQgZGUgbG9zIHRpY2tzDQogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiksICMgQ29sb3IgZGUgbG9zIHRpY2tzIFgNCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiYmxhY2siKSwgICMgQ29sb3IgZGUgbG9zIHRpY2tzIFkNCiAgICBheGlzLmxpbmUueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjUpLCAjIEzDrW5lYSBob3Jpem9udGFsIGRlbCBlamUNCiAgICBheGlzLmxpbmUueSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjUpICAjIEzDrW5lYSB2ZXJ0aWNhbCBkZWwgZWplDQogICkgKw0KICANCiAgIyBBbm90YWNpb25lcyBhZGljaW9uYWxlcw0KICBhbm5vdGF0ZSgNCiAgICAicmVjdCIsDQogICAgeG1pbiA9IGFzLlBPU0lYY3QoIjIwMTktMDMtMDQiLCB0eiA9ICJVVEMiKSwNCiAgICB4bWF4ID0gYXMuUE9TSVhjdCgiMjAxOS0wMy0xMyIsIHR6ID0gIlVUQyIpLA0KICAgIHltaW4gPSAtSW5mLA0KICAgIHltYXggPSBJbmYsDQogICAgYWxwaGEgPSAwLA0KICAgIGNvbG9yID0gIiM2MzYzNjMiLA0KICAgIHNpemUgPSAwLjcsDQogICAgbGluZXR5cGUgPSAiZGFzaGVkIg0KICApICsNCiAgZ2VvbV90ZXh0KA0KICAgIGRhdGEgPSBkYXRhLmZyYW1lKA0KICAgICAgeCA9IGFzLlBPU0lYY3QoIjIwMTktMDMtMTAiLCB0eiA9ICJVVEMiKSwNCiAgICAgIHkgPSA5OCwNCiAgICAgIGxhYmVsID0gIk1vcnRhbGlkYWQiDQogICAgKSwNCiAgICBhZXMoeCA9IHgsIHkgPSB5LCBsYWJlbCA9IGxhYmVsKSwNCiAgICBjb2xvciA9ICIjNjM2MzYzIiwNCiAgICBzaXplID0gNA0KICApDQpgYGANCg0KKipQdW50b3MgbmVnYXRpdm9zOioqIA0KDQoqIEFudGVzIGRlbCBwZXJpb2RvIGRlIE1vcnRhbGlkYWQsIG5vIHNhbGUgIlByb2JhYmlsaWRhZCBkZSBtb3J0YWxpZGFkIiwgcG9yIGxvIHF1ZSwgZW4gZXNlIGNhc28sIGVsIHNpc3RlbWEgZGUgYWxlcnRhIHRlbXByYW5hIG5vIGZ1bmNpb25hLiANCg0KKiBEdXJhbnRlIGxhIE1vcnRhbGlkYWQsIGVsIHBlcmlvZG8gZGUgbGV0YWxpZGFkIGVzIG11eSBjb3J0bywgbm8gYWJhcmNhIGVsIGV2ZW50byBlbnRlcm8uIA0KDQoqIFBvZHLDrWEgc2VyIHRvZG8gbGV0YWwsIHBlcm8gbGEgdG9tYSBkZSBkYXRvcyBkdXJhbnRlIGxhIG1vcnRhbGlkYWQgbm8gZnVlIGVzdHJpY3RhbWVudGUgdG9kYXMgbGFzIGhvcmFzLCBwb3IgZW5kZSwgbm8gY3VtcGxlIGNvbiBlbCBjcml0ZXJpbyBkZSBkdXJhY2lvbiA+NmguLi4gZGlmaWNpbCBkZSBjbGFzaWZpY2FyIGRlbnRybyBkZSBsYSBjYXRlZ29yaWEgTGV0YWwuIA0KDQo=