Trabajo elaborado para la asignatura “Programación y manejo de datos en la era del Big Data” de la Universitat de València durante el curso 2021-2022. El repo del trabajo está aquí.

La página web de la asignatura y los trabajos de mis compañeros pueden verse aquí.


1. Introducción

En este trabajo trataremos de extraer algunas conclusiones y ayudar al lector a comprender algunos datos sobre la piratería marítima en el mundo actual. Nuestro dataset se basa en el que se puede encontrar aquí. La referencia completa es esta (Benden and Dalla Riva 2021).


1.1 Contexto de la piratería marina

A pesar de que la mención de piratas evoca en la mente de la mayoría de nosotros nociones de rudos aventureros delinquiendo por sus vidas en las aguas turquesas de algún paraíso tropical siglos atrás, la pitarería marina es un problema actual con serias implicaciones sociales y económicas, que ha ganado terreno en el discurso mediático y la investigación académica a partir de casos trágicos como el secuestro de un barco ruso en la costa somalí en septiembre de 2008, u otro evento similar siete meses después con el carguero Maersk Alabama, que fue resuelto con el rescate por parte del ejército norteamericano de los rehenes tomados (Haywood and Spivak 2013).


La imagen que suele venirnos a la mente cuando pensamos en piratería.

No existe una única definición clara de qué constituye un ataque pirata, lo cual dificulta su estudio y la formulación de políticas adecuadas para su resolución (Dillon and Dillon 2005). Resulta útil, por tanto, atender a los detalles de cada evento susceptible de ser clasificado como acto de piratería y ajustar la respuesta institucional al problema a los distintos tipos de ataques que pueden producirse. Este dataset resulta de utilidad justamente por permitir diferenciar entre distintas variedades de ataque. Lo que une todos ellos viene recogido por la definición que proporciona el diccionario de Oxford del término piracy (“Piracy” 2021):

The action of committing robbery, kidnap, or violence at sea or from the sea without lawful authority, especially by one vessel against another; an instance of this.

La piratería en el mundo actual es una lacra para el desarrollo, con un coste económico estimado entre los 7 y 12 mil millones de dólares americanos al año, o incluso más (Bowden et al. 2010). Sin embargo, es probable que las peores consecuancias sean las humanitarias, que se dejan sentir especialmente en aquellos paíse subsdesarrollados en cuyas aguas se emplazan la mayoría de ataques. Es importante considerar que la mayoría de actos de piratería suceden en un contexto mayor de violencia y desorden que casi siempre va de la mano de altos niveles de corrupción y llega a incluir guerras civiles, y que como mínimo condiciona la vida de la población local a causa de las distorsiones que genera en los sectores pesquero y de explotación minera y petrolífera, a menudo principales fuentes de riqueza de las comunidades costeras de estos países (Nincic 2009)(Fu, Ng, and Lau 2010).

Nuestro análisis va a permitir identificar algunas de las tendencias que han definido la evolución de la piratería en estos últimos años, especialmente en lo referente a prevalencia de los tipos de ataques y movimiento de las “zonas calientes” de la piratería internacional. También vamos a contextualizar esta información con datos de carácter económico, social y político.

2. Manejo de los datos

Estructura de los datos

Vamos a analizar un dataset que contiene información sobre 7511 ataques pirata ocurridos entre 1993 y 2020. Esta tabla permite apreciar el tipo de datos que tenemos:

library(DT)

datatable(pirate_attacks, rownames = FALSE, filter="top", options = list(pageLength = 10, scrollX=T))
Haciendo los datos tidy

Aquí mostraremos como hemos tratado los datos para poder llevar a cabo nuestros análisis. Para ello hemos unido dos de los datasets que teníamos y hemos tratado de limpiar los datos. Las principales labores han consistido en corregir inconsistencias en los nombres de tipos de ataques, barcos… además de cuestiones algo más técnicas de manipulación de la expresión de fecha y tipo de variable cuando lo hemos requerido.

#Ahora mostramos el código 
# DATA SOURCE: Benden, P., Feng, A., Howell, C. and Dalla Riva, G.V., 2021. Crime at Sea: A Global Database of Maritime Pirate Attacks (1993–2020). Journal of Open Humanities Data, 7, p.19. DOI: http://doi.org/10.5334/johd.39

country_codes <- read_csv("datos/country_codes.csv")

country_indicators <- read_csv("datos/country_indicators.csv")

pirate_attacks <- read_csv("datos/pirate_attacks.csv")

country_data <- full_join(country_codes, country_indicators, by = c("country" = "country"))
 

pirate_attacks <- pirate_attacks %>% mutate(year = year(date))


pirate_attacks <- pirate_attacks %>% mutate(attack_type = case_when(
  attack_type == "Boarding" ~ "Boarded", 
  TRUE ~ attack_type))

pirate_attacks <- pirate_attacks %>% mutate(vessel_status = case_when(
  vessel_status == "steaming" ~ "Steaming", 
  TRUE ~ vessel_status))

pirate_attacks <- pirate_attacks %>% mutate(vessel_type = case_when(
  vessel_type == "BULK CARRIER" ~ "Bulk Carrier", 
  TRUE ~ vessel_type))

pirate_attacks <- pirate_attacks %>% mutate(vessel_type = case_when(
  vessel_type == "CONTAINER" ~ "Container", 
  TRUE ~ vessel_type))

pirate_attacks <- pirate_attacks %>% mutate(vessel_type = case_when(
  vessel_type == "PRODUCT TANKER" ~ "Product Tanker", 
  TRUE ~ vessel_type))

pirate_attacks <- pirate_attacks %>% mutate(vessel_type = case_when(
  vessel_type == "Offshore Supply ship" ~ "Offshore Supply Ship", 
  TRUE ~ vessel_type))

pirate_attacks <- pirate_attacks %>% mutate(vessel_type = case_when(
  vessel_type == "OFFSHORE SUPPLY SHIP" ~ "Offshore Supply Ship", 
  TRUE ~ vessel_type))

pirate_attacks <- pirate_attacks %>% mutate(vessel_type = case_when(
  vessel_type == "Offshore Supply" ~ "Offshore Supply Ship", 
  TRUE ~ vessel_type))

rm(country_codes, country_indicators)

pirate_attacks <- pirate_attacks %>% mutate(year = as.integer(year))

full_by_nearest <- full_join(pirate_attacks, country_data, by = c("nearest_country" = "country", "year" = "year"))|> filter(!is.na(longitude)) 

Para que sirva de primera aproximación, en este globo terráqueo se pueden explorar los ataques registrados, el país más cercano a donde se produjeron y su año.

library("covid19.analytics")
library("plotly")

df2 <- full_by_nearest |> separate(date, c("year", "month", "day"), "-" ) |> dplyr::select("year","longitude","latitude","country_name") |> mutate(year = as.numeric(year)) |> rename(Province = year) |> rename(Country = country_name)|> rename(Long = longitude)|> rename(Lat = latitude) |> dplyr::select(4,1,2,3) |> as.data.frame()

globemap <- live.map(data = df2, select.projctn = FALSE, title = "", no.legend = TRUE)

globemap <- globemap %>% layout(title = "") 

htmltools::div(globemap, align = "center" )

3. Ataques piratas

3.1 Evolución temporal

library(ggplot2)
library(png)
library(dplyr)
library(grid)


#barco <- readPNG("imagenes/barco.png")

#Ataques totales a lo largo de los años

at_totales <- pirate_attacks %>% group_by(year) %>% summarise(total= n()) 



#representamos 


p1 <- ggplot(data = at_totales, aes(year, total)) + geom_line(color="darkblue") + geom_point(color="darkblue") + theme_minimal() + geom_text(aes(y = total, ymax = total, label = total), position = position_dodge(width = 0.9), size=3, vjust=-0.8, hjust=0.8 ,col="black") + theme_classic() + labs(title = "Total de ataques",
    subtitle = "(1993-2020)",
    x = "Años",
    y = "Nº de ataques") + theme(plot.title = element_text(size = 20, face = "bold", hjust = 0.5),plot.subtitle = element_text(size = 20, hjust = 0.5))

#Añadimos una imagen
img <- readPNG("imagenes/barco.png", FALSE)
marca <- rasterGrob(img, interpolate=F,height=unit(3, "cm"),hjust=-1.30, vjust=-0.5)
p1 + annotation_custom(marca,xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf)
marca
#> rastergrob[GRID.rastergrob.11]


year_at_max <- at_totales |> select(year) %>%  slice_max(order_by= year, n = 1) |> as.integer()

at_max <- at_totales |> select(total) %>% slice_max(order_by= total, n = 1) |> as.integer()

Podemos ver como han ido evolucionando los ataques totales a lo largo de los años. Su máximo fue en el año 2020 con un total de 469 ataques. En la actualidad se han reducido debido a 190 ataques. Los ataques a los barcos ponen en peligro la vida de la tripulación, además afectan al comercio internacional. A lo largo del tiempo la preoucupación ha crecido debido a que los asaltantes cada vez hacen más uso de las armas. Debido a esto la pirateria marina ha pasado por distintas fases de regulación en el Derecho Internacional. Acciones como el uso de patrulleras han ayudado en la disminución de los ataques.

3.2 Evolución geográfica


#intento de mapa
library(mapdata)
library(ggplot2)
library(maps)
library(ggrepel)
library(gganimate)

library(plotly)

# Guardamos la información en un nuevo dataframe llamado mapa_mundo

at_mapa <- pirate_attacks %>% select(longitude, latitude, attack_type, year)

mapa_mundo <- map_data("world")

p <- mapa_mundo %>%
  ggplot() +
  geom_polygon(aes( x= long, y = lat, group = group),
               fill = "white",
               color = "black") +
  theme_minimal() +
  theme(
    axis.line = element_blank(),
    axis.text = element_blank(),
    axis.title = element_blank(),
    axis.ticks = element_blank(),
    panel.background = element_rect(colour= "black", size= 1)) +
  geom_point(data=at_mapa, aes(longitude, latitude),
             color= "darkgoldenrod1", size=2) +
  labs(title = "Concentración de los ataques",
    subtitle = "(1993-2020)") + theme(plot.title = element_text(size = 20, face = "bold", hjust = 0.5),plot.subtitle = element_text(size = 20, hjust = 0.5)) +
  coord_fixed (xlim= c(-200,200),
              ylim= c(-58,90),
              ratio = 1.3) + transition_time(year) + labs(caption = "Year: {frame_time}") + theme(panel.background = element_rect(fill = "lightblue2")) 


animate(p, width = 700, height = 432, fps = 1, duration = 15, rewind = FALSE)

Los ataques se han concentrado sobre todo en el Sudeste asiático y el subcontinente indio, África y América del Sur, Central y las Aguas del Caribe. Podemos ver que durante los primeros años (1993-2008) hay una mayor concentración de los ataques en el estrecho de Malasia, sin embargo comienzan a reducirse debido al aumento de la vigilancia maritima. En Indonesia la Policía Marina de Indondesia(IMP) actúa para evitar más ataques patrullando cerca de las costas, por lo que ha establecido ciertos puntos de mayor protección.

En cuanto a África podemos ver que en el golfo de Guinea aproximadamente desde 1999 ha habido una gran concentración de ataques. En Nigeria los piratas son violentos y van armados. Estas aguas se consideran de alto riesgo. Debido a la guerra civil en Yemén en esta zona se suelen concentrar ataques a barcos que no tienen porque estar directamente relacionados con la piratería. Por último, en la actualidad se concentran menos ataques en Kenia, Tanzania, Océano Índico…, sin embargo como se puede ver, en el pasado se concentraron la mayoría de los ataques.

Finalmente, América del Sur también ha sido una zona de concentración de ataques, aunque con menor relevancia que los comentados anteriormente. Muchas de estas conclusiones se ven reflejadas, quizás con mayor claridad, en la siguiente gráfica dinámica:

full_by_nearest <- full_join(pirate_attacks, country_data, by = c("nearest_country" = "country", "year" = "year"))|> filter(!is.na(longitude))

df <- full_by_nearest |> drop_na(region) |> dplyr::select(year, region) |> unite("id", c(1:2), sep = "_", remove = TRUE)|>  group_by(id) |> mutate(nattacks = n()) |> ungroup() |> distinct() |> separate(id, c("year", "region"), "_" ) |> mutate(year = as.numeric(year)) %>% mutate(region = case_when(
  region == "East Asia & Pacific" ~ "Asia del Este & Pacífico",
  region == "Latin America & Caribbean" ~ "Latino América & Caribe",
  region == "South Asia" ~ "Sur de Asia",
  region == "Sub-Saharan Africa" ~ "África Sub-Sahariana",
  TRUE ~ region))


accumulate_by <- function(dat, var) {
  var <- lazyeval::f_eval(var, dat)
  lvls <- plotly:::getLevels(var)
  dats <- lapply(seq_along(lvls), function(x) {
    cbind(dat[var %in% lvls[seq(1, x)], ], frame = lvls[[x]])
  })
  dplyr::bind_rows(dats)
}


fig <- df 
fig <- fig %>% accumulate_by(~year)


fig <- fig %>%
  plot_ly(
    x = ~year, 
    y = ~nattacks,
    split = ~region,
    frame = ~frame, 
    type = 'scatter',
    mode = 'lines', 
    fill = 'tozeroy',
    line = list(simplyfy = F)
  )
fig <- fig %>% layout(
  xaxis = list(
    title = "Año",
    zeroline = F
  ),
  yaxis = list(
    title = "Número de ataques",
    zeroline = F
  )
)
fig <- fig %>% animation_opts(
  frame = 100, 
  transition = 0, 
  redraw = FALSE
)
fig <- fig %>% animation_slider(
  currentvalue = list(
    prefix = "Año "
  )
)

htmltools::div(fig, align = "center" )

3.3 Tipos de ataques

Existen diferentes tipos de ataques como por ejemplo los abordajes, secuestros, explosiones… vamos a ver cuáles son más frecuentes. Para este análisis hemos excluido los ataques de los cuales no hay información en está categoría (120 ataques).

Tipos más frecuentes
#Ataques según tipo: cantidad total de los ataques según el tipo entre 1993 y 2020 (en el grafico poner los numeros en las barras)

library(ggthemes)

a <- pirate_attacks %>% select(year, attack_type) %>% group_by(year) %>%  count(attack_type) %>% filter(year < 2000) %>% group_by(attack_type) %>% summarise(n = sum(n)) %>% drop_na()
period <- c("1993-1999","1993-1999","1993-1999","1993-1999")
a <- data.frame(period, a)  

b <- pirate_attacks %>% select(year, attack_type) %>% group_by(year) %>%  count(attack_type) %>% filter(year > 1999 & year < 2007, !attack_type == "Detained") %>% group_by(attack_type) %>% summarise(n = sum(n)) %>% drop_na()
period <- c("2000-2006","2000-2006","2000-2006",
            "2000-2006")
b <- data.frame(period, b)

c <- pirate_attacks %>% select(year, attack_type) %>% group_by(year) %>%  count(attack_type) %>% filter(year > 2006 & year < 2014) %>% group_by(attack_type) %>% summarise(n = sum(n)) %>% drop_na()
period <- c("2007-2013","2007-2013","2007-2013","2007-2013")
c <- data.frame(period, c)

d <- pirate_attacks %>% select(year, attack_type) %>% group_by(year) %>%  count(attack_type) %>% filter(year > 2013) %>% group_by(attack_type) %>% summarise(n = sum(n)) %>% drop_na()
period <- c("2014-2020","2014-2020","2014-2020","2014-2020",
            "2014-2020")
d <- data.frame(period, d)

at <- rbind(a,b,c,d) %>%  mutate(attack_type = forcats::as_factor(attack_type)) %>% mutate(attack_type = forcats::fct_reorder(attack_type, n, .desc = TRUE))

  


ggplot(data=at, aes(attack_type, n)) + 
  geom_bar(stat="identity", fill="MediumSlateBlue") + 
  theme_classic() + 
  geom_text(aes(y = n, label = n), 
            position = position_dodge(width = 0.9), size=3,
            vjust=-0.1, hjust=0.5 ,col="black", fontface = "bold") +
  labs(title = "Tipos de ataques",
    subtitle = "(1993-2020)",
    x = "Tipos de ataques",
    y = "Número de ataques") + 
  theme(plot.title = element_text(size = 20, face = "bold", 
                                  hjust = 0.5), 
        plot.subtitle = element_text(size = 20, hjust = 0.5)) +
  facet_wrap(vars(period)) +
  scale_x_discrete(labels=c("Abordaje","Intento","Secuestro",
                            "Duda", "Explosión", "Disparos")) +
  scale_y_continuous(limits = c(0, 1700))

Los ataques más frecuentes son los abordajes, los piratas suelen atacar los barcos mientras navegan o están anclados, además se hace especial advertencia a la noche, que es cuando más posibilidades de ser atacado hay. Por lo tanto, los barcos deben prestar vigilancia en todo momento. En menor medida pero también relevantes son los secuestros, en el pasado se llevaron a cabo varios secuestros de camiones cisterna de productos pequeños en la zona del Mar de China Meridional.Los secuestros que se empezaron a observar en 2014 no duraron más de un año. Con éxito las autoridades consiguieron atrapar a varios de los secuestradores. En la zona de África muchos de los secuestros los utilizaban para pedir rescate. A partir de ahora centraremos el análisis en los tipos más comunes: abordaje, intento y secuestro.

Distribución geográfica

Si centramos el foco en estos tres tipos de ataque y los representamos sobre el mapa, comenzamos a identificar alguna de las tendencias más importantes que vienen reflejadas en la literatura sobre piratería. Principalmente, observamos que los secuestros tienen mucha mayor importancia en el Índico occidental que en ninguna otra área. También comenzamos a observar que los ataques de secuestro e intentos fallidos son mucho más frecuentes a mayor distancia de la costa.

library(tmap) 
library(ggplot2)
library(maps)
library(ggthemes)

data(World)
world <- World |> filter(continent != "Antarctica") ; rm(World)

df <- pirate_attacks |> filter(attack_type == "Boarded" | attack_type == "Hijacked" | attack_type == "Attempted" )

map_by_type <- ggplot() + 
  geom_sf(data = world, color = "grey", fill = "grey", lwd = 0.2, aes(geometry = geometry)) + 
  geom_point(data = df, aes(x = longitude, y = latitude, color = attack_type), size = 0.5, alpha = 0.3) + 
  scale_color_discrete(labels = c("Intento", "Abordaje", "Secuestro")) +
  theme(plot.title = element_text(hjust = 0.5),
        axis.ticks = element_line(linetype = "blank"),
    panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    legend.title = element_text(face = "bold"),
    panel.background = element_rect(fill = NA),
    legend.key = element_rect(fill = NA),
    legend.background = element_rect(fill = NA),
    legend.position = "bottom", legend.direction = "horizontal") +labs(title = "Ataques de los tipos más frecuentes", x = NULL,
    y = NULL, colour = "Tipo de ataque")+ theme(axis.text = element_text(face = "bold",
    colour = NA, hjust = 0, vjust = 0), legend.background = element_rect(fill = "white"),
    legend.position = c(0.1, 0.3), legend.direction = "vertical") 

map_by_type 

El siguiente gráfico, con la distancia media a la costa de cada tipo de ataque, confirma esta intuición:


df <- pirate_attacks |> filter(attack_type == "Boarded" | attack_type == "Hijacked" | attack_type == "Attempted" ) |>  group_by(attack_type) |> summarise(n = mean(shore_distance)) |> mutate(attack_type = forcats::as_factor(attack_type)) |> mutate(attack_type = forcats::fct_reorder(attack_type, n, .desc = TRUE))

ggplot(data = df) + geom_bar(mapping = aes(x = attack_type, y = n), stat = "identity", fill=c("PowderBlue", "MistyRose", "LightSteelBlue")) + theme(panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    panel.background = element_rect(fill = NA))  +
  labs(title = "Distancia media a la costa por tipo de ataque",
    x = "Tipos de ataques",
    y = "Distancia media a la costa") + theme(plot.title = element_text(size = 20, face = "bold", hjust = 0.5),         plot.subtitle = element_text(size = 20, hjust = 0.5)) + scale_x_discrete(labels=c("Intento","Secuestro","Abordaje"))

Finalmente, un vistazo a este gráfico tridimensional también permite apreciar las tendencias en la distancia a la costa según el tipo de ataque descritas previamente, además de evidenciar la concentración de los ataques en la franja tropical y en las costas de las masas continentales. De hecho, cuando se posiciona el punto de vista perpendicularmente al plano (x,y), es posible apreciar cómo los puntos perfilan el contorno de África y América del Sur.

library(plotly)

df <- full_by_nearest |> filter(attack_type == "Boarded" | attack_type == "Hijacked" | attack_type == "Attempted" ) %>% 
  mutate(attack_type = case_when(
    attack_type == "Boarded" ~ "Abordaje",
    attack_type == "Hijacked" ~ "Secuestro",
    attack_type == "Attempted" ~ "Intento",
    TRUE ~ attack_type
  ))


fig3d <- plot_ly(df, x = ~longitude, y = ~latitude, z = ~shore_distance, color = ~attack_type, size = 0.2, alpha = 1)
fig3d <- fig3d %>% add_markers()

fig3d <- fig3d %>% layout(scene = list(xaxis = list(title = 'Longitud'),
                                  yaxis = list(title = 'Latitud'),
                                  zaxis = list(title = 'Distancia a la costa')))

fig3d

3.4 Estado de las embarcaciones


at_estado <- pirate_attacks %>% select(year, vessel_status) %>% group_by(year) %>%  count(vessel_status) %>%  filter(!is.na(vessel_status)) %>% slice_max(order_by = n, n=7) %>% group_by(vessel_status) %>% summarise(h=sum(n)) %>% slice_max(order_by = h, n=11) %>%
  mutate(vessel_status = case_when(
    vessel_status == "Anchored" ~ "Anclado",
    vessel_status == "Steaming" ~ "Navegando",
    vessel_status == "Berthed" ~ "Atracado",
    vessel_status == "Underway" ~ "En marcha",
    vessel_status == "Stationary" ~ "Estacionado",
    vessel_status == "Drifting" ~ "A la deriva",
    vessel_status == "Moored" ~ "Amarrado",
    vessel_status == "Bunkering operations" ~ "Repostando",
    vessel_status == "Fishing" ~ "Pescando",
    vessel_status == "Grounded" ~ "En tierra",
    vessel_status == "Towed" ~ "Remolcado",
  )) %>% 
  mutate(vessel_status = forcats::as_factor(vessel_status)) %>% mutate(vessel_status = forcats::fct_reorder(vessel_status, h, .desc = FALSE))


ggplot(data=at_estado, aes(vessel_status, h)) + geom_col(fill="Thistle") + 
  coord_flip() + 
  theme_minimal() + 
  labs(title = "Estado de las embarcaciones",
    x = "Estado de la embarcación",
    y = "Número de embarcaciones") + 
  theme(plot.title = element_text(size = 20, face = "bold", hjust = 0),         plot.subtitle = element_text(size = 20, hjust = 0.5),
        axis.title.x = element_text(size = 13, hjust = 1, vjust = 0),
        axis.title.y = element_text(size = 13, hjust = 1, vjust = 1)) 

La mayoría de las embarcaciones cuando fueron atracadas se encontraban ancladas, navegando o atracadas. Los piratas suelen huir cuando suenan las alarmas de los barcos sin dar tiempo a ser atrapados, por lo que muchos de los incidentes resultan no denunciarse. Las autoridades ponen a disposición Imb Piracy Reporting Centre donde pueden reportar todos los incidentes que se produzcan.

3.5 Tipo de embarcaciones

Si centramos el foco del análisis sobre el tipo de barco atacado, para los cinco tipos más frecuentes, no podemos extraer ninguna conclusión tan clara:

df <- pirate_attacks |> filter(vessel_type %in% c(  
  "Bulk Carrier",
  "Product Tanker",
  "Container",
  "General Cargo",
  "Chemical Tanker")) 


data(World)
world <- World |> filter(continent != "Antarctica") ; rm(World)

map_by_type2 <- ggplot() + 
  geom_sf(data = world, color = "grey", fill = "grey", lwd = 0.2, aes(geometry = geometry)) + 
  geom_point(data = df, aes(x = longitude, y = latitude, color = vessel_type), size = 0.5, alpha = 0.3) + theme(axis.ticks = element_line(linetype = "blank"),
    panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    legend.title = element_text(face = "bold"),
    panel.background = element_rect(fill = NA),
    legend.key = element_rect(fill = NA),
    legend.background = element_rect(fill = NA),
    legend.position = "bottom", legend.direction = "horizontal") +
  labs(title = "Ataques de los tipos de barco más frecuentes", 
       x = NULL,
       y = NULL, 
       colour = "Tipo de barco")+
  scale_color_discrete(labels = c("Granelero", "Buque cisterna\nquímico", "Contenedor", "Carguero", "Buque de\nproductos")) +
  theme(plot.title = element_text(hjust = 0.5),
    axis.text = element_text(face = "bold",
    colour = NA, hjust = 0, vjust = 0), 
    legend.background = element_rect(fill = "transparent"),
    legend.position = c(0.1, 0.3), 
    legend.direction = "vertical",
    legend.title = element_text(hjust = 0.5)) 

map_by_type2 

3.6 Nombres de los barcos más atacados


nom_barc <- pirate_attacks %>% select(year, vessel_name) %>% group_by(year)  %>% count(vessel_name) %>% filter(!is.na(vessel_name)) %>% filter(!vessel_name %in% c("Unspecified","Name Withheld")) %>% group_by(vessel_name) %>% summarise(h=sum(n)) %>% slice_max(order_by = h, n=5) %>%  mutate(vessel_name = forcats::as_factor(vessel_name)) %>% mutate(vessel_name = forcats::fct_reorder(vessel_name, h, .desc = TRUE))



library(plotly)


p1 <- ggplot(data=nom_barc, aes(vessel_name, h )) + geom_col(fill="PaleVioletRed") + theme_minimal() + 
  labs(title = "Nombres de las embarcaciones más atacadas",
       x = "Nombre del barco",
       y = "Número de ataques") + theme(plot.title = element_text(size = 20, face = "bold", hjust = 0),         plot.subtitle = element_text(size = 20, hjust = 0.5),
        axis.title.x = element_text(size = 13, hjust = 1, vjust = 0),
        axis.title.y = element_text(size = 13, hjust = 1, vjust = 1))

s <- ggplotly(p1)

htmltools::div(s, align = "center" )

Como hemos comentado antes, el Maersk Alamaba fue secuestrado allá por el 2009, cuatro piratas somalís tomaron posesión del barco. Fue un acontecimineto importante ya que era el primer asalto que se realizaba con éxito desde el Siglo XIX a un buque portador de la bandera estadounidense. En este secuestro los piratas tuvieron vigilada a la tripulación a punta de pistola. Finalmente la armada de EE.UU abatió a tres de los secuestradores.

Otro ejemplo curioso es el del Thor Falcon, que sufrió 6 ataques en el 2003 seis días seguidos. Este barco fue abordado cerca de Bangladesh las 6 veces mientras se encontraba atracado.

4. Dataset de los Países

Información

El siguiente dataset con el que vamos a trabajar contiene datos de una serie de indicadores para la mayoría de países del mundo. Estos países vienen agrupados en regiones, las cuales no coinciden necesariamente con los continentes. Por este motivo, resulta interesante realizar un primer análisis exploratorio de los principales indicadores del dataset por regiones, para después centrarnos más de cerca en aquellos países más relevantes

Dataset
datatable(paises, rownames = FALSE, filter="top", options = list(pageLength = 10, scrollX=T))

4.1 Análisis por regiones

Para comenzar, realizaremos un análisis exploratorio de los principales datos de este dataset por regiones. En el mapa que se muestra a continuación se representan las distintas regiones en las que vienen agrupados los países. Cabe destacar casos como el de México. País que, aun estando en Norte América, viene recogido por la región de América latina y el Caribe.

media_regiones <- paises %>% 
  select(region, country_name, total_military) %>% 
  group_by(region, country_name) %>% 
  summarise(media_militar = mean(total_military, na.rm = TRUE)) %>% 
  ungroup() %>% group_by(region) %>%  
  mutate(media_militar = mean(media_militar, na.rm = TRUE)) %>% 
  mutate(iso2 = countrycode::countrycode(
    sourcevar = country_name, origin = "country.name",
    destination =  "iso2c", warn = FALSE), .after = country_name) 

mapa_mundo <- map_data("world") %>% 
  mutate(iso2 = countrycode::countrycode(
    sourcevar = region, origin = "country.name",
    destination =  "iso2c", warn = FALSE), .after = region) 

paises_mapa <- full_join(mapa_mundo, media_regiones, 
                         by= c("iso2"="iso2"))

t <- paises_mapa %>%
  ggplot() +
  geom_polygon(aes(x= long, y = lat, group = group, fill = region.y),
               color = "black") +
  labs(
    title = "Representación de los\npaíses de cada región",
    fill = "Regiones"
  ) +
  scale_fill_discrete(breaks = c("East Asia & Pacific", 
                                 "Europe & Central Asia", 
                                 "Latin America & Caribbean", 
                                 "Middle East & North Africa", 
                                 "North America", "South Asia", 
                                 "Sub-Saharan Africa"), 
                      labels = c("Asia del Este\n& Pacífico", 
                                 "Europa\n& Asia Central", 
                                 "Latino América\n& Caribe", 
                                 "Oriente Medio\n& Norte de Africa", 
                                 "América\ndel Norte", 
                                 "Sur\nde Asia", 
                                 "África\nSub-Sahariana")) +
  theme_minimal() +
  theme(plot.title = element_text(
    size = 15, face = "bold", hjust = 0.5),
        axis.line = element_blank(),
        axis.text = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank(),
        panel.background = element_rect(colour= "black", 
                                        size= 1, 
                                        fill = "lightblue2"),
        legend.title = element_text(face= "bold"),
        legend.position = "bottom",
        legend.direction = "horizontal") +
  coord_fixed (xlim= c(-200,200),
               ylim= c(-58,90),
               ratio = 1.3) 

t

4.1.1 Evolución índice de corrupción

El índice de corrupción es un indicador que mide la percepción de corrupción en cada uno de los países. Es un indicador publicado por Transparencia Internacional desde 1995, siendo 100 un nivel de corrupción nulo y 0 un nivel de corrupción muy elevado.

Es importante destacar que hasta el año 2012, el índice de corrupción venía recogido en una escala del 0 al 10. Sin embargo, en 2012 la escala fue cambiada de 0 a 100. Por este motivo, hemos realizado un cambio de escala para los años anteriores a 2012, obteniendo de este modo valores entre 0 y 100 para todo el periodo analizado.

Gráfico

A continuación podemos observar la evolución del índice de corrupción desde 1995 hasta 2019, a excepción del año 1999 en el cual no existen datos. La región mejor considerada es América del Norte, mientras que África Sub-Sahariana es la región con la peor calificación en este apartado.

Otro hecho relevante es la disminución de este índice tras la crisis financiera del 2008 y su posterior recaída en 2014 en las regiones más ricas. Este hecho puede deberse a la naturaleza de este indicador, puesto que se obtiene a través de encuestas de opinión a la ciudadanía y evaluaciones de expertos.

media_regiones <- paises %>% 
  group_by(region, year) %>% 
  summarise(media_corrupción = mean(corruption_index, na.rm = TRUE),
            media_homicidios = mean(homicide_rate, na.rm = TRUE),
            media_militar = mean(total_military, na.rm = TRUE),
            media_gasto = mean(totalgr, na.rm= TRUE)) %>% 
  ungroup() %>% mutate(year = as.numeric(year)) %>%
  mutate(media_corrupción = ifelse(
    year<2012, media_corrupción *10, media_corrupción)) %>%
  filter(year >= 1995) %>% 
  mutate(media_regiones= is.numeric(media_regiones))

zz <- media_regiones %>%
  ggplot(aes(x = region, 
             y = media_corrupción, 
             fill= region )) +
  geom_bar(stat= "identity", 
           color = "white", 
           show.legend = FALSE) +
  geom_text(aes(label = round(media_corrupción, digits = 2)), 
            position = position_dodge(0.9), 
            vjust= 1.2, 
            size = 5, 
            color = "white")+
  scale_x_discrete(labels = c("Asia del Este\n& Pacífico", 
                              "Europa\n& Asia Central", 
                              "Latino América\n& Caribe", 
                              "Oriente Medio\n& Norte de Africa",
                              "América\ndel Norte", 
                              "Sur\nde Asia",
                              "África\nSub-Sahariana")) + 
  scale_y_continuous(labels = scales::comma) +
  theme_minimal()+
  enter_appear() +
  transition_states(year, 
                    transition_length = 1.5, 
                    state_length = 2) +
  labs(title = " Evolución del índice de corrupción por regiones  \n Año: {closest_state}", 
       subtitle = "Evolución por regiones",
       y = "",
       x = "") +
  theme(panel.grid.major.x = element_blank(),
        plot.title = element_text(size = 18, 
                                  face = "bold", 
                                  hjust = 0.5),
        plot.subtitle = element_text(size=14, 
                                     face = "plain", 
                                     hjust = 0.5)) 


animate(zz, width = 700, height = 700, fps = 2, 
        duration = 30, rewind = FALSE) 

Tabla

media_regiones %>% #gtTable
  select(region, year, media_corrupción) %>% 
  filter(!year %in% c(1993, 1994,1999, NA)) %>%
  pivot_wider(names_from = "region", 
              values_from = "media_corrupción") %>% 
  gt(rowname_col = "year") %>% 
  tab_header(title = md("Índice de corrupción por regiones"),
             subtitle = md("De 1995 a 2019")) %>% 
  tab_options(heading.background.color = "midnightblue") %>%
  tab_options(heading.title.font.size = 25,
              heading.subtitle.font.size = 20, 
              column_labels.font.weight =  "bold", 
              heading.align = "center") %>% 
  tab_options(table.align = "center") %>% 
  cols_align(align = "center") %>% 
  cols_label(`East Asia & Pacific` = "Asia del Este & Pacífico",
             `Europe & Central Asia` = "Europa & Asia Central", 
             `Latin America & Caribbean` = "Latino América & Caribe",
             `Middle East & North Africa` = 
               "Oriente Medio & Norte de Africa", 
             `North America` = "América del Norte", 
             `South Asia` = "Sur de Asia", 
             `Sub-Saharan Africa` = "África Sub-Sahariana") %>% 
  fmt_number(columns= 2:8, 
             decimals = 2,
             dec_mark = ",")
Índice de corrupción por regiones
De 1995 a 2019
Asia del Este & Pacífico Europa & Asia Central Latino América & Caribe Oriente Medio & Norte de Africa América del Norte Sur de Asia África Sub-Sahariana
1995 55,16 69,33 41,93 NaN 83,30 25,15 56,20
1996 56,66 67,40 35,36 51,47 83,10 19,73 27,50
1997 53,67 67,75 36,36 79,70 83,55 26,40 33,55
1998 53,83 61,87 34,00 46,80 83,50 28,00 35,60
2000 52,50 55,21 39,27 48,40 85,00 28,00 32,37
2001 54,50 56,81 37,22 53,50 82,50 18,00 31,47
2002 54,75 54,85 34,48 47,40 83,50 25,50 31,50
2003 49,57 50,80 34,36 41,05 81,00 25,00 29,24
2004 49,07 50,70 36,56 41,15 73,50 25,40 28,81
2005 65,94 51,38 61,35 42,30 80,00 24,83 27,95
2006 46,89 52,17 34,96 41,89 79,00 33,20 27,81
2007 42,29 52,04 37,93 38,30 79,50 29,62 28,04
2008 42,25 51,81 39,33 39,25 80,00 29,25 28,15
2009 43,04 51,60 39,62 38,85 81,00 28,00 28,40
2010 43,32 51,15 37,58 39,90 80,00 28,50 28,55
2011 42,23 51,02 39,67 39,25 79,00 29,38 29,19
2012 45,30 53,91 43,40 40,65 78,50 32,43 33,30
2013 45,70 53,89 42,73 39,20 77,00 32,86 32,43
2014 45,05 54,76 43,37 40,15 77,50 33,71 32,70
2015 44,95 55,49 37,04 40,75 79,50 33,29 32,26
2016 46,48 55,20 41,83 38,00 78,00 34,88 31,49
2017 46,77 54,52 41,90 38,45 78,50 35,50 32,04
2018 46,77 54,60 41,57 38,95 76,00 35,50 32,27
2019 47,36 54,56 41,40 39,30 73,00 35,50 32,29

4.1.2 Evolución tasa de homicidios

La tasa de homicidios mide el número de muertes a causa de la acción de otra persona (de manera voluntaria o no) por cada 100.000 habitantes. Este indicador nos ayuda a medir el índice de violencia de un país. Por ello, cobra especial importancia en nuestro estudio, debido a que la piratería marítima se lleva a cabo a través de actos violentos como son secuestros, robos o extorsiones. Así pues, es posible que exista una fuerte correlación entre este indicador y los ataques de piratas.

Gráfico

media_regiones <- paises %>% group_by(region, year) %>%
  summarise(media_corrupción = mean(corruption_index, na.rm = TRUE),
            media_homicidios = mean(homicide_rate, na.rm = TRUE),
            media_militar = mean(total_military, na.rm = TRUE),
            media_gasto = mean(totalgr, na.rm= TRUE)) %>%
  ungroup() %>% mutate(year = as.numeric(year))

bb <- media_regiones %>%
  filter(!year %in% c(2019, NA)) %>%
  ggplot(aes(x= year, y= media_homicidios)) + 
  labs(title = "Evolución tasa de homicidios\npor regiones",
       x= "Año",
       y= "Índice de homicidios medio",
       color = "Regiones") +
  geom_point(aes(color= region), size= 3) +
  geom_line(aes(color= region), size= 1.5) + 
  scale_color_manual(values= c("red", "blue", "green", "black",
                               "yellow", "orange", "midnightblue"),
                     labels = c("Asia del Este\n&\nPacífico",
                                "Europa\n&\nAsia Central",
                                "Latino América\n&\nCaribe",
                                "Oriente Medio\n&\nNorte de Africa",
                                "América\ndel\nNorte",
                                "Sur\nde\nAsia",
                                "África\nSub-Sahariana"))+
  theme_minimal() +
  theme(plot.title = element_text(size = 20, face = "bold",
                                  hjust = 0.5),
        axis.title.x = element_text(size = 13, hjust = 1,
                                    vjust = 0),
        axis.title.y = element_text(size = 13, hjust = 1, vjust = 1),
        legend.title = element_text(face = "bold")) +
  transition_reveal(year) + 
  view_follow()

bb #gganimate  

El uso de gráficos de líneas animados es una buena herramienta para analizar la evolución de una variable de forma dinámica y sencilla. Para la tasa de homicidios, extraemos que para todo el periodo la región con la mayor tasa ha sido Latino América y el Caribe y África Sub-Sahariana. Sin embargo, en el caso de este último, este índice se ha ido reduciendo año tras año.

En lo que respecta al resto de regiones, han mantenido su nivel constante a lo largo del periodo. Destaca el caso de Oriente Medio y el Norte de África, cuyo índice ha sido y es el menor. Resulta sorprendente ya que esta región la forman países que durante el periodo han estado en guerra, como es el caso de Libia. Detrás de este fenómeno es posible que exista una incorrecta medición o la falta de datos que realmente describan la situación de estos países.

Tabla

media_regiones %>% #gtTable
  select(region, year, media_homicidios) %>%
  filter(!year %in% c(2019, NA)) %>% 
  pivot_wider(names_from = "region", values_from = "media_homicidios") %>% 
  gt(rowname_col = "year") %>% 
  tab_header(title = md("Índice de homicidios por regiones"),
             subtitle = md("De 1993 a 2018")) %>% 
  tab_options(heading.background.color = "seagreen") %>%
  tab_options(heading.title.font.size = 25,
              heading.subtitle.font.size = 20,
              column_labels.font.weight =  "bold",
              heading.align = "center") %>% 
  tab_options(table.align = "center") %>% 
  cols_align(align = "center") %>% 
  cols_label(`East Asia & Pacific` = "Asia del Este & Pacífico",
             `Europe & Central Asia` = "Europa & Asia Central", 
             `Latin America & Caribbean` = "Latino América & Caribe",
             `Middle East & North Africa` = 
               "Oriente Medio & Norte de Africa", 
             `North America` = "América del Norte", 
             `South Asia` = "Sur de Asia", 
             `Sub-Saharan Africa` = "África Sub-Sahariana") %>% 
  fmt_number(columns= 2:8, 
             decimals = 2,
             dec_mark = ",")
Índice de homicidios por regiones
De 1993 a 2018
Asia del Este & Pacífico Europa & Asia Central Latino América & Caribe Oriente Medio & Norte de Africa América del Norte Sur de Asia África Sub-Sahariana
1993 3,22 6,57 16,67 2,33 5,49 4,37 14,58
1994 3,04 5,40 22,55 2,36 6,86 4,39 23,75
1995 2,22 5,22 20,80 1,24 5,08 4,36 20,90
1996 2,35 4,71 20,63 1,97 5,27 5,94 19,94
1997 2,42 5,56 20,98 1,81 3,94 4,66 18,77
1998 3,24 4,68 19,78 1,94 2,68 4,30 21,69
1999 3,16 4,78 17,26 2,26 3,50 5,31 19,14
2000 2,71 4,52 18,25 1,71 2,44 3,83 14,37
2001 3,10 4,55 17,62 1,73 4,38 3,80 14,44
2002 3,14 4,37 19,94 1,75 3,02 3,74 12,55
2003 3,49 3,90 19,49 1,72 3,51 3,52 9,47
2004 2,87 3,81 21,27 1,75 3,01 4,37 9,32
2005 3,65 3,51 19,88 1,69 3,60 3,99 8,79
2006 3,53 3,14 20,27 1,73 4,10 4,50 8,04
2007 2,80 2,88 20,44 1,67 4,04 3,17 9,19
2008 2,78 2,95 22,05 2,72 5,00 4,46 9,35
2009 2,99 2,73 25,13 2,20 5,39 3,78 9,82
2010 3,32 2,91 24,28 2,18 5,78 3,49 8,89
2011 3,15 2,24 24,34 2,15 6,35 3,70 8,78
2012 3,27 2,51 22,64 2,39 5,27 4,13 8,35
2013 2,34 2,12 18,70 2,54 4,64 3,30 10,15
2014 2,38 2,24 19,38 1,33 4,11 3,62 8,12
2015 3,47 1,99 21,30 1,38 4,36 4,08 8,13
2016 2,19 1,86 21,52 1,31 6,68 3,18 10,76
2017 1,64 1,93 22,29 1,51 5,09 3,34 7,32
2018 2,72 1,73 19,74 1,19 3,36 3,27 6,29

4.1.3 Media de ingresos públicos

El siguiente indicador que trabajaremos es la media de ingresos públicos por región. Este indicador es un buena aproximación del gasto de estos países, puesto que mayores ingresos suele ir acompañado de mayor gasto. Además, frecuentemente los países más seguros son aquellos en los que la presión fiscal es más alta. Esto se debe, entre otros factores, a una mejor dotación de medios para los cuerpos de seguridad.

Gráfico

A la hora de describir la evolución de una variable es habitual el uso de gráficos de líneas. No obstante, existen otras formas muy útiles de representar la variación de un indicador a lo largo del tiempo. En este caso, hemos hecho uso de un boxplot. En él, podemos obsercar la media de los ingresos públicos por cada región, además del primer y tercer cuartil. Finalmente, también observamos cada una de las observaciones para cada año.

media_regiones <- paises %>% group_by(region, year) %>%
  summarise(media_corrupción = mean(corruption_index, na.rm = TRUE),
            media_homicidios = mean(homicide_rate, na.rm = TRUE),
            media_militar = mean(total_military, na.rm = TRUE),
            media_gasto = mean(totalgr, na.rm= TRUE)) %>%
  ungroup() %>% mutate(year = as.numeric(year))

media_regiones %>% 
  select(region, year, media_gasto) %>%
  filter(!year == is.na(year)) %>% 
  mutate(year = as.character(year)) %>% 
  ggplot(aes(x= region, y= media_gasto)) +
  geom_boxplot() + 
  geom_jitter(aes(color= year), size= 2) +
  scale_x_discrete(labels = c("Asia del Este\n&\nPacífico",
                              "Europa\n&\nAsia Central",
                              "Latino América\n&\nCaribe",
                              "Oriente Medio\n&\nNorte de Africa",
                              "América\ndel\nNorte", 
                              "Sur\nde\nAsia",
                              "África\nSub-Sahariana")) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Porcentaje ingresos públicos por región",
       subtitle = "De 1993 a 2019",
       x= "Región",
       y= "Ingresos públicos (%PIB)",
       color = "Año") +
  theme_ipsum() +
  theme(plot.title = element_text(hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5),
        axis.title.x = element_text(size = 12, face = "bold"),
        axis.title.y = element_text(size = 12, face = "bold"),
        legend.title = element_text(face = "bold", hjust = 0.5))

Cabe destacar las grandes diferencias que existen entre las regiones en lo referente a sus políticas fiscales. Mientras en los países europeos existe una importante presión fiscal, en regiones como el sur de Asía esta presión fiscal se reduce prácticamente a la mitad.

Por otro lado, otro aspecto a destacar es la dispersión de esta variable a lo largo de los años. Curiosamente, esta dispersión es menor para las regiones cuya presión fiscal es muy alta o muy baja. Y es mayor para las regiones cuyo nivel medio se encuentra entre ambos extremos.

Terminando con esta sección, la principal conclusión obtenida es la importante relación que existe entre ingresos públicos y riqueza. Puesto que podemos observar, son las regiones más ricas las que obtienen mayores ingresos públicos. Mientras que en la otra cara de la moneda, aquellas regiones más pobres son las que presentan un menor nivel.

Tabla

media_regiones %>% #gtTable
  select(region, year, media_gasto) %>%
  filter(!year %in% c(2019, NA)) %>% 
  pivot_wider(names_from = "region", values_from = "media_gasto") %>%
  gt(rowname_col = "year") %>% 
  tab_header(title = md("Gasto público por regiones"),
             subtitle = md("De 1993 a 2018")) %>% 
  tab_options(heading.background.color = "sienna") %>%
  tab_options(heading.title.font.size = 25,
              heading.subtitle.font.size = 20,
              column_labels.font.weight =  "bold",
              heading.align = "center") %>% 
  tab_options(table.align = "center") %>% 
  cols_align(align = "center") %>% 
  cols_label(`East Asia & Pacific` = "Asia del Este & Pacífico",
             `Europe & Central Asia` = "Europa & Asia Central", 
             `Latin America & Caribbean` = "Latino América & Caribe",
             `Middle East & North Africa` = 
               "Oriente Medio & Norte de Africa", 
             `North America` = "América del Norte", 
             `South Asia` = "Sur de Asia", 
             `Sub-Saharan Africa` = "África Sub-Sahariana") %>% 
  fmt_percent(columns= 2:8, 
             decimals = 2)
Gasto público por regiones
De 1993 a 2018
Asia del Este & Pacífico Europa & Asia Central Latino América & Caribe Oriente Medio & Norte de Africa América del Norte Sur de Asia África Sub-Sahariana
1993 32.53% 38.08% 18.94% 28.79% 37.86% 21.40% 20.33%
1994 31.23% 38.03% 18.74% 28.05% 37.79% 21.50% 18.33%
1995 35.25% 38.58% 19.44% 29.61% 38.03% 21.87% 18.85%
1996 30.05% 38.22% 20.21% 30.83% 38.55% 22.10% 18.46%
1997 29.91% 37.77% 20.29% 31.83% 39.01% 20.69% 19.20%
1998 29.74% 38.07% 20.49% 30.40% 39.21% 19.51% 17.91%
1999 27.31% 38.15% 20.57% 29.38% 39.15% 20.99% 19.21%
2000 27.17% 37.85% 20.77% 33.91% 39.25% 21.53% 19.38%
2001 26.29% 36.99% 21.14% 33.98% 38.06% 19.60% 19.45%
2002 24.25% 37.58% 20.43% 31.91% 36.18% 17.92% 18.88%
2003 25.75% 37.65% 21.14% 32.35% 35.89% 16.78% 18.95%
2004 30.54% 37.37% 21.42% 34.78% 35.91% 18.27% 20.05%
2005 30.32% 37.98% 22.34% 36.10% 36.71% 19.31% 21.91%
2006 32.14% 38.53% 23.10% 37.33% 37.32% 20.17% 23.97%
2007 33.50% 38.98% 23.35% 36.18% 37.30% 20.77% 25.83%
2008 33.73% 39.39% 24.02% 36.49% 36.11% 19.47% 23.07%
2009 33.10% 38.18% 22.79% 35.43% 35.27% 19.14% 21.53%
2010 33.17% 38.30% 23.33% 36.07% 34.95% 20.50% 21.45%
2011 32.79% 38.54% 23.87% 36.32% 35.06% 20.06% 22.19%
2012 34.72% 39.07% 23.66% 38.68% 35.10% 18.91% 22.33%
2013 36.20% 39.46% 23.88% 36.76% 36.23% 20.49% 21.92%
2014 39.20% 39.67% 24.03% 36.43% 36.24% 20.63% 21.80%
2015 35.12% 39.04% 24.10% 33.05% 37.05% 20.64% 21.43%
2016 34.34% 38.87% 24.60% 29.28% 36.99% 22.84% 20.94%
2017 35.69% 38.66% 25.15% 30.90% 37.46% 21.11% 21.05%
2018 35.84% 39.48% 26.55% 31.71% 36.33% 20.86% 21.69%

4.1.4 Número medio de militares

Para terminar con el análisis por regiones, nos fijaremos en la dimensión de los ejércitos que conforman los diferentes países de cada región. Para ello, obtendremos el número total de militares de cada región y lo representaremos en el mapa que se muestra a continuación.

Gráfico

media_regiones <- paises %>% 
  select(region, country_name, total_military) %>% 
  group_by(region, country_name) %>% 
  summarise(media_militar = mean(total_military, na.rm = TRUE)) %>%
  ungroup() %>% group_by(region) %>%  
  mutate(media_militar = mean(media_militar, na.rm = TRUE)) %>%
  mutate(iso2 = countrycode::countrycode(
    sourcevar = country_name, origin = "country.name",
    destination =  "iso2c", warn = FALSE), .after = country_name) 

mapa_mundo <- map_data("world") %>%
  mutate(iso2 = countrycode::countrycode(
    sourcevar = region, origin = "country.name",
    destination =  "iso2c", warn = FALSE), .after = region) 

paises_mapa <- full_join(mapa_mundo, media_regiones, 
                         by= c("iso2"="iso2"))

a <- paises_mapa %>%
  ggplot() +
  geom_polygon(aes( x= long, y = lat, group = group,
                    fill = region.y), color = "black") +
  labs(title = "Número total de militares por región",
    fill = "Regiones") +
  scale_fill_discrete(breaks = c("East Asia & Pacific", 
                                 "Europe & Central Asia", 
                                 "Latin America & Caribbean",
                                 "Middle East & North Africa", 
                                 "North America", "South Asia",
                                 "Sub-Saharan Africa"), 
                      labels = c("Asia del Este\n& Pacífico",
                                 "Europa\n& Asia Central", 
                                 "Latino América\n& Caribe", 
                                 "Oriente Medio\n& Norte de Africa",
                                 "América\ndel Norte", 
                                 "Sur\nde Asia",
                                 "África\nSub-Sahariana")) +
  theme_minimal() +
  theme(plot.title = element_text(size = 15, face = "bold", 
                                  hjust = 0.5),
        axis.line = element_blank(),
        axis.text = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank(),
        panel.background = element_rect(colour= "black", size= 1, 
                                        fill = "lightblue2"),
        legend.title = element_text(face= "bold"),
        legend.position = "bottom",
        legend.direction = "horizontal") +
  annotate("text", x= 95, y= 62, label = "123.550", size= 6,
           fontface=2, color= "brown") +
  annotate("text", x= 180, y= 10, label = "421.262", size= 6,
           fontface=2, color= "red") +
  annotate("text", x= -110, y= -10, label = "80.469", size= 6,
           fontface=2, color = "seagreen") +
  annotate("text", x= 72, y= -5, label = "516.730", size= 5,
           fontface=2, color = "purple") +
  annotate("text", x= -45, y= 30, label = "178.468", size= 5,
           fontface=2, color = "turquoise4") +
  annotate("text", x= -170, y= 40, label = "792.325", size= 6,
           fontface=2, color = "blue") +
  annotate("text", x= 20, y= -40, label = "38.301", size= 6,
           fontface=2, color = "magenta") +
  coord_fixed (xlim= c(-200,200),
               ylim= c(-58,90),
               ratio = 1.3) 

a

Sin embargo, la obtención de este dato nos crea la duda de conocer la dimensión de los ejércitos de cada país. Puesto que al agregar el número total de militares de cada país por región, perdemos la información sobre qué países realizan una mayor inversión en personal militar frente al resto. Además, para conocer si un país se encuentra fuertemente militarizado hemos de tener en cuenta su población. Por ello, la proporción de militares respecto a la población total nos ayudará más adelante a conocer la dimensión relativa de los ejércitos.

Tabla

paises %>% select(region, country_name, total_military) %>%
  group_by(region, country_name) %>% 
  summarise(media_militar = mean(total_military, na.rm = TRUE)) %>%
  ungroup() %>% group_by(region) %>%  
  summarise(media_militar = mean(media_militar, na.rm = TRUE)) %>%
  ungroup() %>% mutate(region = case_when(
  region == "East Asia & Pacific" ~ "Asia del Este & Pacífico",
  region == "Europe & Central Asia" ~ "Europa & Asia Central", 
  region == "Latin America & Caribbean" ~ "Latino América & Caribe", 
  region == "Middle East & North Africa" ~ 
    "Oriente Medio & Norte de Africa", 
  region == "North America" ~ "América del Norte", 
  region == "South Asia" ~ "Sur de Asia", 
  region == "Sub-Saharan Africa" ~ "África Sub-Sahariana")) %>% 
  gt(rowname_col = "region") %>% 
  tab_header(title = md("Media de militares por región"),
             subtitle = md("De 1993 a 2019")) %>% 
  tab_options(heading.background.color = "orange") %>%
  tab_options(heading.title.font.size = 25,
              heading.subtitle.font.size = 20,
              column_labels.font.weight =  "bold",
              heading.align = "center") %>% 
  tab_options(table.align = "center") %>% 
  cols_align(align = "center") %>% 
  cols_label(`media_militar` = "Media número de militares") %>% 
  fmt_number(columns= 2, 
             decimals = 0,
             sep_mark = ".")
Media de militares por región
De 1993 a 2019
Media número de militares
Asia del Este & Pacífico 421.262
Europa & Asia Central 123.550
Latino América & Caribe 80.469
Oriente Medio & Norte de Africa 178.468
América del Norte 792.325
Sur de Asia 516.730
África Sub-Sahariana 38.301

4.2 Análisis por países

A la hora de realizar un análisis por países hemos de ser conscientes del gran número de observaciones de las que disponemos. Existen alrededor de 200 países en el mundo. Por lo que la visualización de los datos de cada uno de estos países en un mismo gráfico se puede tornar un problema a la hora de representarlos. Por ello, en esta sección se mostraran los los países más relevantes par cada indicador en cuestión, o en otras palabras, nos centraremos en aquellos países que mejor nos ayuden a entender la información del dataset.

4.2.1 Número de militares por país

Comenzaremos donde lo dejamos antes. Para conocer qué países tienen un mayor número de militares respecto a su población, dividimos el número total de militares para cada país en cada año y calculamos su media. El resultado lo podemos mostrar en el siguiente mapa.

#cuartiles <- descr(ejercito$mili_pc)

ejercito <- paises %>% 
  select(country_name, year, total_military, population) %>%
  drop_na(total_military, population) %>% 
  mutate(mili_pc = total_military/population) %>%
  group_by(country_name) %>% mutate(mili_pc = mean(mili_pc)) %>%
  mutate(mili_pc = case_when(
    mili_pc <= 0.0025272261 ~ 1,
    mili_pc > 0.0025272261 & mili_pc < 0.0049017440 ~ 2, 
    mili_pc > 0.0049017440 & mili_pc < 0.0084707455 ~ 3,
    mili_pc >= 0.0084707455  ~ 4,
    is.na(mili_pc) ~ 0)) %>% 
  mutate(country_name = ifelse(
    country_name == "São Tomé and Principe",
    "São Tomé and Principe", country_name)) %>% 
  mutate(iso2 = countrycode::countrycode(
    sourcevar = country_name, origin = "country.name",
    destination =  "iso2c", warn = FALSE), .after = country_name) %>%
  mutate(mili_pc = as.character(mili_pc))

mapa_mundo <- map_data("world") %>% 
  mutate(iso2 = countrycode::countrycode(
    sourcevar = region, origin = "country.name",
    destination =  "iso2c", warn = FALSE), .after = region) 

paises_mapa2 <- full_join(mapa_mundo, ejercito, by= c("iso2"="iso2"))

l <- paises_mapa2 %>%
  ggplot() +
  geom_polygon(aes( x= long, y = lat, group = group, fill = mili_pc),
               color = "black") +
  scale_fill_discrete(breaks = c(4, 3, 2, 1, 0), 
                      labels= c("n > 0.84%", 
                                "0.49% < n < 0.84%",
                                "0.25% < n < 0.49%", "n < 0.25%",
                                "Sin datos")) +
  labs(
    title = "Porcentaje de militares por país",
    subtitle = "Media del periodo 1993-2019",
    fill = "Porcentaje de militares"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(size = 15, face = "bold",
                                  hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5),
        axis.line = element_blank(),
        axis.text = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank(),
        legend.title = element_text(face = "bold"),
        legend.position = "bottom",
        legend.direction = "vertical",
        panel.background = element_rect(colour= "black", size= 1,
                                        fill ="lightblue2")) +
  coord_fixed (xlim= c(-200,200),
               ylim= c(-58,90),
               ratio = 1.3) 

l

Los intervalos calculados para la representación del mapa han sido obtenidos de los cuartiles de la variable mili_pc. Sin embargo, entre en tercer cuartil y el valor más alto existe una gran dispersión. Por ello, resulta interesante conocer cuál es el porcentaje de militares en los países más militarizados.

ejercito2 <- paises %>% 
  select(country_name, year, total_military, population) %>% 
  drop_na(total_military, population) %>% 
  mutate(mili_pc = total_military/population) %>% 
  group_by(country_name) %>% summarise(mili_pc = mean(mili_pc)) %>% 
  slice_max(order_by = mili_pc, n= 5) %>% 
  mutate(country_name = forcats::as_factor(country_name)) %>% 
  mutate(country_name = forcats::fct_reorder(
    country_name, mili_pc, .desc = FALSE))

a <- ggplot(ejercito2) + 
  geom_col(aes(x=country_name, y= mili_pc), fill = "sienna") +
  scale_y_continuous(limits = c(0, 0.06), 
                     breaks = seq(0, 0.06, 0.02), 
                     labels = scales::percent_format(accuracy = 1)) +
  scale_x_discrete(labels = c("Brunei", "Israel",
                              "Singapur", "Corea del Norte",
                              "Eritrea")) +
  labs(title = "Top 5 países con mayor\nporcentaje de militares",
       x= "",
       y="") +
  coord_flip() +
  theme_ipsum() +
  theme(plot.title = element_text(hjust = 0.5))

dd <- ggplotly(a, width = 600, height = 520)

htmltools::div(dd, align = "center")

4.2.2 Tasa de desempleo

Otro de los indicadores de los que disponemos es de la tasa de desempleo. A continuación, visualizaremos cuáles son los países que de media han mantenido un mayor y un menor nivel de desempleo a lo largo del periodo analizado.

Mayor desempleo
desemp_max <- paises %>% group_by(country_name) %>% 
  mutate(unemployment_rate = unemployment_rate/100) %>% 
  summarise(desemp = mean(unemployment_rate)) %>% drop_na() %>% 
  slice_max(order_by = desemp, n= 5)

desemp_max %>% #gtTable
  mutate(country_name = case_when(
    country_name == "North Macedonia" ~ "Macedonia del Norte",
    country_name == "Lesotho" ~ "Lesoto",
    country_name == "South Africa" ~ "Sudáfrica",
    country_name == "Bosnia and Herzegovina" ~ 
      "Bosnia & Herzegovina",
    country_name == "Eswatini" ~ "Suazilandia")) %>% 
  gt(rowname_col = "country_name") %>% 
  tab_header(title = md("Top 5 mayor tasa de desempleo"),
             subtitle = md("De 1993 a 2019")) %>% 
  tab_options(heading.background.color = "tan2") %>% 
  tab_options(heading.title.font.size = 25, 
              heading.subtitle.font.size = 20,  
              column_labels.font.weight =  "bold", 
              heading.align = "center") %>% 
  tab_options(table.align = "center") %>% 
  cols_align(align = "center") %>% 
  cols_label(desemp = "Desempleo medio") %>% 
  fmt_percent(columns= 2, 
             decimals = 2,
             dec_mark = ",")
Top 5 mayor tasa de desempleo
De 1993 a 2019
Desempleo medio
Macedonia del Norte 31,54%
Lesoto 30,45%
Sudáfrica 27,99%
Bosnia & Herzegovina 25,14%
Suazilandia 24,63%
Menor desempleo
desemp_min <- paises %>% group_by(country_name) %>% 
  mutate(unemployment_rate = unemployment_rate/100) %>% 
  summarise(desemp = mean(unemployment_rate)) %>% drop_na() %>% 
  slice_min(order_by = desemp, n= 5) 

desemp_min %>% #gtTable
  mutate(country_name = ifelse(
    country_name == "Cambodia", "Camboya", country_name)) %>%
  gt(rowname_col = "country_name") %>% 
  tab_header(title = md("Top 5 menor tasa de desempleo"),
             subtitle = md("De 1993 a 2019")) %>% 
  tab_options(heading.background.color = "tan2") %>% 
  tab_options(heading.title.font.size = 25, 
              heading.subtitle.font.size = 20,  
              column_labels.font.weight =  "bold", 
              heading.align = "center") %>% 
  tab_options(table.align = "center") %>% 
  cols_align(align = "center") %>% 
  cols_label(desemp = "Desempleo medio") %>% 
  fmt_percent(columns= 2, 
              decimals = 2,
              dec_mark = ",")
Top 5 menor tasa de desempleo
De 1993 a 2019
Desempleo medio
Myanmar 0,87%
Camboya 0,88%
Rwanda 0,88%
Bahrain 1,14%
Qatar 1,17%

Como podemos observar, existe una gran diferencia entre los países con mayor y menor desempleo. Cabe preguntarnos como ha evolucionado este indicador a lo largo del periodo para cada grupo de países.

b <- paises %>% 
  select(country_name, year, unemployment_rate) %>%  
  mutate(country_name = case_when(
    country_name == "North Macedonia" ~ "Macedonia del Norte",
    country_name == "Lesotho" ~ "Lesoto",
    country_name == "South Africa" ~ "Sudáfrica",
    country_name == "Bosnia and Herzegovina" ~ 
      "Bosnia & Herzegovina",
    country_name == "Eswatini" ~ "Suazilandia",
    country_name == "Cambodia" ~ "Camboya",
    TRUE ~ country_name)) %>% 
  filter(country_name %in% c("Myanmar", "Camboya",
                             "Rwanda", "Bahrain", "Qatar",
                             "Macedonia del Norte", "Lesoto",
                             "Sudáfrica", "Bosnia & Herzegovina",
                             "Suazilandia")) %>% 
  mutate(unemployment_rate = unemployment_rate/100) %>% 
  ggplot(aes(x= year, y= unemployment_rate, color= country_name)) +
  geom_line(size = 1.2) +
  scale_y_continuous(limits = c(0, 0.4),
                     labels = scales::percent_format(accuracy = 1)) +
  scale_color_discrete(labels = c("Bahrain", "Bosnia\n& Herzegovina",
                                  "Camboya", "Lesoto", 
                                  "Macedonia\ndel Norte", "Myanmar",
                                  "Qatar", "Rwanda", "Suazilandia",
                                  "Sudáfrica")) +
  scale_color_viridis_d() +
  labs(title = "Evolución del TOP 5\nmayor y menor tasa de desempleo",
       x = "Tasa de desempleo",
       y = "Año",
       color = "Países") +
  theme_ipsum() +
  theme(plot.title = element_text(hjust = 0.5),
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12),
        legend.title = element_text(face = "bold"))

pp <- ggplotly(b, width = 600, height = 500)

htmltools::div(pp, align = "center" )

Como podíamos imaginar, los países con bajas tasas de desempleo han matenido constante este indicador a lo largo del periodo, mientras que los países con un desempleo mayor presentan una mayor variabilidad en este indicador.

4.2.3 Kilogramos de pesca según la población

Diversas causas o motivos pueden estar detrás de la piratería. Un indicador que nos puede ayudar a entender este tipo de ataques en las costas de un país es la cantidad de pesca per cápita de un país. Este indicador nos muestra cuál es la importancia que tiene esta actividad para los países. Una forma visual de mostrar estos datos es a través de un gráfico “wordcloud.”

library(wordcloud2)

pesca <- paises %>% 
  mutate(fish = total_fisheries_per_ton*1000/population) %>% 
  group_by(country_name) %>% 
  summarise(fish_pc = mean(fish, na.rm = TRUE)) %>% 
  mutate(fish_pc = round(fish_pc, digits = 2)) %>% 
  mutate(country_name = case_when(
    country_name == "Greenland" ~ "Groenlandia",
    country_name == "Iceland" ~ "Islandia",
    country_name == "Marshall Islands" ~ "Islas Marshall",
    country_name == "Maldives" ~ "Maldivas",
    country_name == "Faroe Islands" ~ "Islas Faroe",
    country_name == "St. Vincent and the Grenadines" ~ 
      "San Vicente y las Granadinas", 
    country_name == "Norway" ~ "Noruega",
    TRUE ~ country_name)) %>% 
  slice_max(order_by = fish_pc, n=200)

wordcloud2(pesca, shape= "diamond", size = 0.8)

Claramente, observamos que las Islas Feroe, Islandia y Groenlandia son los países en los que más kilogramos por habitante se pesca, seguidos de lejos por otros países como Noruega, las Islas Marshall o las Seychelles. No obstante, llama la atención que los tres principales territores en los cuáles la pesca es una de las principales actividades sean dos territorios autónomos del Reino de Dinamarca (Las Islas Feroe y Groenlandia) y un país con un pasado vinculado a este reino, como es Islandia.

4.2.4 PIB per capita

Para terminar con esta sección, prestaremos especial atención al PIB per cápita y al PIB industrial per cápita. Como bien sabemos, el PIB per cápita es uno de los indicadores más usados para medir la riqueza de un país. Este mide la producción de un país por cada habitante. De esta forma, es posible realizar comparaciones entre países de distinta dimensión y población. Por otra parte, el PIB industrial nos indica a qué porcentaje del PIB contribuye la industria de un país. Resulta interesante conocer cuál es la relación entre ambas variables.

gdp_pc <- paises %>% group_by(country_name) %>% 
  mutate(ind_pc = industryofgdp*GDP) %>% 
  select(country_name, year, region, GDP, ind_pc) %>%  
  drop_na(ind_pc)  

gdp_pc %>% ggplot(aes(x= GDP, y= ind_pc)) +
  geom_point(color = "salmon2", size = 2) +
  scale_color_discrete(labels = c("Asia del Este\n& Pacífico",
                                  "Europa\n& Asia Central",
                                  "Latino América\n& Caribe",
                                  "Oriente Medio\n& Norte de Africa",
                                  "América\ndel Norte",
                                  "Sur\nde Asia",
                                  "África\nSub-Sahariana")) + 
  theme_minimal() +
  transition_states(year) +
  labs(title = "Evolución del PIB industrial per capita
en función del PIB per capita\n Year : {closest_state}", 
       y = "PIB industrial per capita",
       x = "PIB per capita",
       color = "Regiones") +
  theme(plot.title = element_text(size = 20, hjust = 0.5,
                                  face = "bold"),
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12),
        legend.title = element_text(face = "bold", hjust = 0.5))

A medida que aumenta el PIB per cápita de un país, aumenta el PIB industrial per cápita. Esta conclusión parece obvia incluso antes de realizar el gráfico anterior. Sin embargo, del gráfico podemos extraer una idea bastante interesante. Conforme aumenta el PIB per cápita, ademas de aumentar el PIB per cápita industrial, también lo hace la varianza entre ambas variables. Este hecho nos indica que, aunque es cierto que el desarrollo industrial es un potente motor para el crecimiento, no es el único. Esto se debe a que conforme un país aumenta su riqueza otros sectores comienzan a ganar un mayor peso, como es el caso del sector servicios. Así, no es de extrañar que entre los países más ricos encontremos mayores diferencias en cuanto a la contribución que realiza su industria a la riqueza del país.

5. Conclusiones

En este correlograma vemos los coeficientes de correlación entre las variables de las que disponemos de los países, más una nueva variable que es el número de ataques pirata ocurridos en las aguas de cada país en un determinado año. Como vemos, algunas relaciones son justamente las que podríamos esperar: los países más grandes suelen tener ejércitos más grandes, etc. Sin embargo, cuando ponemos el foco en la relación con el número de ataques, que es lo que más interesa en este trabajo, encontramos relaciones débiles de difícil interpretación. Creemos que esta vía de análisis carece de mayor interés.

full_by_nearest <- full_join(pirate_attacks, country_data, by = c("nearest_country" = "country", "year" = "year"))|> filter(!is.na(longitude)) 

full_by_nearest <- full_by_nearest |> select(1,7,11:21) |>  group_by(nearest_country, year) |> mutate(nattacks = n()) |> ungroup() |> distinct()%>% select(where(is.numeric))

cor <- cor(full_by_nearest, use = "complete.obs")

corrplot(cor, type="upper", order="hclust", insig = "blank")

Para concluir, reconoceremos que este trabajo ha sido exitoso identificando en los datos ciertos patrones en los ataques pirata ya apreciados por la literatura, como la prevalencia de secuestros en la costa de África o el movimiento de las zonas calientes de Asia a África. No ha habido el mismo éxito buscando correlaciones con las variables de las que disponemos de los países, lo cual no quiere decir, a nuestro juicio, que no existan otras maneras de enriquecer este análisis.

6. Bibliografía

Benden, Feng, P., and G. V. Dalla Riva. 2021. “Crime at Sea: A Global Database of Maritime Pirate Attacks (1993–2020).” Journal of Open Humanities Data, no. 7: 19.
Bowden, Anna, Kaija Hurlburt, Charles Marts, Andrew Lee, Eamon Aloyo, Peter Chalk, and Pierre Cariou. 2010. “The Economic Costs of Maritime Piracy.” Null. https://doi.org/null.
Dillon, Dana R., and Dana R. Dillon. 2005. “Maritime Piracy: Defining the Problem.” SAIS Review. https://doi.org/10.1353/sais.2005.0005.
Fu, Xiaowen, Adolf K. Y. Ng, and Yui-yip Lau. 2010. “The Impacts of Maritime Piracy on Global Economic Development: The Case of Somalia.” Maritime Policy & Management. https://doi.org/10.1080/03088839.2010.524736.
Haywood, Robert, and Roberta Spivak. 2013. Maritime Piracy. Routledge.
Nincic, Donna J. 2009. “Maritime Piracy in Africa: The Humanitarian Dimension.” African Security Review. https://doi.org/10.1080/10246029.2009.9627538.
“Piracy.” 2021. In Oxford English Dictionary. Oxford University Press.



Información de mi R-sesión:

- Session info ---------------------------------------------------------------
 setting  value                       
 version  R version 4.1.1 (2021-08-10)
 os       Windows 10 x64              
 system   x86_64, mingw32             
 ui       RTerm                       
 language (EN)                        
 collate  Spanish_Spain.1252          
 ctype    Spanish_Spain.1252          
 tz       Europe/Paris                
 date     2021-12-16                  

- Packages -------------------------------------------------------------------
 package           * version    date       lib source                        
 abind               1.4-5      2016-07-21 [1] CRAN (R 4.1.0)                
 ape                 5.5        2021-04-25 [1] CRAN (R 4.1.2)                
 assertthat          0.2.1      2019-03-21 [1] CRAN (R 4.1.1)                
 backports           1.2.1      2020-12-09 [1] CRAN (R 4.1.0)                
 base64enc           0.1-3      2015-07-28 [1] CRAN (R 4.1.0)                
 bit                 4.0.4      2020-08-04 [1] CRAN (R 4.1.1)                
 bit64               4.0.5      2020-08-30 [1] CRAN (R 4.1.1)                
 bitops              1.0-7      2021-04-24 [1] CRAN (R 4.1.0)                
 broom               0.7.9      2021-07-27 [1] CRAN (R 4.1.1)                
 bslib               0.3.1      2021-10-06 [1] CRAN (R 4.1.1)                
 caTools             1.18.2     2021-03-28 [1] CRAN (R 4.1.1)                
 cellranger          1.1.0      2016-07-27 [1] CRAN (R 4.1.1)                
 checkmate           2.0.0      2020-02-06 [1] CRAN (R 4.1.1)                
 class               7.3-19     2021-05-03 [2] CRAN (R 4.1.1)                
 classInt            0.4-3      2020-04-07 [1] CRAN (R 4.1.1)                
 cli                 3.1.0      2021-10-27 [1] CRAN (R 4.1.1)                
 clipr               0.7.1      2020-10-08 [1] CRAN (R 4.1.1)                
 cluster             2.1.2      2021-04-17 [2] CRAN (R 4.1.1)                
 codetools           0.2-18     2020-11-04 [2] CRAN (R 4.1.1)                
 collapsibleTree     0.1.7      2018-08-22 [1] CRAN (R 4.1.2)                
 colorspace          2.0-2      2021-06-24 [1] CRAN (R 4.1.1)                
 commonmark          1.7        2018-12-01 [1] CRAN (R 4.1.1)                
 corrplot          * 0.90       2021-06-30 [1] CRAN (R 4.1.1)                
 countrycode         1.3.0      2021-07-15 [1] CRAN (R 4.1.1)                
 covid19.analytics * 2.1.1      2021-09-14 [1] CRAN (R 4.1.2)                
 crayon              1.4.2      2021-10-29 [1] CRAN (R 4.1.1)                
 crosstalk           1.1.1      2021-01-12 [1] CRAN (R 4.1.1)                
 curl                4.3.2      2021-06-23 [1] CRAN (R 4.1.1)                
 data.table          1.14.0     2021-02-21 [1] CRAN (R 4.1.1)                
 data.tree           1.0.0      2020-08-03 [1] CRAN (R 4.1.2)                
 DBI                 1.1.1      2021-01-15 [1] CRAN (R 4.1.1)                
 dbplyr              2.1.1      2021-04-06 [1] CRAN (R 4.1.1)                
 desc                1.3.0      2021-03-05 [1] CRAN (R 4.1.1)                
 deSolve             1.30       2021-10-07 [1] CRAN (R 4.1.2)                
 details             0.2.1      2020-01-12 [1] CRAN (R 4.1.1)                
 dichromat           2.0-0      2013-01-24 [1] CRAN (R 4.1.0)                
 digest              0.6.28     2021-09-23 [1] CRAN (R 4.1.1)                
 dplyr             * 1.0.7      2021-06-18 [1] CRAN (R 4.1.1)                
 DT                * 0.19       2021-09-02 [1] CRAN (R 4.1.1)                
 e1071               1.7-8      2021-07-28 [1] CRAN (R 4.1.1)                
 ellipsis            0.3.2      2021-04-29 [1] CRAN (R 4.1.1)                
 evaluate            0.14       2019-05-28 [1] CRAN (R 4.1.1)                
 extrafont           0.17       2014-12-08 [1] CRAN (R 4.1.1)                
 extrafontdb         1.0        2012-06-11 [1] CRAN (R 4.1.1)                
 fansi               0.5.0      2021-05-25 [1] CRAN (R 4.1.1)                
 farver              2.1.0      2021-02-28 [1] CRAN (R 4.1.1)                
 fastmap             1.1.0      2021-01-25 [1] CRAN (R 4.1.1)                
 forcats           * 0.5.1      2021-01-27 [1] CRAN (R 4.1.1)                
 foreign             0.8-81     2020-12-22 [2] CRAN (R 4.1.1)                
 Formula           * 1.2-4      2020-10-16 [1] CRAN (R 4.1.0)                
 fs                  1.5.0      2020-07-31 [1] CRAN (R 4.1.1)                
 gdtools             0.2.3      2021-01-06 [1] CRAN (R 4.1.1)                
 generics            0.1.1      2021-10-25 [1] CRAN (R 4.1.1)                
 gganimate         * 1.0.7      2020-10-15 [1] CRAN (R 4.1.1)                
 ggplot2           * 3.3.5      2021-06-25 [1] CRAN (R 4.1.1)                
 ggrepel           * 0.9.1      2021-01-15 [1] CRAN (R 4.1.1)                
 ggthemes          * 4.2.4      2021-01-20 [1] CRAN (R 4.1.1)                
 gifski              1.4.3-1    2021-05-02 [1] CRAN (R 4.1.1)                
 glue                1.5.0      2021-11-07 [1] CRAN (R 4.1.2)                
 gplots              3.1.1      2020-11-28 [1] CRAN (R 4.1.1)                
 gridExtra           2.3        2017-09-09 [1] CRAN (R 4.1.1)                
 gt                * 0.3.1.9000 2021-11-26 [1] Github (rstudio/gt@e441737)   
 gtable              0.3.0      2019-03-25 [1] CRAN (R 4.1.1)                
 gtools              3.9.2      2021-06-06 [1] CRAN (R 4.1.1)                
 haven               2.4.3      2021-08-04 [1] CRAN (R 4.1.1)                
 here                1.0.1      2020-12-13 [1] CRAN (R 4.1.1)                
 highr               0.9        2021-04-16 [1] CRAN (R 4.1.1)                
 Hmisc             * 4.5-0      2021-02-28 [1] CRAN (R 4.1.1)                
 hms                 1.1.1      2021-09-26 [1] CRAN (R 4.1.1)                
 hrbrthemes        * 0.8.0      2020-03-06 [1] CRAN (R 4.1.1)                
 htmlTable           2.2.1      2021-05-18 [1] CRAN (R 4.1.1)                
 htmltools           0.5.2      2021-08-25 [1] CRAN (R 4.1.1)                
 htmlwidgets         1.5.4      2021-09-08 [1] CRAN (R 4.1.1)                
 httpuv              1.6.3      2021-09-09 [1] CRAN (R 4.1.1)                
 httr                1.4.2      2020-07-20 [1] CRAN (R 4.1.1)                
 jpeg                0.1-9      2021-07-24 [1] CRAN (R 4.1.0)                
 jquerylib           0.1.4      2021-04-26 [1] CRAN (R 4.1.1)                
 jsonlite            1.7.2      2020-12-09 [1] CRAN (R 4.1.1)                
 KernSmooth          2.23-20    2021-05-03 [2] CRAN (R 4.1.1)                
 klippy            * 0.0.0.9500 2021-11-16 [1] Github (rlesur/klippy@378c247)
 knitr             * 1.36       2021-09-29 [1] CRAN (R 4.1.1)                
 labeling            0.4.2      2020-10-20 [1] CRAN (R 4.1.0)                
 later               1.3.0      2021-08-18 [1] CRAN (R 4.1.1)                
 lattice           * 0.20-44    2021-05-02 [1] CRAN (R 4.1.1)                
 latticeExtra        0.6-29     2019-12-19 [1] CRAN (R 4.1.1)                
 lazyeval            0.2.2      2019-03-15 [1] CRAN (R 4.1.1)                
 leafem              0.1.6      2021-05-24 [1] CRAN (R 4.1.1)                
 leaflet             2.0.4.1    2021-01-07 [1] CRAN (R 4.1.1)                
 leafsync            0.1.0      2019-03-05 [1] CRAN (R 4.1.1)                
 lifecycle           1.0.1      2021-09-24 [1] CRAN (R 4.1.1)                
 lubridate         * 1.7.10     2021-02-26 [1] CRAN (R 4.1.1)                
 lwgeom              0.2-7      2021-07-28 [1] CRAN (R 4.1.1)                
 magick              2.7.3      2021-08-18 [1] CRAN (R 4.1.1)                
 magrittr            2.0.1      2020-11-17 [1] CRAN (R 4.1.1)                
 mapdata           * 2.3.0      2018-03-30 [1] CRAN (R 4.1.2)                
 maps              * 3.3.0      2018-04-03 [1] CRAN (R 4.1.1)                
 Matrix              1.3-4      2021-06-01 [2] CRAN (R 4.1.1)                
 matrixStats         0.60.1     2021-08-23 [1] CRAN (R 4.1.1)                
 mime                0.12       2021-09-28 [1] CRAN (R 4.1.1)                
 modelr              0.1.8      2020-05-19 [1] CRAN (R 4.1.1)                
 munsell             0.5.0      2018-06-12 [1] CRAN (R 4.1.1)                
 nlme                3.1-152    2021-02-04 [2] CRAN (R 4.1.1)                
 nnet                7.3-16     2021-05-03 [2] CRAN (R 4.1.1)                
 openxlsx            4.2.4      2021-06-16 [1] CRAN (R 4.1.1)                
 pander              0.6.4      2021-06-13 [1] CRAN (R 4.1.1)                
 patchwork         * 1.1.1      2020-12-17 [1] CRAN (R 4.1.1)                
 pheatmap            1.0.12     2019-01-04 [1] CRAN (R 4.1.2)                
 pillar              1.6.4      2021-10-18 [1] CRAN (R 4.1.1)                
 pkgconfig           2.0.3      2019-09-22 [1] CRAN (R 4.1.1)                
 plotly            * 4.9.4.1    2021-06-18 [1] CRAN (R 4.1.1)                
 plyr                1.8.6      2020-03-03 [1] CRAN (R 4.1.1)                
 png               * 0.1-7      2013-12-03 [1] CRAN (R 4.1.0)                
 prettyunits         1.1.1      2020-01-24 [1] CRAN (R 4.1.1)                
 progress            1.2.2      2019-05-16 [1] CRAN (R 4.1.1)                
 promises            1.2.0.1    2021-02-11 [1] CRAN (R 4.1.1)                
 proxy               0.4-26     2021-06-07 [1] CRAN (R 4.1.1)                
 pryr                0.1.5      2021-07-26 [1] CRAN (R 4.1.1)                
 purrr             * 0.3.4      2020-04-17 [1] CRAN (R 4.1.1)                
 R6                  2.5.1      2021-08-19 [1] CRAN (R 4.1.1)                
 rapportools         1.0        2014-01-07 [1] CRAN (R 4.1.1)                
 raster              3.5-2      2021-10-11 [1] CRAN (R 4.1.1)                
 RColorBrewer        1.1-2      2014-12-07 [1] CRAN (R 4.1.0)                
 Rcpp                1.0.7      2021-07-07 [1] CRAN (R 4.1.1)                
 readr             * 2.0.1      2021-08-10 [1] CRAN (R 4.1.1)                
 readxl              1.3.1      2019-03-13 [1] CRAN (R 4.1.1)                
 rentrez             1.2.3      2020-11-10 [1] CRAN (R 4.1.2)                
 reprex              2.0.1      2021-08-05 [1] CRAN (R 4.1.1)                
 rio                 0.5.27     2021-06-21 [1] CRAN (R 4.1.1)                
 rlang               0.4.12     2021-10-18 [1] CRAN (R 4.1.1)                
 rmarkdown           2.11       2021-09-14 [1] CRAN (R 4.1.1)                
 rpart               4.1-15     2019-04-12 [2] CRAN (R 4.1.1)                
 rprojroot           2.0.2      2020-11-15 [1] CRAN (R 4.1.1)                
 rstudioapi          0.13       2020-11-12 [1] CRAN (R 4.1.1)                
 Rttf2pt1            1.3.9      2021-07-22 [1] CRAN (R 4.1.1)                
 rvest               1.0.1      2021-07-26 [1] CRAN (R 4.1.1)                
 s2                  1.0.6      2021-06-17 [1] CRAN (R 4.1.1)                
 sass                0.4.0      2021-05-12 [1] CRAN (R 4.1.1)                
 scales              1.1.1      2020-05-11 [1] CRAN (R 4.1.1)                
 sessioninfo         1.1.1      2018-11-05 [1] CRAN (R 4.1.1)                
 sf                  1.0-2      2021-07-26 [1] CRAN (R 4.1.1)                
 shiny               1.7.1      2021-10-02 [1] CRAN (R 4.1.1)                
 shinycssloaders     1.0.0      2020-07-28 [1] CRAN (R 4.1.2)                
 shinydashboard      0.7.2      2021-09-30 [1] CRAN (R 4.1.2)                
 sp                  1.4-5      2021-01-10 [1] CRAN (R 4.1.1)                
 stars               0.5-3      2021-06-08 [1] CRAN (R 4.1.1)                
 stringi             1.7.5      2021-10-04 [1] CRAN (R 4.1.1)                
 stringr           * 1.4.0      2019-02-10 [1] CRAN (R 4.1.1)                
 summarytools      * 1.0.0      2021-07-28 [1] CRAN (R 4.1.1)                
 survival          * 3.2-11     2021-04-26 [2] CRAN (R 4.1.1)                
 systemfonts         1.0.3      2021-10-13 [1] CRAN (R 4.1.1)                
 terra               1.4-11     2021-10-11 [1] CRAN (R 4.1.1)                
 tibble            * 3.1.5      2021-09-30 [1] CRAN (R 4.1.1)                
 tidyr             * 1.1.4      2021-09-27 [1] CRAN (R 4.1.1)                
 tidyselect          1.1.1      2021-04-30 [1] CRAN (R 4.1.1)                
 tidyverse         * 1.3.1      2021-04-15 [1] CRAN (R 4.1.1)                
 tmap              * 3.3-2      2021-06-16 [1] CRAN (R 4.1.1)                
 tmaptools           3.1-1      2021-01-19 [1] CRAN (R 4.1.1)                
 tweenr              1.0.2      2021-03-23 [1] CRAN (R 4.1.1)                
 tzdb                0.1.2      2021-07-20 [1] CRAN (R 4.1.1)                
 units               0.7-2      2021-06-08 [1] CRAN (R 4.1.1)                
 utf8                1.2.2      2021-07-24 [1] CRAN (R 4.1.1)                
 vctrs               0.3.8      2021-04-29 [1] CRAN (R 4.1.1)                
 viridisLite         0.4.0      2021-04-13 [1] CRAN (R 4.1.1)                
 vroom               1.5.5      2021-09-14 [1] CRAN (R 4.1.1)                
 withr               2.4.2      2021-04-18 [1] CRAN (R 4.1.1)                
 wk                  0.5.0      2021-07-13 [1] CRAN (R 4.1.1)                
 wordcloud2        * 0.2.1      2018-01-03 [1] CRAN (R 4.1.1)                
 xfun                0.26       2021-09-14 [1] CRAN (R 4.1.1)                
 XML                 3.99-0.7   2021-08-17 [1] CRAN (R 4.1.1)                
 xml2                1.3.2      2020-04-23 [1] CRAN (R 4.1.1)                
 xtable              1.8-4      2019-04-21 [1] CRAN (R 4.1.1)                
 yaml                2.2.1      2020-02-01 [1] CRAN (R 4.1.0)                
 zip                 2.2.0      2021-05-31 [1] CRAN (R 4.1.1)                

[1] C:/Users/Usuario/Documents/R/win-library/4.1
[2] C:/Program Files/R/R-4.1.1/library




LS0tDQp0aXRsZTogIkxhIHBpcmF0ZXLDrWEgZGVzZGUgMTk5MyBoYXN0YSBudWVzdHJvcyBkw61hcyINCmF1dGhvcjogIlRlb2Rvcm8gRCdBZ29zdGlubyh0ZWRhZ2FyQGFsdW1uaS51di5lcykgIFxuXG4gSm9yZ2UgR29uesOhbGV6KGpvcmdvbmFuQGFsdW1uaS51di5lcykgIFxuIFxuIEF1cm9yYSBMbG9yZXQoYXVsbG9oZUBhbHVtbmkudXYuZXMpLiBcblxuIFVuaXZlcnNpdGF0IGRlIFZhbMOobmNpYSINCmRhdGU6ICJEaWNpZW1icmUgZGUgMjAyMSAoYWN0dWFsaXphZG8gZWwgYHIgZm9ybWF0KFN5cy50aW1lKCksICclZC0lbS0lWScpYCkiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY3NzOiAiLi9hc3NldHMvbXlfY3NzX2ZpbGUuY3NzIg0KICAgIHRoZW1lOiBjb3Ntbw0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUgDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzIA0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBkZl9wcmludDoga2FibGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSINCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWINCi0tLQ0KDQpgYGB7ciBwYWNrYWdlcy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGtsaXBweSkgICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmxpYnJhcnkoa25pdHIpDQpgYGANCg0KYGBge3IgY2h1bmstc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAjcmVzdWx0cyA9ICJob2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLCBjYWNoZS5wYXRoID0gIi9jYWNoZXMvIiwgY29tbWVudCA9ICIjPiIsDQogICAgICAgICAgICAgICAgICAgICAgI2ZpZy53aWR0aCA9IDcsICNmaWcuaGVpZ2h0PSA3LCAgIA0KICAgICAgICAgICAgICAgICAgICAgICNvdXQud2lkdGggPSA3LCBvdXQuaGVpZ2h0ID0gNywNCiAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9IFRSVUUsICBmaWcuc2hvdyA9ICJob2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYXNwID0gMC44MjgsIG91dC53aWR0aCA9ICI5MCUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIikNCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpDQpgYGANCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KYGBge3Iga2xpcHB5LCBlY2hvID0gRkFMU0V9DQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoInRvcCIsICJyaWdodCIpKSAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpDQpgYGANCg0KPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+DQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gY2FzaSBpZ3VhbCwgc29sbyBIQVMgZGUgU1VTVElUVUlSICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+DQoNClRyYWJham8gZWxhYm9yYWRvIHBhcmEgbGEgYXNpZ25hdHVyYSAiUHJvZ3JhbWFjacOzbiB5IG1hbmVqbyBkZSBkYXRvcyBlbiBsYSBlcmEgZGVsIEJpZyBEYXRhIiBkZSBsYSBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEgZHVyYW50ZSBlbCBjdXJzbyAyMDIxLTIwMjIuIEVsIHJlcG8gZGVsIHRyYWJham8gZXN0w6EgW2FxdcOtXShodHRwczovL2dpdGh1Yi5jb20vam9vcmdlMDYwMy90cmFiYWpvX0JpZ0RhdGFfZXF1aXBvKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8IS0tIEVsIHDDoXJyYWZvIGRlIGFiYWpvIGhhcyBkZSBkZWphcmxvIGV4YWN0YW1lbnRlIGlndWFsLCBOTyBoYXMgZGUgY2FtYmlhciBuYWRhLS0+DQoNCkxhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmEgeSBsb3MgdHJhYmFqb3MgZGUgbWlzIGNvbXBhw7Flcm9zIHB1ZWRlbiB2ZXJzZSBbYXF1w61dKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIxLTIyLXdlYi8wNy10cmFiYWpvcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8aHIgY2xhc3M9ImxpbmVhLWJsYWNrIj4NCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShndCkNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KbGlicmFyeShocmJydGhlbWVzKQ0KbGlicmFyeShzdW1tYXJ5dG9vbHMpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShtYXBkYXRhKQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShnZ3JlcGVsKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBuZykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdyaWQpDQpgYGANCg0KIyAxLiBJbnRyb2R1Y2Npw7NuDQoNCkVuIGVzdGUgdHJhYmFqbyB0cmF0YXJlbW9zIGRlIGV4dHJhZXIgYWxndW5hcyBjb25jbHVzaW9uZXMgeSBheXVkYXIgYWwgbGVjdG9yIGEgY29tcHJlbmRlciBhbGd1bm9zIGRhdG9zIHNvYnJlIGxhIHBpcmF0ZXLDrWEgbWFyw610aW1hIGVuIGVsIG11bmRvIGFjdHVhbC4gTnVlc3RybyBkYXRhc2V0IHNlIGJhc2EgZW4gZWwgcXVlIHNlIHB1ZWRlIGVuY29udHJhciBbYXF1w61dKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vbjBuNWVuc2UvZ2xvYmFsLW1hcml0aW1lLXBpcmF0ZS1hdHRhY2tzLTE5OTMyMDIwKS4gTGEgcmVmZXJlbmNpYSBjb21wbGV0YSBlcyBlc3RhIFtAZGF0YXNldF0uDQoNCjxicj4NCg0KIyMgMS4xIENvbnRleHRvIGRlIGxhIHBpcmF0ZXLDrWEgbWFyaW5hDQoNCkEgcGVzYXIgZGUgcXVlIGxhIG1lbmNpw7NuIGRlIHBpcmF0YXMgZXZvY2EgZW4gbGEgbWVudGUgZGUgbGEgbWF5b3LDrWEgZGUgbm9zb3Ryb3Mgbm9jaW9uZXMgZGUgcnVkb3MgYXZlbnR1cmVyb3MgZGVsaW5xdWllbmRvIHBvciBzdXMgdmlkYXMgZW4gbGFzIGFndWFzIHR1cnF1ZXNhcyBkZSBhbGfDum4gcGFyYcOtc28gdHJvcGljYWwgc2lnbG9zIGF0csOhcywgbGEgcGl0YXJlcsOtYSBtYXJpbmEgZXMgdW4gcHJvYmxlbWEgYWN0dWFsIGNvbiBzZXJpYXMgaW1wbGljYWNpb25lcyBzb2NpYWxlcyB5IGVjb27Ds21pY2FzLCBxdWUgaGEgZ2FuYWRvIHRlcnJlbm8gZW4gZWwgZGlzY3Vyc28gbWVkacOhdGljbyB5IGxhIGludmVzdGlnYWNpw7NuIGFjYWTDqW1pY2EgYSBwYXJ0aXIgZGUgY2Fzb3MgdHLDoWdpY29zIGNvbW8gZWwgc2VjdWVzdHJvIGRlIHVuIGJhcmNvIHJ1c28gZW4gbGEgY29zdGEgc29tYWzDrSBlbiBzZXB0aWVtYnJlIGRlIDIwMDgsIHUgb3RybyBldmVudG8gc2ltaWxhciBzaWV0ZSBtZXNlcyBkZXNwdcOpcyBjb24gZWwgY2FyZ3Vlcm8gTWFlcnNrIEFsYWJhbWEsIHF1ZSBmdWUgcmVzdWVsdG8gY29uIGVsIHJlc2NhdGUgcG9yIHBhcnRlIGRlbCBlasOpcmNpdG8gbm9ydGVhbWVyaWNhbm8gZGUgbG9zIHJlaGVuZXMgdG9tYWRvcyBbQGhheXdvb2QyMDEzbWFyaXRpbWVdLg0KDQo8YnI+DQoNCiFbKkxhIGltYWdlbiBxdWUgc3VlbGUgdmVuaXJub3MgYSBsYSBtZW50ZSBjdWFuZG8gcGVuc2Ftb3MgZW4gcGlyYXRlcsOtYS4qXShpbWFnZW5lcy9waXJhdGFzLmpwZyl7d2lkdGg9IndpZHRoIiBoZWlnaHQ9ImhlaWdodCJ9DQoNCk5vIGV4aXN0ZSB1bmEgw7puaWNhIGRlZmluaWNpw7NuIGNsYXJhIGRlIHF1w6kgY29uc3RpdHV5ZSB1biBhdGFxdWUgcGlyYXRhLCBsbyBjdWFsIGRpZmljdWx0YSBzdSBlc3R1ZGlvIHkgbGEgZm9ybXVsYWNpw7NuIGRlIHBvbMOtdGljYXMgYWRlY3VhZGFzIHBhcmEgc3UgcmVzb2x1Y2nDs24gW0BEaWxsb25fMjAwNV0uIFJlc3VsdGEgw7p0aWwsIHBvciB0YW50bywgYXRlbmRlciBhIGxvcyBkZXRhbGxlcyBkZSBjYWRhIGV2ZW50byBzdXNjZXB0aWJsZSBkZSBzZXIgY2xhc2lmaWNhZG8gY29tbyBhY3RvIGRlIHBpcmF0ZXLDrWEgeSBhanVzdGFyIGxhIHJlc3B1ZXN0YSBpbnN0aXR1Y2lvbmFsIGFsIHByb2JsZW1hIGEgbG9zIGRpc3RpbnRvcyB0aXBvcyBkZSBhdGFxdWVzIHF1ZSBwdWVkZW4gcHJvZHVjaXJzZS4gRXN0ZSBkYXRhc2V0IHJlc3VsdGEgZGUgdXRpbGlkYWQganVzdGFtZW50ZSBwb3IgcGVybWl0aXIgZGlmZXJlbmNpYXIgZW50cmUgZGlzdGludGFzIHZhcmllZGFkZXMgZGUgYXRhcXVlLiBMbyBxdWUgdW5lIHRvZG9zIGVsbG9zIHZpZW5lIHJlY29naWRvIHBvciBsYSBkZWZpbmljacOzbiBxdWUgcHJvcG9yY2lvbmEgZWwgZGljY2lvbmFyaW8gZGUgT3hmb3JkIGRlbCB0w6lybWlubyBwaXJhY3kgW0BveGZvcmRdOg0KDQo+ICpUaGUgYWN0aW9uIG9mIGNvbW1pdHRpbmcgcm9iYmVyeSwga2lkbmFwLCBvciB2aW9sZW5jZSBhdCBzZWEgb3IgZnJvbSB0aGUgc2VhIHdpdGhvdXQgbGF3ZnVsIGF1dGhvcml0eSwgZXNwZWNpYWxseSBieSBvbmUgdmVzc2VsIGFnYWluc3QgYW5vdGhlcjsgYW4gaW5zdGFuY2Ugb2YgdGhpcy4qDQoNCkxhIHBpcmF0ZXLDrWEgZW4gZWwgbXVuZG8gYWN0dWFsIGVzIHVuYSBsYWNyYSBwYXJhIGVsIGRlc2Fycm9sbG8sIGNvbiB1biBjb3N0ZSBlY29uw7NtaWNvIGVzdGltYWRvIGVudHJlIGxvcyA3IHkgMTIgbWlsIG1pbGxvbmVzIGRlIGTDs2xhcmVzIGFtZXJpY2Fub3MgYWwgYcOxbywgbyBpbmNsdXNvIG3DoXMgW0BCb3dkZW5fMjAxMF0uIFNpbiBlbWJhcmdvLCBlcyBwcm9iYWJsZSBxdWUgbGFzIHBlb3JlcyBjb25zZWN1YW5jaWFzIHNlYW4gbGFzIGh1bWFuaXRhcmlhcywgcXVlIHNlIGRlamFuIHNlbnRpciBlc3BlY2lhbG1lbnRlIGVuIGFxdWVsbG9zIHBhw61zZSBzdWJzZGVzYXJyb2xsYWRvcyBlbiBjdXlhcyBhZ3VhcyBzZSBlbXBsYXphbiBsYSBtYXlvcsOtYSBkZSBhdGFxdWVzLiBFcyBpbXBvcnRhbnRlIGNvbnNpZGVyYXIgcXVlIGxhIG1heW9yw61hIGRlIGFjdG9zIGRlIHBpcmF0ZXLDrWEgc3VjZWRlbiBlbiB1biBjb250ZXh0byBtYXlvciBkZSB2aW9sZW5jaWEgeSBkZXNvcmRlbiBxdWUgY2FzaSBzaWVtcHJlIHZhIGRlIGxhIG1hbm8gZGUgYWx0b3Mgbml2ZWxlcyBkZSBjb3JydXBjacOzbiB5IGxsZWdhIGEgaW5jbHVpciBndWVycmFzIGNpdmlsZXMsIHkgcXVlIGNvbW8gbcOtbmltbyBjb25kaWNpb25hIGxhIHZpZGEgZGUgbGEgcG9ibGFjacOzbiBsb2NhbCBhIGNhdXNhIGRlIGxhcyBkaXN0b3JzaW9uZXMgcXVlIGdlbmVyYSBlbiBsb3Mgc2VjdG9yZXMgcGVzcXVlcm8geSBkZSBleHBsb3RhY2nDs24gbWluZXJhIHkgcGV0cm9sw61mZXJhLCBhIG1lbnVkbyBwcmluY2lwYWxlcyBmdWVudGVzIGRlIHJpcXVlemEgZGUgbGFzIGNvbXVuaWRhZGVzIGNvc3RlcmFzIGRlIGVzdG9zIHBhw61zZXMgW0BOaW5jaWNfMjAwOV1bQEZ1XzIwMTBdLg0KDQpOdWVzdHJvIGFuw6FsaXNpcyB2YSBhIHBlcm1pdGlyIGlkZW50aWZpY2FyIGFsZ3VuYXMgZGUgbGFzIHRlbmRlbmNpYXMgcXVlIGhhbiBkZWZpbmlkbyBsYSBldm9sdWNpw7NuIGRlIGxhIHBpcmF0ZXLDrWEgZW4gZXN0b3Mgw7psdGltb3MgYcOxb3MsIGVzcGVjaWFsbWVudGUgZW4gbG8gcmVmZXJlbnRlIGEgcHJldmFsZW5jaWEgZGUgbG9zIHRpcG9zIGRlIGF0YXF1ZXMgeSBtb3ZpbWllbnRvIGRlIGxhcyAiem9uYXMgY2FsaWVudGVzIiBkZSBsYSBwaXJhdGVyw61hIGludGVybmFjaW9uYWwuIFRhbWJpw6luIHZhbW9zIGEgY29udGV4dHVhbGl6YXIgZXN0YSBpbmZvcm1hY2nDs24gY29uIGRhdG9zIGRlIGNhcsOhY3RlciBlY29uw7NtaWNvLCBzb2NpYWwgeSBwb2zDrXRpY28uDQoNCiMgMi4gTWFuZWpvIGRlIGxvcyBkYXRvcyANCg0KIyMjIyB7LnRhYnNldH0NCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvPUZBTFNFfQ0KI1ByaW1lcm8gbG8gZXZhbHVhbW9zIHBlcm8gbm8gbG9zIG1vc3RyYW1vcw0KIyBEQVRBIFNPVVJDRTogQmVuZGVuLCBQLiwgRmVuZywgQS4sIEhvd2VsbCwgQy4gYW5kIERhbGxhIFJpdmEsIEcuVi4sIDIwMjEuIENyaW1lIGF0IFNlYTogQSBHbG9iYWwgRGF0YWJhc2Ugb2YgTWFyaXRpbWUgUGlyYXRlIEF0dGFja3MgKDE5OTPigJMyMDIwKS4gSm91cm5hbCBvZiBPcGVuIEh1bWFuaXRpZXMgRGF0YSwgNywgcC4xOS4gRE9JOiBodHRwOi8vZG9pLm9yZy8xMC41MzM0L2pvaGQuMzkNCg0KDQpjb3VudHJ5X2NvZGVzIDwtIHJlYWRfY3N2KCJkYXRvcy9jb3VudHJ5X2NvZGVzLmNzdiIpDQoNCmNvdW50cnlfaW5kaWNhdG9ycyA8LSByZWFkX2NzdigiZGF0b3MvY291bnRyeV9pbmRpY2F0b3JzLmNzdiIpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHJlYWRfY3N2KCJkYXRvcy9waXJhdGVfYXR0YWNrcy5jc3YiKQ0KDQpjb3VudHJ5X2RhdGEgPC0gZnVsbF9qb2luKGNvdW50cnlfY29kZXMsIGNvdW50cnlfaW5kaWNhdG9ycywgYnkgPSBjKCJjb3VudHJ5IiA9ICJjb3VudHJ5IikpDQogDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUoeWVhciA9IHllYXIoZGF0ZSkpDQoNCg0KcGlyYXRlX2F0dGFja3MgPC0gcGlyYXRlX2F0dGFja3MgJT4lIG11dGF0ZShhdHRhY2tfdHlwZSA9IGNhc2Vfd2hlbigNCiAgYXR0YWNrX3R5cGUgPT0gIkJvYXJkaW5nIiB+ICJCb2FyZGVkIiwgDQogIFRSVUUgfiBhdHRhY2tfdHlwZSkpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUodmVzc2VsX3N0YXR1cyA9IGNhc2Vfd2hlbigNCiAgdmVzc2VsX3N0YXR1cyA9PSAic3RlYW1pbmciIH4gIlN0ZWFtaW5nIiwgDQogIFRSVUUgfiB2ZXNzZWxfc3RhdHVzKSkNCg0KcGlyYXRlX2F0dGFja3MgPC0gcGlyYXRlX2F0dGFja3MgJT4lIG11dGF0ZSh2ZXNzZWxfdHlwZSA9IGNhc2Vfd2hlbigNCiAgdmVzc2VsX3R5cGUgPT0gIkJVTEsgQ0FSUklFUiIgfiAiQnVsayBDYXJyaWVyIiwgDQogIFRSVUUgfiB2ZXNzZWxfdHlwZSkpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUodmVzc2VsX3R5cGUgPSBjYXNlX3doZW4oDQogIHZlc3NlbF90eXBlID09ICJDT05UQUlORVIiIH4gIkNvbnRhaW5lciIsIA0KICBUUlVFIH4gdmVzc2VsX3R5cGUpKQ0KDQpwaXJhdGVfYXR0YWNrcyA8LSBwaXJhdGVfYXR0YWNrcyAlPiUgbXV0YXRlKHZlc3NlbF90eXBlID0gY2FzZV93aGVuKA0KICB2ZXNzZWxfdHlwZSA9PSAiUFJPRFVDVCBUQU5LRVIiIH4gIlByb2R1Y3QgVGFua2VyIiwgDQogIFRSVUUgfiB2ZXNzZWxfdHlwZSkpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUodmVzc2VsX3R5cGUgPSBjYXNlX3doZW4oDQogIHZlc3NlbF90eXBlID09ICJPZmZzaG9yZSBTdXBwbHkgc2hpcCIgfiAiT2Zmc2hvcmUgU3VwcGx5IFNoaXAiLCANCiAgVFJVRSB+IHZlc3NlbF90eXBlKSkNCg0KcGlyYXRlX2F0dGFja3MgPC0gcGlyYXRlX2F0dGFja3MgJT4lIG11dGF0ZSh2ZXNzZWxfdHlwZSA9IGNhc2Vfd2hlbigNCiAgdmVzc2VsX3R5cGUgPT0gIk9GRlNIT1JFIFNVUFBMWSBTSElQIiB+ICJPZmZzaG9yZSBTdXBwbHkgU2hpcCIsIA0KICBUUlVFIH4gdmVzc2VsX3R5cGUpKQ0KDQpwaXJhdGVfYXR0YWNrcyA8LSBwaXJhdGVfYXR0YWNrcyAlPiUgbXV0YXRlKHZlc3NlbF90eXBlID0gY2FzZV93aGVuKA0KICB2ZXNzZWxfdHlwZSA9PSAiT2Zmc2hvcmUgU3VwcGx5IiB+ICJPZmZzaG9yZSBTdXBwbHkgU2hpcCIsIA0KICBUUlVFIH4gdmVzc2VsX3R5cGUpKQ0KDQpybShjb3VudHJ5X2NvZGVzLCBjb3VudHJ5X2luZGljYXRvcnMpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUoeWVhciA9IGFzLmludGVnZXIoeWVhcikpDQoNCmZ1bGxfYnlfbmVhcmVzdCA8LSBmdWxsX2pvaW4ocGlyYXRlX2F0dGFja3MsIGNvdW50cnlfZGF0YSwgYnkgPSBjKCJuZWFyZXN0X2NvdW50cnkiID0gImNvdW50cnkiLCAieWVhciIgPSAieWVhciIpKXw+IGZpbHRlcighaXMubmEobG9uZ2l0dWRlKSkgDQoNCmBgYA0KDQojIyMjIyAqKkVzdHJ1Y3R1cmEgZGUgbG9zIGRhdG9zKioNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQoNCiMgbnVtZXJvIGRlIGF0YXF1ZXMNCg0Kbl9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzIHw+ICBucm93KCkgfD4gYXMuaW50ZWdlcigpDQoNCg0KIyBwZXJpb2RvIGRlIGHDsW9zOiBkZXNkZSBmaXJzdF95ZWFyIGhhc3RhIGxhc3RfeWVhcg0KDQpmaXJzdF95ZWFyIDwtIHBpcmF0ZV9hdHRhY2tzIHw+IHNlbGVjdCh5ZWFyKSB8PiBzbGljZV9oZWFkKG4gPSAxKSB8PiBhcy5pbnRlZ2VyKCkNCg0KbGFzdF95ZWFyIDwtIHBpcmF0ZV9hdHRhY2tzIHw+IHNlbGVjdCh5ZWFyKSB8PiAgc2xpY2VfdGFpbChuID0gMSkgfD4gYXMuaW50ZWdlcigpDQpgYGANCg0KVmFtb3MgYSBhbmFsaXphciB1biBkYXRhc2V0IHF1ZSBjb250aWVuZSBpbmZvcm1hY2nDs24gc29icmUgYHIgbl9hdHRhY2tzYCBhdGFxdWVzIHBpcmF0YSBvY3Vycmlkb3MgZW50cmUgYHIgZmlyc3RfeWVhcmAgeSBgciBsYXN0X3llYXJgLiBFc3RhIHRhYmxhIHBlcm1pdGUgYXByZWNpYXIgZWwgdGlwbyBkZSBkYXRvcyBxdWUgdGVuZW1vczoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCmxpYnJhcnkoRFQpDQoNCmRhdGF0YWJsZShwaXJhdGVfYXR0YWNrcywgcm93bmFtZXMgPSBGQUxTRSwgZmlsdGVyPSJ0b3AiLCBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsIHNjcm9sbFg9VCkpDQoNCmBgYA0KDQojIyMjIyAqKkhhY2llbmRvIGxvcyBkYXRvcyB0aWR5KioNCg0KQXF1w60gbW9zdHJhcmVtb3MgY29tbyBoZW1vcyB0cmF0YWRvIGxvcyBkYXRvcyBwYXJhIHBvZGVyIGxsZXZhciBhIGNhYm8gbnVlc3Ryb3MgYW7DoWxpc2lzLiBQYXJhIGVsbG8gaGVtb3MgdW5pZG8gZG9zIGRlIGxvcyBkYXRhc2V0cyBxdWUgdGVuw61hbW9zIHkgaGVtb3MgdHJhdGFkbyBkZSBsaW1waWFyIGxvcyBkYXRvcy4gTGFzIHByaW5jaXBhbGVzIGxhYm9yZXMgaGFuIGNvbnNpc3RpZG8gZW4gY29ycmVnaXIgaW5jb25zaXN0ZW5jaWFzIGVuIGxvcyBub21icmVzIGRlIHRpcG9zIGRlIGF0YXF1ZXMsIGJhcmNvcy4uLiBhZGVtw6FzIGRlIGN1ZXN0aW9uZXMgYWxnbyBtw6FzIHTDqWNuaWNhcyBkZSBtYW5pcHVsYWNpw7NuIGRlIGxhIGV4cHJlc2nDs24gZGUgZmVjaGEgeSB0aXBvIGRlIHZhcmlhYmxlIGN1YW5kbyBsbyBoZW1vcyByZXF1ZXJpZG8uDQoNCmBgYHtyLCBldmFsID0gRkFMU0V9DQojQWhvcmEgbW9zdHJhbW9zIGVsIGPDs2RpZ28gDQojIERBVEEgU09VUkNFOiBCZW5kZW4sIFAuLCBGZW5nLCBBLiwgSG93ZWxsLCBDLiBhbmQgRGFsbGEgUml2YSwgRy5WLiwgMjAyMS4gQ3JpbWUgYXQgU2VhOiBBIEdsb2JhbCBEYXRhYmFzZSBvZiBNYXJpdGltZSBQaXJhdGUgQXR0YWNrcyAoMTk5M+KAkzIwMjApLiBKb3VybmFsIG9mIE9wZW4gSHVtYW5pdGllcyBEYXRhLCA3LCBwLjE5LiBET0k6IGh0dHA6Ly9kb2kub3JnLzEwLjUzMzQvam9oZC4zOQ0KDQpjb3VudHJ5X2NvZGVzIDwtIHJlYWRfY3N2KCJkYXRvcy9jb3VudHJ5X2NvZGVzLmNzdiIpDQoNCmNvdW50cnlfaW5kaWNhdG9ycyA8LSByZWFkX2NzdigiZGF0b3MvY291bnRyeV9pbmRpY2F0b3JzLmNzdiIpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHJlYWRfY3N2KCJkYXRvcy9waXJhdGVfYXR0YWNrcy5jc3YiKQ0KDQpjb3VudHJ5X2RhdGEgPC0gZnVsbF9qb2luKGNvdW50cnlfY29kZXMsIGNvdW50cnlfaW5kaWNhdG9ycywgYnkgPSBjKCJjb3VudHJ5IiA9ICJjb3VudHJ5IikpDQogDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUoeWVhciA9IHllYXIoZGF0ZSkpDQoNCg0KcGlyYXRlX2F0dGFja3MgPC0gcGlyYXRlX2F0dGFja3MgJT4lIG11dGF0ZShhdHRhY2tfdHlwZSA9IGNhc2Vfd2hlbigNCiAgYXR0YWNrX3R5cGUgPT0gIkJvYXJkaW5nIiB+ICJCb2FyZGVkIiwgDQogIFRSVUUgfiBhdHRhY2tfdHlwZSkpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUodmVzc2VsX3N0YXR1cyA9IGNhc2Vfd2hlbigNCiAgdmVzc2VsX3N0YXR1cyA9PSAic3RlYW1pbmciIH4gIlN0ZWFtaW5nIiwgDQogIFRSVUUgfiB2ZXNzZWxfc3RhdHVzKSkNCg0KcGlyYXRlX2F0dGFja3MgPC0gcGlyYXRlX2F0dGFja3MgJT4lIG11dGF0ZSh2ZXNzZWxfdHlwZSA9IGNhc2Vfd2hlbigNCiAgdmVzc2VsX3R5cGUgPT0gIkJVTEsgQ0FSUklFUiIgfiAiQnVsayBDYXJyaWVyIiwgDQogIFRSVUUgfiB2ZXNzZWxfdHlwZSkpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUodmVzc2VsX3R5cGUgPSBjYXNlX3doZW4oDQogIHZlc3NlbF90eXBlID09ICJDT05UQUlORVIiIH4gIkNvbnRhaW5lciIsIA0KICBUUlVFIH4gdmVzc2VsX3R5cGUpKQ0KDQpwaXJhdGVfYXR0YWNrcyA8LSBwaXJhdGVfYXR0YWNrcyAlPiUgbXV0YXRlKHZlc3NlbF90eXBlID0gY2FzZV93aGVuKA0KICB2ZXNzZWxfdHlwZSA9PSAiUFJPRFVDVCBUQU5LRVIiIH4gIlByb2R1Y3QgVGFua2VyIiwgDQogIFRSVUUgfiB2ZXNzZWxfdHlwZSkpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUodmVzc2VsX3R5cGUgPSBjYXNlX3doZW4oDQogIHZlc3NlbF90eXBlID09ICJPZmZzaG9yZSBTdXBwbHkgc2hpcCIgfiAiT2Zmc2hvcmUgU3VwcGx5IFNoaXAiLCANCiAgVFJVRSB+IHZlc3NlbF90eXBlKSkNCg0KcGlyYXRlX2F0dGFja3MgPC0gcGlyYXRlX2F0dGFja3MgJT4lIG11dGF0ZSh2ZXNzZWxfdHlwZSA9IGNhc2Vfd2hlbigNCiAgdmVzc2VsX3R5cGUgPT0gIk9GRlNIT1JFIFNVUFBMWSBTSElQIiB+ICJPZmZzaG9yZSBTdXBwbHkgU2hpcCIsIA0KICBUUlVFIH4gdmVzc2VsX3R5cGUpKQ0KDQpwaXJhdGVfYXR0YWNrcyA8LSBwaXJhdGVfYXR0YWNrcyAlPiUgbXV0YXRlKHZlc3NlbF90eXBlID0gY2FzZV93aGVuKA0KICB2ZXNzZWxfdHlwZSA9PSAiT2Zmc2hvcmUgU3VwcGx5IiB+ICJPZmZzaG9yZSBTdXBwbHkgU2hpcCIsIA0KICBUUlVFIH4gdmVzc2VsX3R5cGUpKQ0KDQpybShjb3VudHJ5X2NvZGVzLCBjb3VudHJ5X2luZGljYXRvcnMpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBtdXRhdGUoeWVhciA9IGFzLmludGVnZXIoeWVhcikpDQoNCmZ1bGxfYnlfbmVhcmVzdCA8LSBmdWxsX2pvaW4ocGlyYXRlX2F0dGFja3MsIGNvdW50cnlfZGF0YSwgYnkgPSBjKCJuZWFyZXN0X2NvdW50cnkiID0gImNvdW50cnkiLCAieWVhciIgPSAieWVhciIpKXw+IGZpbHRlcighaXMubmEobG9uZ2l0dWRlKSkgDQoNCmBgYA0KDQojIyMjDQoNClBhcmEgcXVlIHNpcnZhIGRlIHByaW1lcmEgYXByb3hpbWFjacOzbiwgZW4gZXN0ZSBnbG9ibyB0ZXJyw6FxdWVvIHNlIHB1ZWRlbiBleHBsb3JhciBsb3MgYXRhcXVlcyByZWdpc3RyYWRvcywgZWwgcGHDrXMgbcOhcyBjZXJjYW5vIGEgZG9uZGUgc2UgcHJvZHVqZXJvbiB5IHN1IGHDsW8uDQoNCmBgYHtyfQ0KbGlicmFyeSgiY292aWQxOS5hbmFseXRpY3MiKQ0KbGlicmFyeSgicGxvdGx5IikNCg0KZGYyIDwtIGZ1bGxfYnlfbmVhcmVzdCB8PiBzZXBhcmF0ZShkYXRlLCBjKCJ5ZWFyIiwgIm1vbnRoIiwgImRheSIpLCAiLSIgKSB8PiBkcGx5cjo6c2VsZWN0KCJ5ZWFyIiwibG9uZ2l0dWRlIiwibGF0aXR1ZGUiLCJjb3VudHJ5X25hbWUiKSB8PiBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoeWVhcikpIHw+IHJlbmFtZShQcm92aW5jZSA9IHllYXIpIHw+IHJlbmFtZShDb3VudHJ5ID0gY291bnRyeV9uYW1lKXw+IHJlbmFtZShMb25nID0gbG9uZ2l0dWRlKXw+IHJlbmFtZShMYXQgPSBsYXRpdHVkZSkgfD4gZHBseXI6OnNlbGVjdCg0LDEsMiwzKSB8PiBhcy5kYXRhLmZyYW1lKCkNCg0KZ2xvYmVtYXAgPC0gbGl2ZS5tYXAoZGF0YSA9IGRmMiwgc2VsZWN0LnByb2pjdG4gPSBGQUxTRSwgdGl0bGUgPSAiIiwgbm8ubGVnZW5kID0gVFJVRSkNCg0KZ2xvYmVtYXAgPC0gZ2xvYmVtYXAgJT4lIGxheW91dCh0aXRsZSA9ICIiKSANCg0KaHRtbHRvb2xzOjpkaXYoZ2xvYmVtYXAsIGFsaWduID0gImNlbnRlciIgKQ0KYGBgDQoNCiMgMy4gQXRhcXVlcyBwaXJhdGFzDQoNCiMjIDMuMSBFdm9sdWNpw7NuIHRlbXBvcmFsDQoNCmBgYHtyLCBldmFsID0gVFJVRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocG5nKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ3JpZCkNCg0KDQojYmFyY28gPC0gcmVhZFBORygiaW1hZ2VuZXMvYmFyY28ucG5nIikNCg0KI0F0YXF1ZXMgdG90YWxlcyBhIGxvIGxhcmdvIGRlIGxvcyBhw7Fvcw0KDQphdF90b3RhbGVzIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc3VtbWFyaXNlKHRvdGFsPSBuKCkpIA0KDQoNCg0KI3JlcHJlc2VudGFtb3MgDQoNCg0KcDEgPC0gZ2dwbG90KGRhdGEgPSBhdF90b3RhbGVzLCBhZXMoeWVhciwgdG90YWwpKSArIGdlb21fbGluZShjb2xvcj0iZGFya2JsdWUiKSArIGdlb21fcG9pbnQoY29sb3I9ImRhcmtibHVlIikgKyB0aGVtZV9taW5pbWFsKCkgKyBnZW9tX3RleHQoYWVzKHkgPSB0b3RhbCwgeW1heCA9IHRvdGFsLCBsYWJlbCA9IHRvdGFsKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHNpemU9Mywgdmp1c3Q9LTAuOCwgaGp1c3Q9MC44ICxjb2w9ImJsYWNrIikgKyB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gIlRvdGFsIGRlIGF0YXF1ZXMiLA0KICAgIHN1YnRpdGxlID0gIigxOTkzLTIwMjApIiwNCiAgICB4ID0gIkHDsW9zIiwNCiAgICB5ID0gIk7CuiBkZSBhdGFxdWVzIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBoanVzdCA9IDAuNSkpDQoNCiNBw7FhZGltb3MgdW5hIGltYWdlbg0KaW1nIDwtIHJlYWRQTkcoImltYWdlbmVzL2JhcmNvLnBuZyIsIEZBTFNFKQ0KbWFyY2EgPC0gcmFzdGVyR3JvYihpbWcsIGludGVycG9sYXRlPUYsaGVpZ2h0PXVuaXQoMywgImNtIiksaGp1c3Q9LTEuMzAsIHZqdXN0PS0wLjUpDQpwMSArIGFubm90YXRpb25fY3VzdG9tKG1hcmNhLHhtaW49LUluZiwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYpDQptYXJjYQ0KDQoNCnllYXJfYXRfbWF4IDwtIGF0X3RvdGFsZXMgfD4gc2VsZWN0KHllYXIpICU+JSAgc2xpY2VfbWF4KG9yZGVyX2J5PSB5ZWFyLCBuID0gMSkgfD4gYXMuaW50ZWdlcigpDQoNCmF0X21heCA8LSBhdF90b3RhbGVzIHw+IHNlbGVjdCh0b3RhbCkgJT4lIHNsaWNlX21heChvcmRlcl9ieT0gdG90YWwsIG4gPSAxKSB8PiBhcy5pbnRlZ2VyKCkNCg0KDQoNCmBgYA0KDQpQb2RlbW9zIHZlciBjb21vIGhhbiBpZG8gZXZvbHVjaW9uYW5kbyBsb3MgYXRhcXVlcyB0b3RhbGVzIGEgbG8gbGFyZ28gZGUgbG9zIGHDsW9zLiBTdSBtw6F4aW1vIGZ1ZSBlbiBlbCBhw7FvIGByIHllYXJfYXRfbWF4YCBjb24gdW4gdG90YWwgZGUgYHIgYXRfbWF4YCBhdGFxdWVzLiBFbiBsYSBhY3R1YWxpZGFkIHNlIGhhbiByZWR1Y2lkbyBkZWJpZG8gYSAxOTAgYXRhcXVlcy4gTG9zIGF0YXF1ZXMgYSBsb3MgYmFyY29zIHBvbmVuIGVuIHBlbGlncm8gbGEgdmlkYSBkZSBsYSB0cmlwdWxhY2nDs24sIGFkZW3DoXMgYWZlY3RhbiBhbCBjb21lcmNpbyBpbnRlcm5hY2lvbmFsLiBBIGxvIGxhcmdvIGRlbCB0aWVtcG8gbGEgcHJlb3VjdXBhY2nDs24gaGEgY3JlY2lkbyBkZWJpZG8gYSBxdWUgbG9zIGFzYWx0YW50ZXMgY2FkYSB2ZXogaGFjZW4gbcOhcyB1c28gZGUgbGFzIGFybWFzLiBEZWJpZG8gYSBlc3RvIGxhIHBpcmF0ZXJpYSBtYXJpbmEgaGEgcGFzYWRvIHBvciBkaXN0aW50YXMgZmFzZXMgZGUgcmVndWxhY2nDs24gZW4gZWwgRGVyZWNobyBJbnRlcm5hY2lvbmFsLiBBY2Npb25lcyBjb21vIGVsIHVzbyBkZSBwYXRydWxsZXJhcyBoYW4gYXl1ZGFkbyBlbiBsYSBkaXNtaW51Y2nDs24gZGUgbG9zIGF0YXF1ZXMuDQoNCiMjIDMuMiBFdm9sdWNpw7NuIGdlb2dyw6FmaWNhDQoNCmBgYHtyLCBldmFsID0gVFJVRX0NCg0KI2ludGVudG8gZGUgbWFwYQ0KbGlicmFyeShtYXBkYXRhKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShnZ3JlcGVsKQ0KbGlicmFyeShnZ2FuaW1hdGUpDQoNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEd1YXJkYW1vcyBsYSBpbmZvcm1hY2nDs24gZW4gdW4gbnVldm8gZGF0YWZyYW1lIGxsYW1hZG8gbWFwYV9tdW5kbw0KDQphdF9tYXBhIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBzZWxlY3QobG9uZ2l0dWRlLCBsYXRpdHVkZSwgYXR0YWNrX3R5cGUsIHllYXIpDQoNCm1hcGFfbXVuZG8gPC0gbWFwX2RhdGEoIndvcmxkIikNCg0KcCA8LSBtYXBhX211bmRvICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21fcG9seWdvbihhZXMoIHg9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXI9ICJibGFjayIsIHNpemU9IDEpKSArDQogIGdlb21fcG9pbnQoZGF0YT1hdF9tYXBhLCBhZXMobG9uZ2l0dWRlLCBsYXRpdHVkZSksDQogICAgICAgICAgICAgY29sb3I9ICJkYXJrZ29sZGVucm9kMSIsIHNpemU9MikgKw0KICBsYWJzKHRpdGxlID0gIkNvbmNlbnRyYWNpw7NuIGRlIGxvcyBhdGFxdWVzIiwNCiAgICBzdWJ0aXRsZSA9ICIoMTk5My0yMDIwKSIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSxwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgaGp1c3QgPSAwLjUpKSArDQogIGNvb3JkX2ZpeGVkICh4bGltPSBjKC0yMDAsMjAwKSwNCiAgICAgICAgICAgICAgeWxpbT0gYygtNTgsOTApLA0KICAgICAgICAgICAgICByYXRpbyA9IDEuMykgKyB0cmFuc2l0aW9uX3RpbWUoeWVhcikgKyBsYWJzKGNhcHRpb24gPSAiWWVhcjoge2ZyYW1lX3RpbWV9IikgKyB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAibGlnaHRibHVlMiIpKSANCg0KDQphbmltYXRlKHAsIHdpZHRoID0gNzAwLCBoZWlnaHQgPSA0MzIsIGZwcyA9IDEsIGR1cmF0aW9uID0gMTUsIHJld2luZCA9IEZBTFNFKQ0KYGBgDQoNCkxvcyBhdGFxdWVzIHNlIGhhbiBjb25jZW50cmFkbyBzb2JyZSB0b2RvIGVuIGVsIFN1ZGVzdGUgYXNpw6F0aWNvIHkgZWwgc3ViY29udGluZW50ZSBpbmRpbywgw4FmcmljYSB5IEFtw6lyaWNhIGRlbCBTdXIsIENlbnRyYWwgeSBsYXMgQWd1YXMgZGVsIENhcmliZS4gUG9kZW1vcyB2ZXIgcXVlIGR1cmFudGUgbG9zIHByaW1lcm9zIGHDsW9zICgxOTkzLTIwMDgpIGhheSB1bmEgbWF5b3IgY29uY2VudHJhY2nDs24gZGUgbG9zIGF0YXF1ZXMgZW4gZWwgZXN0cmVjaG8gZGUgTWFsYXNpYSwgc2luIGVtYmFyZ28gY29taWVuemFuIGEgcmVkdWNpcnNlIGRlYmlkbyBhbCBhdW1lbnRvIGRlIGxhIHZpZ2lsYW5jaWEgbWFyaXRpbWEuIEVuIEluZG9uZXNpYSBsYSBQb2xpY8OtYSBNYXJpbmEgZGUgSW5kb25kZXNpYShJTVApIGFjdMO6YSBwYXJhIGV2aXRhciBtw6FzIGF0YXF1ZXMgcGF0cnVsbGFuZG8gY2VyY2EgZGUgbGFzIGNvc3RhcywgcG9yIGxvIHF1ZSBoYSBlc3RhYmxlY2lkbyBjaWVydG9zIHB1bnRvcyBkZSBtYXlvciBwcm90ZWNjacOzbi4NCg0KRW4gY3VhbnRvIGEgw4FmcmljYSBwb2RlbW9zIHZlciBxdWUgZW4gZWwgZ29sZm8gZGUgR3VpbmVhIGFwcm94aW1hZGFtZW50ZSBkZXNkZSAxOTk5IGhhIGhhYmlkbyB1bmEgZ3JhbiBjb25jZW50cmFjacOzbiBkZSBhdGFxdWVzLiBFbiBOaWdlcmlhIGxvcyBwaXJhdGFzIHNvbiB2aW9sZW50b3MgeSB2YW4gYXJtYWRvcy4gRXN0YXMgYWd1YXMgc2UgY29uc2lkZXJhbiBkZSBhbHRvIHJpZXNnby4gRGViaWRvIGEgbGEgZ3VlcnJhIGNpdmlsIGVuIFllbcOpbiBlbiBlc3RhIHpvbmEgc2Ugc3VlbGVuIGNvbmNlbnRyYXIgYXRhcXVlcyBhIGJhcmNvcyBxdWUgbm8gdGllbmVuIHBvcnF1ZSBlc3RhciBkaXJlY3RhbWVudGUgcmVsYWNpb25hZG9zIGNvbiBsYSBwaXJhdGVyw61hLiBQb3Igw7psdGltbywgZW4gbGEgYWN0dWFsaWRhZCBzZSBjb25jZW50cmFuIG1lbm9zIGF0YXF1ZXMgZW4gS2VuaWEsIFRhbnphbmlhLCBPY8OpYW5vIMONbmRpY28uLi4sIHNpbiBlbWJhcmdvIGNvbW8gc2UgcHVlZGUgdmVyLCBlbiBlbCBwYXNhZG8gc2UgY29uY2VudHJhcm9uIGxhIG1heW9yw61hIGRlIGxvcyBhdGFxdWVzLg0KDQpGaW5hbG1lbnRlLCBBbcOpcmljYSBkZWwgU3VyIHRhbWJpw6luIGhhIHNpZG8gdW5hIHpvbmEgZGUgY29uY2VudHJhY2nDs24gZGUgYXRhcXVlcywgYXVucXVlIGNvbiBtZW5vciByZWxldmFuY2lhIHF1ZSBsb3MgY29tZW50YWRvcyBhbnRlcmlvcm1lbnRlLiBNdWNoYXMgZGUgZXN0YXMgY29uY2x1c2lvbmVzIHNlIHZlbiByZWZsZWphZGFzLCBxdWl6w6FzIGNvbiBtYXlvciBjbGFyaWRhZCwgZW4gbGEgc2lndWllbnRlIGdyw6FmaWNhIGRpbsOhbWljYToNCg0KYGBge3J9DQpmdWxsX2J5X25lYXJlc3QgPC0gZnVsbF9qb2luKHBpcmF0ZV9hdHRhY2tzLCBjb3VudHJ5X2RhdGEsIGJ5ID0gYygibmVhcmVzdF9jb3VudHJ5IiA9ICJjb3VudHJ5IiwgInllYXIiID0gInllYXIiKSl8PiBmaWx0ZXIoIWlzLm5hKGxvbmdpdHVkZSkpDQoNCmRmIDwtIGZ1bGxfYnlfbmVhcmVzdCB8PiBkcm9wX25hKHJlZ2lvbikgfD4gZHBseXI6OnNlbGVjdCh5ZWFyLCByZWdpb24pIHw+IHVuaXRlKCJpZCIsIGMoMToyKSwgc2VwID0gIl8iLCByZW1vdmUgPSBUUlVFKXw+ICBncm91cF9ieShpZCkgfD4gbXV0YXRlKG5hdHRhY2tzID0gbigpKSB8PiB1bmdyb3VwKCkgfD4gZGlzdGluY3QoKSB8PiBzZXBhcmF0ZShpZCwgYygieWVhciIsICJyZWdpb24iKSwgIl8iICkgfD4gbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKSAlPiUgbXV0YXRlKHJlZ2lvbiA9IGNhc2Vfd2hlbigNCiAgcmVnaW9uID09ICJFYXN0IEFzaWEgJiBQYWNpZmljIiB+ICJBc2lhIGRlbCBFc3RlICYgUGFjw61maWNvIiwNCiAgcmVnaW9uID09ICJMYXRpbiBBbWVyaWNhICYgQ2FyaWJiZWFuIiB+ICJMYXRpbm8gQW3DqXJpY2EgJiBDYXJpYmUiLA0KICByZWdpb24gPT0gIlNvdXRoIEFzaWEiIH4gIlN1ciBkZSBBc2lhIiwNCiAgcmVnaW9uID09ICJTdWItU2FoYXJhbiBBZnJpY2EiIH4gIsOBZnJpY2EgU3ViLVNhaGFyaWFuYSIsDQogIFRSVUUgfiByZWdpb24pKQ0KDQoNCmFjY3VtdWxhdGVfYnkgPC0gZnVuY3Rpb24oZGF0LCB2YXIpIHsNCiAgdmFyIDwtIGxhenlldmFsOjpmX2V2YWwodmFyLCBkYXQpDQogIGx2bHMgPC0gcGxvdGx5Ojo6Z2V0TGV2ZWxzKHZhcikNCiAgZGF0cyA8LSBsYXBwbHkoc2VxX2Fsb25nKGx2bHMpLCBmdW5jdGlvbih4KSB7DQogICAgY2JpbmQoZGF0W3ZhciAlaW4lIGx2bHNbc2VxKDEsIHgpXSwgXSwgZnJhbWUgPSBsdmxzW1t4XV0pDQogIH0pDQogIGRwbHlyOjpiaW5kX3Jvd3MoZGF0cykNCn0NCg0KDQpmaWcgPC0gZGYgDQpmaWcgPC0gZmlnICU+JSBhY2N1bXVsYXRlX2J5KH55ZWFyKQ0KDQoNCmZpZyA8LSBmaWcgJT4lDQogIHBsb3RfbHkoDQogICAgeCA9IH55ZWFyLCANCiAgICB5ID0gfm5hdHRhY2tzLA0KICAgIHNwbGl0ID0gfnJlZ2lvbiwNCiAgICBmcmFtZSA9IH5mcmFtZSwgDQogICAgdHlwZSA9ICdzY2F0dGVyJywNCiAgICBtb2RlID0gJ2xpbmVzJywgDQogICAgZmlsbCA9ICd0b3plcm95JywNCiAgICBsaW5lID0gbGlzdChzaW1wbHlmeSA9IEYpDQogICkNCmZpZyA8LSBmaWcgJT4lIGxheW91dCgNCiAgeGF4aXMgPSBsaXN0KA0KICAgIHRpdGxlID0gIkHDsW8iLA0KICAgIHplcm9saW5lID0gRg0KICApLA0KICB5YXhpcyA9IGxpc3QoDQogICAgdGl0bGUgPSAiTsO6bWVybyBkZSBhdGFxdWVzIiwNCiAgICB6ZXJvbGluZSA9IEYNCiAgKQ0KKQ0KZmlnIDwtIGZpZyAlPiUgYW5pbWF0aW9uX29wdHMoDQogIGZyYW1lID0gMTAwLCANCiAgdHJhbnNpdGlvbiA9IDAsIA0KICByZWRyYXcgPSBGQUxTRQ0KKQ0KZmlnIDwtIGZpZyAlPiUgYW5pbWF0aW9uX3NsaWRlcigNCiAgY3VycmVudHZhbHVlID0gbGlzdCgNCiAgICBwcmVmaXggPSAiQcOxbyAiDQogICkNCikNCg0KaHRtbHRvb2xzOjpkaXYoZmlnLCBhbGlnbiA9ICJjZW50ZXIiICkNCg0KYGBgDQoNCiMjIDMuMyBUaXBvcyBkZSBhdGFxdWVzIA0KDQojIyMjIHsudGFic2V0fQ0KDQpFeGlzdGVuIGRpZmVyZW50ZXMgdGlwb3MgZGUgYXRhcXVlcyBjb21vIHBvciBlamVtcGxvIGxvcyBhYm9yZGFqZXMsIHNlY3Vlc3Ryb3MsIGV4cGxvc2lvbmVzLi4uIHZhbW9zIGEgdmVyIGN1w6FsZXMgc29uIG3DoXMgZnJlY3VlbnRlcy4gUGFyYSBlc3RlIGFuw6FsaXNpcyBoZW1vcyBleGNsdWlkbyBsb3MgYXRhcXVlcyBkZSBsb3MgY3VhbGVzIG5vIGhheSBpbmZvcm1hY2nDs24gZW4gZXN0w6EgY2F0ZWdvcsOtYSAoMTIwIGF0YXF1ZXMpLg0KDQojIyMjIyAqKlRpcG9zIG3DoXMgZnJlY3VlbnRlcyoqDQoNCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD02fQ0KI0F0YXF1ZXMgc2Vnw7puIHRpcG86IGNhbnRpZGFkIHRvdGFsIGRlIGxvcyBhdGFxdWVzIHNlZ8O6biBlbCB0aXBvIGVudHJlIDE5OTMgeSAyMDIwIChlbiBlbCBncmFmaWNvIHBvbmVyIGxvcyBudW1lcm9zIGVuIGxhcyBiYXJyYXMpDQoNCmxpYnJhcnkoZ2d0aGVtZXMpDQoNCmEgPC0gcGlyYXRlX2F0dGFja3MgJT4lIHNlbGVjdCh5ZWFyLCBhdHRhY2tfdHlwZSkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSAgY291bnQoYXR0YWNrX3R5cGUpICU+JSBmaWx0ZXIoeWVhciA8IDIwMDApICU+JSBncm91cF9ieShhdHRhY2tfdHlwZSkgJT4lIHN1bW1hcmlzZShuID0gc3VtKG4pKSAlPiUgZHJvcF9uYSgpDQpwZXJpb2QgPC0gYygiMTk5My0xOTk5IiwiMTk5My0xOTk5IiwiMTk5My0xOTk5IiwiMTk5My0xOTk5IikNCmEgPC0gZGF0YS5mcmFtZShwZXJpb2QsIGEpICANCg0KYiA8LSBwaXJhdGVfYXR0YWNrcyAlPiUgc2VsZWN0KHllYXIsIGF0dGFja190eXBlKSAlPiUgZ3JvdXBfYnkoeWVhcikgJT4lICBjb3VudChhdHRhY2tfdHlwZSkgJT4lIGZpbHRlcih5ZWFyID4gMTk5OSAmIHllYXIgPCAyMDA3LCAhYXR0YWNrX3R5cGUgPT0gIkRldGFpbmVkIikgJT4lIGdyb3VwX2J5KGF0dGFja190eXBlKSAlPiUgc3VtbWFyaXNlKG4gPSBzdW0obikpICU+JSBkcm9wX25hKCkNCnBlcmlvZCA8LSBjKCIyMDAwLTIwMDYiLCIyMDAwLTIwMDYiLCIyMDAwLTIwMDYiLA0KICAgICAgICAgICAgIjIwMDAtMjAwNiIpDQpiIDwtIGRhdGEuZnJhbWUocGVyaW9kLCBiKQ0KDQpjIDwtIHBpcmF0ZV9hdHRhY2tzICU+JSBzZWxlY3QoeWVhciwgYXR0YWNrX3R5cGUpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgIGNvdW50KGF0dGFja190eXBlKSAlPiUgZmlsdGVyKHllYXIgPiAyMDA2ICYgeWVhciA8IDIwMTQpICU+JSBncm91cF9ieShhdHRhY2tfdHlwZSkgJT4lIHN1bW1hcmlzZShuID0gc3VtKG4pKSAlPiUgZHJvcF9uYSgpDQpwZXJpb2QgPC0gYygiMjAwNy0yMDEzIiwiMjAwNy0yMDEzIiwiMjAwNy0yMDEzIiwiMjAwNy0yMDEzIikNCmMgPC0gZGF0YS5mcmFtZShwZXJpb2QsIGMpDQoNCmQgPC0gcGlyYXRlX2F0dGFja3MgJT4lIHNlbGVjdCh5ZWFyLCBhdHRhY2tfdHlwZSkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSAgY291bnQoYXR0YWNrX3R5cGUpICU+JSBmaWx0ZXIoeWVhciA+IDIwMTMpICU+JSBncm91cF9ieShhdHRhY2tfdHlwZSkgJT4lIHN1bW1hcmlzZShuID0gc3VtKG4pKSAlPiUgZHJvcF9uYSgpDQpwZXJpb2QgPC0gYygiMjAxNC0yMDIwIiwiMjAxNC0yMDIwIiwiMjAxNC0yMDIwIiwiMjAxNC0yMDIwIiwNCiAgICAgICAgICAgICIyMDE0LTIwMjAiKQ0KZCA8LSBkYXRhLmZyYW1lKHBlcmlvZCwgZCkNCg0KYXQgPC0gcmJpbmQoYSxiLGMsZCkgJT4lICBtdXRhdGUoYXR0YWNrX3R5cGUgPSBmb3JjYXRzOjphc19mYWN0b3IoYXR0YWNrX3R5cGUpKSAlPiUgbXV0YXRlKGF0dGFja190eXBlID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIoYXR0YWNrX3R5cGUsIG4sIC5kZXNjID0gVFJVRSkpDQoNCiAgDQoNCg0KZ2dwbG90KGRhdGE9YXQsIGFlcyhhdHRhY2tfdHlwZSwgbikpICsgDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iTWVkaXVtU2xhdGVCbHVlIikgKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIGdlb21fdGV4dChhZXMoeSA9IG4sIGxhYmVsID0gbiksIA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHNpemU9MywNCiAgICAgICAgICAgIHZqdXN0PS0wLjEsIGhqdXN0PTAuNSAsY29sPSJibGFjayIsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIGxhYnModGl0bGUgPSAiVGlwb3MgZGUgYXRhcXVlcyIsDQogICAgc3VidGl0bGUgPSAiKDE5OTMtMjAyMCkiLA0KICAgIHggPSAiVGlwb3MgZGUgYXRhcXVlcyIsDQogICAgeSA9ICJOw7ptZXJvIGRlIGF0YXF1ZXMiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAwLjUpLCANCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGhqdXN0ID0gMC41KSkgKw0KICBmYWNldF93cmFwKHZhcnMocGVyaW9kKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJBYm9yZGFqZSIsIkludGVudG8iLCJTZWN1ZXN0cm8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEdWRhIiwgIkV4cGxvc2nDs24iLCAiRGlzcGFyb3MiKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNzAwKSkNCmBgYA0KDQpMb3MgYXRhcXVlcyBtw6FzIGZyZWN1ZW50ZXMgc29uIGxvcyBhYm9yZGFqZXMsIGxvcyBwaXJhdGFzIHN1ZWxlbiBhdGFjYXIgbG9zIGJhcmNvcyBtaWVudHJhcyBuYXZlZ2FuIG8gZXN0w6FuIGFuY2xhZG9zLCBhZGVtw6FzIHNlIGhhY2UgZXNwZWNpYWwgYWR2ZXJ0ZW5jaWEgYSBsYSBub2NoZSwgcXVlIGVzIGN1YW5kbyBtw6FzIHBvc2liaWxpZGFkZXMgZGUgc2VyIGF0YWNhZG8gaGF5LiBQb3IgbG8gdGFudG8sIGxvcyBiYXJjb3MgZGViZW4gcHJlc3RhciB2aWdpbGFuY2lhIGVuIHRvZG8gbW9tZW50by4gRW4gbWVub3IgbWVkaWRhIHBlcm8gdGFtYmnDqW4gcmVsZXZhbnRlcyBzb24gbG9zIHNlY3Vlc3Ryb3MsIGVuIGVsIHBhc2FkbyBzZSBsbGV2YXJvbiBhIGNhYm8gdmFyaW9zIHNlY3Vlc3Ryb3MgZGUgY2FtaW9uZXMgY2lzdGVybmEgZGUgcHJvZHVjdG9zIHBlcXVlw7FvcyBlbiBsYSB6b25hIGRlbCBNYXIgZGUgQ2hpbmEgTWVyaWRpb25hbC5Mb3Mgc2VjdWVzdHJvcyBxdWUgc2UgZW1wZXphcm9uIGEgb2JzZXJ2YXIgZW4gMjAxNCBubyBkdXJhcm9uIG3DoXMgZGUgdW4gYcOxby4gQ29uIMOpeGl0byBsYXMgYXV0b3JpZGFkZXMgY29uc2lndWllcm9uIGF0cmFwYXIgYSB2YXJpb3MgZGUgbG9zIHNlY3Vlc3RyYWRvcmVzLiBFbiBsYSB6b25hIGRlIMOBZnJpY2EgbXVjaG9zIGRlIGxvcyBzZWN1ZXN0cm9zIGxvcyB1dGlsaXphYmFuIHBhcmEgcGVkaXIgcmVzY2F0ZS4gQSBwYXJ0aXIgZGUgYWhvcmEgY2VudHJhcmVtb3MgZWwgYW7DoWxpc2lzIGVuIGxvcyB0aXBvcyBtw6FzIGNvbXVuZXM6IGFib3JkYWplLCBpbnRlbnRvIHkgc2VjdWVzdHJvLg0KDQojIyMjIyAqKkRpc3RyaWJ1Y2nDs24gZ2VvZ3LDoWZpY2EqKg0KDQpTaSBjZW50cmFtb3MgZWwgZm9jbyBlbiBlc3RvcyB0cmVzIHRpcG9zIGRlIGF0YXF1ZSB5IGxvcyByZXByZXNlbnRhbW9zIHNvYnJlIGVsIG1hcGEsIGNvbWVuemFtb3MgYSBpZGVudGlmaWNhciBhbGd1bmEgZGUgbGFzIHRlbmRlbmNpYXMgbcOhcyBpbXBvcnRhbnRlcyBxdWUgdmllbmVuIHJlZmxlamFkYXMgZW4gbGEgbGl0ZXJhdHVyYSBzb2JyZSBwaXJhdGVyw61hLiBQcmluY2lwYWxtZW50ZSwgb2JzZXJ2YW1vcyBxdWUgbG9zIHNlY3Vlc3Ryb3MgdGllbmVuIG11Y2hhIG1heW9yIGltcG9ydGFuY2lhIGVuIGVsIMONbmRpY28gb2NjaWRlbnRhbCBxdWUgZW4gbmluZ3VuYSBvdHJhIMOhcmVhLiBUYW1iacOpbiBjb21lbnphbW9zIGEgb2JzZXJ2YXIgcXVlIGxvcyBhdGFxdWVzIGRlIHNlY3Vlc3RybyBlIGludGVudG9zIGZhbGxpZG9zIHNvbiBtdWNobyBtw6FzIGZyZWN1ZW50ZXMgYSBtYXlvciBkaXN0YW5jaWEgZGUgbGEgY29zdGEuDQoNCmBgYHtyLCBldmFsID0gVFJVRX0NCmxpYnJhcnkodG1hcCkgDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KG1hcHMpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KDQpkYXRhKFdvcmxkKQ0Kd29ybGQgPC0gV29ybGQgfD4gZmlsdGVyKGNvbnRpbmVudCAhPSAiQW50YXJjdGljYSIpIDsgcm0oV29ybGQpDQoNCmRmIDwtIHBpcmF0ZV9hdHRhY2tzIHw+IGZpbHRlcihhdHRhY2tfdHlwZSA9PSAiQm9hcmRlZCIgfCBhdHRhY2tfdHlwZSA9PSAiSGlqYWNrZWQiIHwgYXR0YWNrX3R5cGUgPT0gIkF0dGVtcHRlZCIgKQ0KDQptYXBfYnlfdHlwZSA8LSBnZ3Bsb3QoKSArIA0KICBnZW9tX3NmKGRhdGEgPSB3b3JsZCwgY29sb3IgPSAiZ3JleSIsIGZpbGwgPSAiZ3JleSIsIGx3ZCA9IDAuMiwgYWVzKGdlb21ldHJ5ID0gZ2VvbWV0cnkpKSArIA0KICBnZW9tX3BvaW50KGRhdGEgPSBkZiwgYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSwgY29sb3IgPSBhdHRhY2tfdHlwZSksIHNpemUgPSAwLjUsIGFscGhhID0gMC4zKSArIA0KICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJJbnRlbnRvIiwgIkFib3JkYWplIiwgIlNlY3Vlc3RybyIpKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwNCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSArbGFicyh0aXRsZSA9ICJBdGFxdWVzIGRlIGxvcyB0aXBvcyBtw6FzIGZyZWN1ZW50ZXMiLCB4ID0gTlVMTCwNCiAgICB5ID0gTlVMTCwgY29sb3VyID0gIlRpcG8gZGUgYXRhcXVlIikrIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLA0KICAgIGNvbG91ciA9IE5BLCBoanVzdCA9IDAsIHZqdXN0ID0gMCksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMSwgMC4zKSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIpIA0KDQptYXBfYnlfdHlwZSANCmBgYA0KDQpFbCBzaWd1aWVudGUgZ3LDoWZpY28sIGNvbiBsYSBkaXN0YW5jaWEgbWVkaWEgYSBsYSBjb3N0YSBkZSBjYWRhIHRpcG8gZGUgYXRhcXVlLCBjb25maXJtYSBlc3RhIGludHVpY2nDs246DQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmRmIDwtIHBpcmF0ZV9hdHRhY2tzIHw+IGZpbHRlcihhdHRhY2tfdHlwZSA9PSAiQm9hcmRlZCIgfCBhdHRhY2tfdHlwZSA9PSAiSGlqYWNrZWQiIHwgYXR0YWNrX3R5cGUgPT0gIkF0dGVtcHRlZCIgKSB8PiAgZ3JvdXBfYnkoYXR0YWNrX3R5cGUpIHw+IHN1bW1hcmlzZShuID0gbWVhbihzaG9yZV9kaXN0YW5jZSkpIHw+IG11dGF0ZShhdHRhY2tfdHlwZSA9IGZvcmNhdHM6OmFzX2ZhY3RvcihhdHRhY2tfdHlwZSkpIHw+IG11dGF0ZShhdHRhY2tfdHlwZSA9IGZvcmNhdHM6OmZjdF9yZW9yZGVyKGF0dGFja190eXBlLCBuLCAuZGVzYyA9IFRSVUUpKQ0KDQpnZ3Bsb3QoZGF0YSA9IGRmKSArIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGF0dGFja190eXBlLCB5ID0gbiksIHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsPWMoIlBvd2RlckJsdWUiLCAiTWlzdHlSb3NlIiwgIkxpZ2h0U3RlZWxCbHVlIikpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSkpICArDQogIGxhYnModGl0bGUgPSAiRGlzdGFuY2lhIG1lZGlhIGEgbGEgY29zdGEgcG9yIHRpcG8gZGUgYXRhcXVlIiwNCiAgICB4ID0gIlRpcG9zIGRlIGF0YXF1ZXMiLA0KICAgIHkgPSAiRGlzdGFuY2lhIG1lZGlhIGEgbGEgY29zdGEiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSksICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGhqdXN0ID0gMC41KSkgKyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJJbnRlbnRvIiwiU2VjdWVzdHJvIiwiQWJvcmRhamUiKSkNCmBgYA0KDQojIyMjDQoNCkZpbmFsbWVudGUsIHVuIHZpc3Rhem8gYSBlc3RlIGdyw6FmaWNvIHRyaWRpbWVuc2lvbmFsIHRhbWJpw6luIHBlcm1pdGUgYXByZWNpYXIgbGFzIHRlbmRlbmNpYXMgZW4gbGEgZGlzdGFuY2lhIGEgbGEgY29zdGEgc2Vnw7puIGVsIHRpcG8gZGUgYXRhcXVlIGRlc2NyaXRhcyBwcmV2aWFtZW50ZSwgYWRlbcOhcyBkZSBldmlkZW5jaWFyIGxhIGNvbmNlbnRyYWNpw7NuIGRlIGxvcyBhdGFxdWVzIGVuIGxhIGZyYW5qYSB0cm9waWNhbCB5IGVuIGxhcyBjb3N0YXMgZGUgbGFzIG1hc2FzIGNvbnRpbmVudGFsZXMuIERlIGhlY2hvLCBjdWFuZG8gc2UgcG9zaWNpb25hIGVsIHB1bnRvIGRlIHZpc3RhIHBlcnBlbmRpY3VsYXJtZW50ZSBhbCBwbGFubyAoeCx5KSwgZXMgcG9zaWJsZSBhcHJlY2lhciBjw7NtbyBsb3MgcHVudG9zIHBlcmZpbGFuIGVsIGNvbnRvcm5vIGRlIMOBZnJpY2EgeSBBbcOpcmljYSBkZWwgU3VyLg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShwbG90bHkpDQoNCmRmIDwtIGZ1bGxfYnlfbmVhcmVzdCB8PiBmaWx0ZXIoYXR0YWNrX3R5cGUgPT0gIkJvYXJkZWQiIHwgYXR0YWNrX3R5cGUgPT0gIkhpamFja2VkIiB8IGF0dGFja190eXBlID09ICJBdHRlbXB0ZWQiICkgJT4lIA0KICBtdXRhdGUoYXR0YWNrX3R5cGUgPSBjYXNlX3doZW4oDQogICAgYXR0YWNrX3R5cGUgPT0gIkJvYXJkZWQiIH4gIkFib3JkYWplIiwNCiAgICBhdHRhY2tfdHlwZSA9PSAiSGlqYWNrZWQiIH4gIlNlY3Vlc3RybyIsDQogICAgYXR0YWNrX3R5cGUgPT0gIkF0dGVtcHRlZCIgfiAiSW50ZW50byIsDQogICAgVFJVRSB+IGF0dGFja190eXBlDQogICkpDQoNCg0KZmlnM2QgPC0gcGxvdF9seShkZiwgeCA9IH5sb25naXR1ZGUsIHkgPSB+bGF0aXR1ZGUsIHogPSB+c2hvcmVfZGlzdGFuY2UsIGNvbG9yID0gfmF0dGFja190eXBlLCBzaXplID0gMC4yLCBhbHBoYSA9IDEpDQpmaWczZCA8LSBmaWczZCAlPiUgYWRkX21hcmtlcnMoKQ0KDQpmaWczZCA8LSBmaWczZCAlPiUgbGF5b3V0KHNjZW5lID0gbGlzdCh4YXhpcyA9IGxpc3QodGl0bGUgPSAnTG9uZ2l0dWQnKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnTGF0aXR1ZCcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdEaXN0YW5jaWEgYSBsYSBjb3N0YScpKSkNCg0KZmlnM2QNCmBgYA0KDQojIyAzLjQgRXN0YWRvIGRlIGxhcyBlbWJhcmNhY2lvbmVzDQoNCmBgYHtyfQ0KDQphdF9lc3RhZG8gPC0gcGlyYXRlX2F0dGFja3MgJT4lIHNlbGVjdCh5ZWFyLCB2ZXNzZWxfc3RhdHVzKSAlPiUgZ3JvdXBfYnkoeWVhcikgJT4lICBjb3VudCh2ZXNzZWxfc3RhdHVzKSAlPiUgIGZpbHRlcighaXMubmEodmVzc2VsX3N0YXR1cykpICU+JSBzbGljZV9tYXgob3JkZXJfYnkgPSBuLCBuPTcpICU+JSBncm91cF9ieSh2ZXNzZWxfc3RhdHVzKSAlPiUgc3VtbWFyaXNlKGg9c3VtKG4pKSAlPiUgc2xpY2VfbWF4KG9yZGVyX2J5ID0gaCwgbj0xMSkgJT4lDQogIG11dGF0ZSh2ZXNzZWxfc3RhdHVzID0gY2FzZV93aGVuKA0KICAgIHZlc3NlbF9zdGF0dXMgPT0gIkFuY2hvcmVkIiB+ICJBbmNsYWRvIiwNCiAgICB2ZXNzZWxfc3RhdHVzID09ICJTdGVhbWluZyIgfiAiTmF2ZWdhbmRvIiwNCiAgICB2ZXNzZWxfc3RhdHVzID09ICJCZXJ0aGVkIiB+ICJBdHJhY2FkbyIsDQogICAgdmVzc2VsX3N0YXR1cyA9PSAiVW5kZXJ3YXkiIH4gIkVuIG1hcmNoYSIsDQogICAgdmVzc2VsX3N0YXR1cyA9PSAiU3RhdGlvbmFyeSIgfiAiRXN0YWNpb25hZG8iLA0KICAgIHZlc3NlbF9zdGF0dXMgPT0gIkRyaWZ0aW5nIiB+ICJBIGxhIGRlcml2YSIsDQogICAgdmVzc2VsX3N0YXR1cyA9PSAiTW9vcmVkIiB+ICJBbWFycmFkbyIsDQogICAgdmVzc2VsX3N0YXR1cyA9PSAiQnVua2VyaW5nIG9wZXJhdGlvbnMiIH4gIlJlcG9zdGFuZG8iLA0KICAgIHZlc3NlbF9zdGF0dXMgPT0gIkZpc2hpbmciIH4gIlBlc2NhbmRvIiwNCiAgICB2ZXNzZWxfc3RhdHVzID09ICJHcm91bmRlZCIgfiAiRW4gdGllcnJhIiwNCiAgICB2ZXNzZWxfc3RhdHVzID09ICJUb3dlZCIgfiAiUmVtb2xjYWRvIiwNCiAgKSkgJT4lIA0KICBtdXRhdGUodmVzc2VsX3N0YXR1cyA9IGZvcmNhdHM6OmFzX2ZhY3Rvcih2ZXNzZWxfc3RhdHVzKSkgJT4lIG11dGF0ZSh2ZXNzZWxfc3RhdHVzID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIodmVzc2VsX3N0YXR1cywgaCwgLmRlc2MgPSBGQUxTRSkpDQoNCg0KZ2dwbG90KGRhdGE9YXRfZXN0YWRvLCBhZXModmVzc2VsX3N0YXR1cywgaCkpICsgZ2VvbV9jb2woZmlsbD0iVGhpc3RsZSIpICsgDQogIGNvb3JkX2ZsaXAoKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyANCiAgbGFicyh0aXRsZSA9ICJFc3RhZG8gZGUgbGFzIGVtYmFyY2FjaW9uZXMiLA0KICAgIHggPSAiRXN0YWRvIGRlIGxhIGVtYmFyY2FjacOzbiIsDQogICAgeSA9ICJOw7ptZXJvIGRlIGVtYmFyY2FjaW9uZXMiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwKSwgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgaGp1c3QgPSAwLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBoanVzdCA9IDEsIHZqdXN0ID0gMCksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsIGhqdXN0ID0gMSwgdmp1c3QgPSAxKSkgDQoNCmBgYA0KDQpMYSBtYXlvcsOtYSBkZSBsYXMgZW1iYXJjYWNpb25lcyBjdWFuZG8gZnVlcm9uIGF0cmFjYWRhcyBzZSBlbmNvbnRyYWJhbiBhbmNsYWRhcywgbmF2ZWdhbmRvIG8gYXRyYWNhZGFzLiBMb3MgcGlyYXRhcyBzdWVsZW4gaHVpciBjdWFuZG8gc3VlbmFuIGxhcyBhbGFybWFzIGRlIGxvcyBiYXJjb3Mgc2luIGRhciB0aWVtcG8gYSBzZXIgYXRyYXBhZG9zLCBwb3IgbG8gcXVlIG11Y2hvcyBkZSBsb3MgaW5jaWRlbnRlcyByZXN1bHRhbiBubyBkZW51bmNpYXJzZS4gTGFzIGF1dG9yaWRhZGVzIHBvbmVuIGEgZGlzcG9zaWNpw7NuIEltYiBQaXJhY3kgUmVwb3J0aW5nIENlbnRyZSBkb25kZSBwdWVkZW4gcmVwb3J0YXIgdG9kb3MgbG9zIGluY2lkZW50ZXMgcXVlIHNlIHByb2R1emNhbi4NCg0KIyMgMy41IFRpcG8gZGUgZW1iYXJjYWNpb25lcw0KDQpTaSBjZW50cmFtb3MgZWwgZm9jbyBkZWwgYW7DoWxpc2lzIHNvYnJlIGVsIHRpcG8gZGUgYmFyY28gYXRhY2FkbywgcGFyYSBsb3MgY2luY28gdGlwb3MgbcOhcyBmcmVjdWVudGVzLCBubyBwb2RlbW9zIGV4dHJhZXIgbmluZ3VuYSBjb25jbHVzacOzbiB0YW4gY2xhcmE6DQoNCmBgYHtyfQ0KZGYgPC0gcGlyYXRlX2F0dGFja3MgfD4gZmlsdGVyKHZlc3NlbF90eXBlICVpbiUgYygJDQogICJCdWxrIENhcnJpZXIiLA0KICAiUHJvZHVjdCBUYW5rZXIiLA0KICAiQ29udGFpbmVyIiwNCiAgIkdlbmVyYWwgQ2FyZ28iLA0KICAiQ2hlbWljYWwgVGFua2VyIikpIA0KDQoNCmRhdGEoV29ybGQpDQp3b3JsZCA8LSBXb3JsZCB8PiBmaWx0ZXIoY29udGluZW50ICE9ICJBbnRhcmN0aWNhIikgOyBybShXb3JsZCkNCg0KbWFwX2J5X3R5cGUyIDwtIGdncGxvdCgpICsgDQogIGdlb21fc2YoZGF0YSA9IHdvcmxkLCBjb2xvciA9ICJncmV5IiwgZmlsbCA9ICJncmV5IiwgbHdkID0gMC4yLCBhZXMoZ2VvbWV0cnkgPSBnZW9tZXRyeSkpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IGRmLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBjb2xvciA9IHZlc3NlbF90eXBlKSwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjMpICsgdGhlbWUoYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikgKw0KICBsYWJzKHRpdGxlID0gIkF0YXF1ZXMgZGUgbG9zIHRpcG9zIGRlIGJhcmNvIG3DoXMgZnJlY3VlbnRlcyIsIA0KICAgICAgIHggPSBOVUxMLA0KICAgICAgIHkgPSBOVUxMLCANCiAgICAgICBjb2xvdXIgPSAiVGlwbyBkZSBiYXJjbyIpKw0KICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJHcmFuZWxlcm8iLCAiQnVxdWUgY2lzdGVybmFcbnF1w61taWNvIiwgIkNvbnRlbmVkb3IiLCAiQ2FyZ3Vlcm8iLCAiQnVxdWUgZGVcbnByb2R1Y3RvcyIpKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLA0KICAgIGNvbG91ciA9IE5BLCBoanVzdCA9IDAsIHZqdXN0ID0gMCksIA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMSwgMC4zKSwgDQogICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgDQoNCm1hcF9ieV90eXBlMiANCg0KYGBgDQoNCiMjIDMuNiBOb21icmVzIGRlIGxvcyBiYXJjb3MgbcOhcyBhdGFjYWRvcw0KDQpgYGB7cn0NCg0Kbm9tX2JhcmMgPC0gcGlyYXRlX2F0dGFja3MgJT4lIHNlbGVjdCh5ZWFyLCB2ZXNzZWxfbmFtZSkgJT4lIGdyb3VwX2J5KHllYXIpICAlPiUgY291bnQodmVzc2VsX25hbWUpICU+JSBmaWx0ZXIoIWlzLm5hKHZlc3NlbF9uYW1lKSkgJT4lIGZpbHRlcighdmVzc2VsX25hbWUgJWluJSBjKCJVbnNwZWNpZmllZCIsIk5hbWUgV2l0aGhlbGQiKSkgJT4lIGdyb3VwX2J5KHZlc3NlbF9uYW1lKSAlPiUgc3VtbWFyaXNlKGg9c3VtKG4pKSAlPiUgc2xpY2VfbWF4KG9yZGVyX2J5ID0gaCwgbj01KSAlPiUgIG11dGF0ZSh2ZXNzZWxfbmFtZSA9IGZvcmNhdHM6OmFzX2ZhY3Rvcih2ZXNzZWxfbmFtZSkpICU+JSBtdXRhdGUodmVzc2VsX25hbWUgPSBmb3JjYXRzOjpmY3RfcmVvcmRlcih2ZXNzZWxfbmFtZSwgaCwgLmRlc2MgPSBUUlVFKSkNCg0KDQoNCmxpYnJhcnkocGxvdGx5KQ0KDQoNCnAxIDwtIGdncGxvdChkYXRhPW5vbV9iYXJjLCBhZXModmVzc2VsX25hbWUsIGggKSkgKyBnZW9tX2NvbChmaWxsPSJQYWxlVmlvbGV0UmVkIikgKyB0aGVtZV9taW5pbWFsKCkgKyANCiAgbGFicyh0aXRsZSA9ICJOb21icmVzIGRlIGxhcyBlbWJhcmNhY2lvbmVzIG3DoXMgYXRhY2FkYXMiLA0KICAgICAgIHggPSAiTm9tYnJlIGRlbCBiYXJjbyIsDQogICAgICAgeSA9ICJOw7ptZXJvIGRlIGF0YXF1ZXMiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDApLCAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBoanVzdCA9IDAuNSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsIGhqdXN0ID0gMSwgdmp1c3QgPSAwKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMywgaGp1c3QgPSAxLCB2anVzdCA9IDEpKQ0KDQpzIDwtIGdncGxvdGx5KHAxKQ0KDQpodG1sdG9vbHM6OmRpdihzLCBhbGlnbiA9ICJjZW50ZXIiICkNCmBgYA0KDQpDb21vIGhlbW9zIGNvbWVudGFkbyBhbnRlcywgZWwgTWFlcnNrIEFsYW1hYmEgZnVlIHNlY3Vlc3RyYWRvIGFsbMOhIHBvciBlbCAyMDA5LCBjdWF0cm8gcGlyYXRhcyBzb21hbMOtcyB0b21hcm9uIHBvc2VzacOzbiBkZWwgYmFyY28uIEZ1ZSB1biBhY29udGVjaW1pbmV0byBpbXBvcnRhbnRlIHlhIHF1ZSBlcmEgZWwgcHJpbWVyIGFzYWx0byBxdWUgc2UgcmVhbGl6YWJhIGNvbiDDqXhpdG8gZGVzZGUgZWwgU2lnbG8gWElYIGEgdW4gYnVxdWUgcG9ydGFkb3IgZGUgbGEgYmFuZGVyYSBlc3RhZG91bmlkZW5zZS4gRW4gZXN0ZSBzZWN1ZXN0cm8gbG9zIHBpcmF0YXMgdHV2aWVyb24gdmlnaWxhZGEgYSBsYSB0cmlwdWxhY2nDs24gYSBwdW50YSBkZSBwaXN0b2xhLiBGaW5hbG1lbnRlIGxhIGFybWFkYSBkZSBFRS5VVSBhYmF0acOzIGEgdHJlcyBkZSBsb3Mgc2VjdWVzdHJhZG9yZXMuDQoNCk90cm8gZWplbXBsbyBjdXJpb3NvIGVzIGVsIGRlbCBUaG9yIEZhbGNvbiwgcXVlIHN1ZnJpw7MgNiBhdGFxdWVzIGVuIGVsIDIwMDMgc2VpcyBkw61hcyBzZWd1aWRvcy4gRXN0ZSBiYXJjbyBmdWUgYWJvcmRhZG8gY2VyY2EgZGUgQmFuZ2xhZGVzaCBsYXMgNiB2ZWNlcyBtaWVudHJhcyBzZSBlbmNvbnRyYWJhIGF0cmFjYWRvLg0KDQojIDQuIERhdGFzZXQgZGUgbG9zIFBhw61zZXMNCg0KIyMjIyAgey50YWJzZXR9DQoNCiMjIyMjICoqSW5mb3JtYWNpw7NuKioNCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQpvcHRpb25zKHNjaXBlbiA9IDk5OSkNCg0KIyBEYXRvcw0KDQpjb2RpZ29zIDwtIHJpbzo6aW1wb3J0KGhlcmU6OmhlcmUoImRhdG9zIiwgImNvdW50cnlfY29kZXMuY3N2IikpDQoNCmluZGljYWRvcmVzIDwtIHJpbzo6aW1wb3J0KGhlcmU6OmhlcmUoImRhdG9zIiwgImNvdW50cnlfaW5kaWNhdG9ycy5jc3YiKSkNCg0KcGFpc2VzIDwtIGZ1bGxfam9pbihjb2RpZ29zLCBpbmRpY2Fkb3JlcywgYnk9IGMoImNvdW50cnkiID0gImNvdW50cnkiKSkNCg0KbWVkaWFfcGFpc2VzIDwtIHBhaXNlcyAlPiUgZ3JvdXBfYnkoY291bnRyeSwgY291bnRyeV9uYW1lKSAlPiUgc3VtbWFyaXNlKG1lZGlhX2NvcnJ1cGNpw7NuID0gbWVhbihjb3JydXB0aW9uX2luZGV4LCBuYS5ybSA9IFRSVUUpLCBtZWRpYV9ob21pY2lkaW9zID0gbWVhbihob21pY2lkZV9yYXRlLCBuYS5ybSA9IFRSVUUpLCBtZWRpYV9taWxpdGFyID0gbWVhbih0b3RhbF9taWxpdGFyeSwgbmEucm0gPSBUUlVFKSwgbWVkaWFfZ2FzdG8gPSBtZWFuKHRvdGFsZ3IsIG5hLnJtPSBUUlVFKSkNCmBgYA0KDQpFbCBzaWd1aWVudGUgZGF0YXNldCBjb24gZWwgcXVlIHZhbW9zIGEgdHJhYmFqYXIgY29udGllbmUgZGF0b3MgZGUgdW5hIHNlcmllIGRlIGluZGljYWRvcmVzIHBhcmEgbGEgbWF5b3LDrWEgZGUgcGHDrXNlcyBkZWwgbXVuZG8uIEVzdG9zIHBhw61zZXMgdmllbmVuIGFncnVwYWRvcyBlbiByZWdpb25lcywgbGFzIGN1YWxlcyBubyBjb2luY2lkZW4gbmVjZXNhcmlhbWVudGUgY29uIGxvcyBjb250aW5lbnRlcy4gUG9yIGVzdGUgbW90aXZvLCByZXN1bHRhIGludGVyZXNhbnRlIHJlYWxpemFyIHVuIHByaW1lciBhbsOhbGlzaXMgZXhwbG9yYXRvcmlvIGRlIGxvcyBwcmluY2lwYWxlcyBpbmRpY2Fkb3JlcyBkZWwgZGF0YXNldCBwb3IgcmVnaW9uZXMsIHBhcmEgZGVzcHXDqXMgY2VudHJhcm5vcyBtw6FzIGRlIGNlcmNhIGVuIGFxdWVsbG9zIHBhw61zZXMgbcOhcyByZWxldmFudGVzDQoNCiMjIyMjICoqRGF0YXNldCoqDQoNCmBgYHtyfQ0KZGF0YXRhYmxlKHBhaXNlcywgcm93bmFtZXMgPSBGQUxTRSwgZmlsdGVyPSJ0b3AiLCBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsIHNjcm9sbFg9VCkpDQpgYGANCg0KIyMjIyANCg0KIyMgNC4xIEFuw6FsaXNpcyBwb3IgcmVnaW9uZXMNCg0KUGFyYSBjb21lbnphciwgcmVhbGl6YXJlbW9zIHVuIGFuw6FsaXNpcyBleHBsb3JhdG9yaW8gZGUgbG9zIHByaW5jaXBhbGVzIGRhdG9zIGRlIGVzdGUgZGF0YXNldCBwb3IgcmVnaW9uZXMuIEVuIGVsIG1hcGEgcXVlIHNlIG11ZXN0cmEgYSBjb250aW51YWNpw7NuIHNlIHJlcHJlc2VudGFuIGxhcyBkaXN0aW50YXMgcmVnaW9uZXMgZW4gbGFzIHF1ZSB2aWVuZW4gYWdydXBhZG9zIGxvcyBwYcOtc2VzLiBDYWJlIGRlc3RhY2FyIGNhc29zIGNvbW8gZWwgZGUgTcOpeGljby4gUGHDrXMgcXVlLCBhdW4gZXN0YW5kbyBlbiBOb3J0ZSBBbcOpcmljYSwgdmllbmUgcmVjb2dpZG8gcG9yIGxhIHJlZ2nDs24gZGUgQW3DqXJpY2EgbGF0aW5hIHkgZWwgQ2FyaWJlLg0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjkwJSJ9DQptZWRpYV9yZWdpb25lcyA8LSBwYWlzZXMgJT4lIA0KICBzZWxlY3QocmVnaW9uLCBjb3VudHJ5X25hbWUsIHRvdGFsX21pbGl0YXJ5KSAlPiUgDQogIGdyb3VwX2J5KHJlZ2lvbiwgY291bnRyeV9uYW1lKSAlPiUgDQogIHN1bW1hcmlzZShtZWRpYV9taWxpdGFyID0gbWVhbih0b3RhbF9taWxpdGFyeSwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIGdyb3VwX2J5KHJlZ2lvbikgJT4lICANCiAgbXV0YXRlKG1lZGlhX21pbGl0YXIgPSBtZWFuKG1lZGlhX21pbGl0YXIsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgbXV0YXRlKGlzbzIgPSBjb3VudHJ5Y29kZTo6Y291bnRyeWNvZGUoDQogICAgc291cmNldmFyID0gY291bnRyeV9uYW1lLCBvcmlnaW4gPSAiY291bnRyeS5uYW1lIiwNCiAgICBkZXN0aW5hdGlvbiA9ICAiaXNvMmMiLCB3YXJuID0gRkFMU0UpLCAuYWZ0ZXIgPSBjb3VudHJ5X25hbWUpIA0KDQptYXBhX211bmRvIDwtIG1hcF9kYXRhKCJ3b3JsZCIpICU+JSANCiAgbXV0YXRlKGlzbzIgPSBjb3VudHJ5Y29kZTo6Y291bnRyeWNvZGUoDQogICAgc291cmNldmFyID0gcmVnaW9uLCBvcmlnaW4gPSAiY291bnRyeS5uYW1lIiwNCiAgICBkZXN0aW5hdGlvbiA9ICAiaXNvMmMiLCB3YXJuID0gRkFMU0UpLCAuYWZ0ZXIgPSByZWdpb24pIA0KDQpwYWlzZXNfbWFwYSA8LSBmdWxsX2pvaW4obWFwYV9tdW5kbywgbWVkaWFfcmVnaW9uZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSBjKCJpc28yIj0iaXNvMiIpKQ0KDQp0IDwtIHBhaXNlc19tYXBhICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21fcG9seWdvbihhZXMoeD0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHJlZ2lvbi55KSwNCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlJlcHJlc2VudGFjacOzbiBkZSBsb3NcbnBhw61zZXMgZGUgY2FkYSByZWdpw7NuIiwNCiAgICBmaWxsID0gIlJlZ2lvbmVzIg0KICApICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShicmVha3MgPSBjKCJFYXN0IEFzaWEgJiBQYWNpZmljIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXVyb3BlICYgQ2VudHJhbCBBc2lhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGF0aW4gQW1lcmljYSAmIENhcmliYmVhbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1pZGRsZSBFYXN0ICYgTm9ydGggQWZyaWNhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ydGggQW1lcmljYSIsICJTb3V0aCBBc2lhIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3ViLVNhaGFyYW4gQWZyaWNhIiksIA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkFzaWEgZGVsIEVzdGVcbiYgUGFjw61maWNvIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXVyb3BhXG4mIEFzaWEgQ2VudHJhbCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhdGlubyBBbcOpcmljYVxuJiBDYXJpYmUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPcmllbnRlIE1lZGlvXG4mIE5vcnRlIGRlIEFmcmljYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFtw6lyaWNhXG5kZWwgTm9ydGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdXJcbmRlIEFzaWEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDgWZyaWNhXG5TdWItU2FoYXJpYW5hIikpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCgNCiAgICBzaXplID0gMTUsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPSAxLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZTIiKSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2U9ICJib2xkIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSArDQogIGNvb3JkX2ZpeGVkICh4bGltPSBjKC0yMDAsMjAwKSwNCiAgICAgICAgICAgICAgIHlsaW09IGMoLTU4LDkwKSwNCiAgICAgICAgICAgICAgIHJhdGlvID0gMS4zKSANCg0KdA0KYGBgDQoNCiMjIyA0LjEuMSBFdm9sdWNpw7NuIMOtbmRpY2UgZGUgY29ycnVwY2nDs24gey50YWJzZXR9DQoNCkVsIMOtbmRpY2UgZGUgY29ycnVwY2nDs24gZXMgdW4gaW5kaWNhZG9yIHF1ZSBtaWRlIGxhIHBlcmNlcGNpw7NuIGRlIGNvcnJ1cGNpw7NuIGVuIGNhZGEgdW5vIGRlIGxvcyBwYcOtc2VzLiBFcyB1biBpbmRpY2Fkb3IgcHVibGljYWRvIHBvciBUcmFuc3BhcmVuY2lhIEludGVybmFjaW9uYWwgZGVzZGUgMTk5NSwgc2llbmRvIDEwMCB1biBuaXZlbCBkZSBjb3JydXBjacOzbiBudWxvIHkgMCB1biBuaXZlbCBkZSBjb3JydXBjacOzbiBtdXkgZWxldmFkby4NCg0KRXMgaW1wb3J0YW50ZSBkZXN0YWNhciBxdWUgaGFzdGEgZWwgYcOxbyAyMDEyLCBlbCDDrW5kaWNlIGRlIGNvcnJ1cGNpw7NuIHZlbsOtYSByZWNvZ2lkbyBlbiB1bmEgZXNjYWxhIGRlbCAwIGFsIDEwLiBTaW4gZW1iYXJnbywgZW4gMjAxMiBsYSBlc2NhbGEgZnVlIGNhbWJpYWRhIGRlIDAgYSAxMDAuIFBvciBlc3RlIG1vdGl2bywgaGVtb3MgcmVhbGl6YWRvIHVuIGNhbWJpbyBkZSBlc2NhbGEgcGFyYSBsb3MgYcOxb3MgYW50ZXJpb3JlcyBhIDIwMTIsIG9idGVuaWVuZG8gZGUgZXN0ZSBtb2RvIHZhbG9yZXMgZW50cmUgMCB5IDEwMCBwYXJhIHRvZG8gZWwgcGVyaW9kbyBhbmFsaXphZG8uDQoNCiMjIyMgKipHcsOhZmljbyoqDQoNCkEgY29udGludWFjacOzbiBwb2RlbW9zIG9ic2VydmFyIGxhIGV2b2x1Y2nDs24gZGVsIMOtbmRpY2UgZGUgY29ycnVwY2nDs24gZGVzZGUgMTk5NSBoYXN0YSAyMDE5LCBhIGV4Y2VwY2nDs24gZGVsIGHDsW8gMTk5OSBlbiBlbCBjdWFsIG5vIGV4aXN0ZW4gZGF0b3MuIExhIHJlZ2nDs24gbWVqb3IgY29uc2lkZXJhZGEgZXMgQW3DqXJpY2EgZGVsIE5vcnRlLCBtaWVudHJhcyBxdWUgw4FmcmljYSBTdWItU2FoYXJpYW5hIGVzIGxhIHJlZ2nDs24gY29uIGxhIHBlb3IgY2FsaWZpY2FjacOzbiBlbiBlc3RlIGFwYXJ0YWRvLg0KDQpPdHJvIGhlY2hvIHJlbGV2YW50ZSBlcyBsYSBkaXNtaW51Y2nDs24gZGUgZXN0ZSDDrW5kaWNlIHRyYXMgbGEgY3Jpc2lzIGZpbmFuY2llcmEgZGVsIDIwMDggeSBzdSBwb3N0ZXJpb3IgcmVjYcOtZGEgZW4gMjAxNCBlbiBsYXMgcmVnaW9uZXMgbcOhcyByaWNhcy4gRXN0ZSBoZWNobyBwdWVkZSBkZWJlcnNlIGEgbGEgbmF0dXJhbGV6YSBkZSBlc3RlIGluZGljYWRvciwgcHVlc3RvIHF1ZSBzZSBvYnRpZW5lIGEgdHJhdsOpcyBkZSBlbmN1ZXN0YXMgZGUgb3BpbmnDs24gYSBsYSBjaXVkYWRhbsOtYSB5IGV2YWx1YWNpb25lcyBkZSBleHBlcnRvcy4NCg0KYGBge3J9DQptZWRpYV9yZWdpb25lcyA8LSBwYWlzZXMgJT4lIA0KICBncm91cF9ieShyZWdpb24sIHllYXIpICU+JSANCiAgc3VtbWFyaXNlKG1lZGlhX2NvcnJ1cGNpw7NuID0gbWVhbihjb3JydXB0aW9uX2luZGV4LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbWVkaWFfaG9taWNpZGlvcyA9IG1lYW4oaG9taWNpZGVfcmF0ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG1lZGlhX21pbGl0YXIgPSBtZWFuKHRvdGFsX21pbGl0YXJ5LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbWVkaWFfZ2FzdG8gPSBtZWFuKHRvdGFsZ3IsIG5hLnJtPSBUUlVFKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIG11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyh5ZWFyKSkgJT4lDQogIG11dGF0ZShtZWRpYV9jb3JydXBjacOzbiA9IGlmZWxzZSgNCiAgICB5ZWFyPDIwMTIsIG1lZGlhX2NvcnJ1cGNpw7NuICoxMCwgbWVkaWFfY29ycnVwY2nDs24pKSAlPiUNCiAgZmlsdGVyKHllYXIgPj0gMTk5NSkgJT4lIA0KICBtdXRhdGUobWVkaWFfcmVnaW9uZXM9IGlzLm51bWVyaWMobWVkaWFfcmVnaW9uZXMpKQ0KDQp6eiA8LSBtZWRpYV9yZWdpb25lcyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gcmVnaW9uLCANCiAgICAgICAgICAgICB5ID0gbWVkaWFfY29ycnVwY2nDs24sIA0KICAgICAgICAgICAgIGZpbGw9IHJlZ2lvbiApKSArDQogIGdlb21fYmFyKHN0YXQ9ICJpZGVudGl0eSIsIA0KICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIA0KICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtZWRpYV9jb3JydXBjacOzbiwgZGlnaXRzID0gMikpLCANCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSwgDQogICAgICAgICAgICB2anVzdD0gMS4yLCANCiAgICAgICAgICAgIHNpemUgPSA1LCANCiAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIikrDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiQXNpYSBkZWwgRXN0ZVxuJiBQYWPDrWZpY28iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFdXJvcGFcbiYgQXNpYSBDZW50cmFsIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGF0aW5vIEFtw6lyaWNhXG4mIENhcmliZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9yaWVudGUgTWVkaW9cbiYgTm9ydGUgZGUgQWZyaWNhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbcOpcmljYVxuZGVsIE5vcnRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3VyXG5kZSBBc2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDgWZyaWNhXG5TdWItU2FoYXJpYW5hIikpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogIHRoZW1lX21pbmltYWwoKSsNCiAgZW50ZXJfYXBwZWFyKCkgKw0KICB0cmFuc2l0aW9uX3N0YXRlcyh5ZWFyLCANCiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbl9sZW5ndGggPSAxLjUsIA0KICAgICAgICAgICAgICAgICAgICBzdGF0ZV9sZW5ndGggPSAyKSArDQogIGxhYnModGl0bGUgPSAiIEV2b2x1Y2nDs24gZGVsIMOtbmRpY2UgZGUgY29ycnVwY2nDs24gcG9yIHJlZ2lvbmVzICBcbiBBw7FvOiB7Y2xvc2VzdF9zdGF0ZX0iLCANCiAgICAgICBzdWJ0aXRsZSA9ICJFdm9sdWNpw7NuIHBvciByZWdpb25lcyIsDQogICAgICAgeSA9ICIiLA0KICAgICAgIHggPSAiIikgKw0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJwbGFpbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMC41KSkgDQoNCg0KYW5pbWF0ZSh6eiwgd2lkdGggPSA3MDAsIGhlaWdodCA9IDcwMCwgZnBzID0gMiwgDQogICAgICAgIGR1cmF0aW9uID0gMzAsIHJld2luZCA9IEZBTFNFKSANCmBgYA0KDQojIyMjICoqVGFibGEqKg0KDQpgYGB7cn0NCm1lZGlhX3JlZ2lvbmVzICU+JSAjZ3RUYWJsZQ0KICBzZWxlY3QocmVnaW9uLCB5ZWFyLCBtZWRpYV9jb3JydXBjacOzbikgJT4lIA0KICBmaWx0ZXIoIXllYXIgJWluJSBjKDE5OTMsIDE5OTQsMTk5OSwgTkEpKSAlPiUNCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJyZWdpb24iLCANCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSAibWVkaWFfY29ycnVwY2nDs24iKSAlPiUgDQogIGd0KHJvd25hbWVfY29sID0gInllYXIiKSAlPiUgDQogIHRhYl9oZWFkZXIodGl0bGUgPSBtZCgiw41uZGljZSBkZSBjb3JydXBjacOzbiBwb3IgcmVnaW9uZXMiKSwNCiAgICAgICAgICAgICBzdWJ0aXRsZSA9IG1kKCJEZSAxOTk1IGEgMjAxOSIpKSAlPiUgDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICJtaWRuaWdodGJsdWUiKSAlPiUNCiAgdGFiX29wdGlvbnMoaGVhZGluZy50aXRsZS5mb250LnNpemUgPSAyNSwNCiAgICAgICAgICAgICAgaGVhZGluZy5zdWJ0aXRsZS5mb250LnNpemUgPSAyMCwgDQogICAgICAgICAgICAgIGNvbHVtbl9sYWJlbHMuZm9udC53ZWlnaHQgPSAgImJvbGQiLCANCiAgICAgICAgICAgICAgaGVhZGluZy5hbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIHRhYl9vcHRpb25zKHRhYmxlLmFsaWduID0gImNlbnRlciIpICU+JSANCiAgY29sc19hbGlnbihhbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIGNvbHNfbGFiZWwoYEVhc3QgQXNpYSAmIFBhY2lmaWNgID0gIkFzaWEgZGVsIEVzdGUgJiBQYWPDrWZpY28iLA0KICAgICAgICAgICAgIGBFdXJvcGUgJiBDZW50cmFsIEFzaWFgID0gIkV1cm9wYSAmIEFzaWEgQ2VudHJhbCIsIA0KICAgICAgICAgICAgIGBMYXRpbiBBbWVyaWNhICYgQ2FyaWJiZWFuYCA9ICJMYXRpbm8gQW3DqXJpY2EgJiBDYXJpYmUiLA0KICAgICAgICAgICAgIGBNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYWAgPSANCiAgICAgICAgICAgICAgICJPcmllbnRlIE1lZGlvICYgTm9ydGUgZGUgQWZyaWNhIiwgDQogICAgICAgICAgICAgYE5vcnRoIEFtZXJpY2FgID0gIkFtw6lyaWNhIGRlbCBOb3J0ZSIsIA0KICAgICAgICAgICAgIGBTb3V0aCBBc2lhYCA9ICJTdXIgZGUgQXNpYSIsIA0KICAgICAgICAgICAgIGBTdWItU2FoYXJhbiBBZnJpY2FgID0gIsOBZnJpY2EgU3ViLVNhaGFyaWFuYSIpICU+JSANCiAgZm10X251bWJlcihjb2x1bW5zPSAyOjgsIA0KICAgICAgICAgICAgIGRlY2ltYWxzID0gMiwNCiAgICAgICAgICAgICBkZWNfbWFyayA9ICIsIikNCmBgYA0KDQojIyMgNC4xLjIgRXZvbHVjacOzbiB0YXNhIGRlIGhvbWljaWRpb3Mgey50YWJzZXR9DQoNCkxhIHRhc2EgZGUgaG9taWNpZGlvcyBtaWRlIGVsIG7Dum1lcm8gZGUgbXVlcnRlcyBhIGNhdXNhIGRlIGxhIGFjY2nDs24gZGUgb3RyYSBwZXJzb25hIChkZSBtYW5lcmEgdm9sdW50YXJpYSBvIG5vKSBwb3IgY2FkYSAxMDAuMDAwIGhhYml0YW50ZXMuIEVzdGUgaW5kaWNhZG9yIG5vcyBheXVkYSBhIG1lZGlyIGVsIMOtbmRpY2UgZGUgdmlvbGVuY2lhIGRlIHVuIHBhw61zLiBQb3IgZWxsbywgY29icmEgZXNwZWNpYWwgaW1wb3J0YW5jaWEgZW4gbnVlc3RybyBlc3R1ZGlvLCBkZWJpZG8gYSBxdWUgbGEgcGlyYXRlcsOtYSBtYXLDrXRpbWEgc2UgbGxldmEgYSBjYWJvIGEgdHJhdsOpcyBkZSBhY3RvcyB2aW9sZW50b3MgY29tbyBzb24gc2VjdWVzdHJvcywgcm9ib3MgbyBleHRvcnNpb25lcy4gQXPDrSBwdWVzLCBlcyBwb3NpYmxlIHF1ZSBleGlzdGEgdW5hIGZ1ZXJ0ZSBjb3JyZWxhY2nDs24gZW50cmUgZXN0ZSBpbmRpY2Fkb3IgeSBsb3MgYXRhcXVlcyBkZSBwaXJhdGFzLg0KDQojIyMjICoqR3LDoWZpY28qKg0KDQpgYGB7cn0NCm1lZGlhX3JlZ2lvbmVzIDwtIHBhaXNlcyAlPiUgZ3JvdXBfYnkocmVnaW9uLCB5ZWFyKSAlPiUNCiAgc3VtbWFyaXNlKG1lZGlhX2NvcnJ1cGNpw7NuID0gbWVhbihjb3JydXB0aW9uX2luZGV4LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbWVkaWFfaG9taWNpZGlvcyA9IG1lYW4oaG9taWNpZGVfcmF0ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG1lZGlhX21pbGl0YXIgPSBtZWFuKHRvdGFsX21pbGl0YXJ5LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbWVkaWFfZ2FzdG8gPSBtZWFuKHRvdGFsZ3IsIG5hLnJtPSBUUlVFKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKQ0KDQpiYiA8LSBtZWRpYV9yZWdpb25lcyAlPiUNCiAgZmlsdGVyKCF5ZWFyICVpbiUgYygyMDE5LCBOQSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHg9IHllYXIsIHk9IG1lZGlhX2hvbWljaWRpb3MpKSArIA0KICBsYWJzKHRpdGxlID0gIkV2b2x1Y2nDs24gdGFzYSBkZSBob21pY2lkaW9zXG5wb3IgcmVnaW9uZXMiLA0KICAgICAgIHg9ICJBw7FvIiwNCiAgICAgICB5PSAiw41uZGljZSBkZSBob21pY2lkaW9zIG1lZGlvIiwNCiAgICAgICBjb2xvciA9ICJSZWdpb25lcyIpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9IHJlZ2lvbiksIHNpemU9IDMpICsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj0gcmVnaW9uKSwgc2l6ZT0gMS41KSArIA0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPSBjKCJyZWQiLCAiYmx1ZSIsICJncmVlbiIsICJibGFjayIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInllbGxvdyIsICJvcmFuZ2UiLCAibWlkbmlnaHRibHVlIiksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJBc2lhIGRlbCBFc3RlXG4mXG5QYWPDrWZpY28iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXVyb3BhXG4mXG5Bc2lhIENlbnRyYWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGF0aW5vIEFtw6lyaWNhXG4mXG5DYXJpYmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3JpZW50ZSBNZWRpb1xuJlxuTm9ydGUgZGUgQWZyaWNhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFtw6lyaWNhXG5kZWxcbk5vcnRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlN1clxuZGVcbkFzaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiw4FmcmljYVxuU3ViLVNhaGFyaWFuYSIpKSsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAwLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBoanVzdCA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDApLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBoanVzdCA9IDEsIHZqdXN0ID0gMSksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkgKw0KICB0cmFuc2l0aW9uX3JldmVhbCh5ZWFyKSArIA0KICB2aWV3X2ZvbGxvdygpDQoNCmJiICNnZ2FuaW1hdGUgIA0KYGBgDQoNCkVsIHVzbyBkZSBncsOhZmljb3MgZGUgbMOtbmVhcyBhbmltYWRvcyBlcyB1bmEgYnVlbmEgaGVycmFtaWVudGEgcGFyYSBhbmFsaXphciBsYSBldm9sdWNpw7NuIGRlIHVuYSB2YXJpYWJsZSBkZSBmb3JtYSBkaW7DoW1pY2EgeSBzZW5jaWxsYS4gUGFyYSBsYSB0YXNhIGRlIGhvbWljaWRpb3MsIGV4dHJhZW1vcyBxdWUgcGFyYSB0b2RvIGVsIHBlcmlvZG8gbGEgcmVnacOzbiBjb24gbGEgbWF5b3IgdGFzYSBoYSBzaWRvIExhdGlubyBBbcOpcmljYSB5IGVsIENhcmliZSB5IMOBZnJpY2EgU3ViLVNhaGFyaWFuYS4gU2luIGVtYmFyZ28sIGVuIGVsIGNhc28gZGUgZXN0ZSDDumx0aW1vLCBlc3RlIMOtbmRpY2Ugc2UgaGEgaWRvIHJlZHVjaWVuZG8gYcOxbyB0cmFzIGHDsW8uDQoNCkVuIGxvIHF1ZSByZXNwZWN0YSBhbCByZXN0byBkZSByZWdpb25lcywgaGFuIG1hbnRlbmlkbyBzdSBuaXZlbCBjb25zdGFudGUgYSBsbyBsYXJnbyBkZWwgcGVyaW9kby4gRGVzdGFjYSBlbCBjYXNvIGRlIE9yaWVudGUgTWVkaW8geSBlbCBOb3J0ZSBkZSDDgWZyaWNhLCBjdXlvIMOtbmRpY2UgaGEgc2lkbyB5IGVzIGVsIG1lbm9yLiBSZXN1bHRhIHNvcnByZW5kZW50ZSB5YSBxdWUgZXN0YSByZWdpw7NuIGxhIGZvcm1hbiBwYcOtc2VzIHF1ZSBkdXJhbnRlIGVsIHBlcmlvZG8gaGFuIGVzdGFkbyBlbiBndWVycmEsIGNvbW8gZXMgZWwgY2FzbyBkZSBMaWJpYS4gRGV0csOhcyBkZSBlc3RlIGZlbsOzbWVubyBlcyBwb3NpYmxlIHF1ZSBleGlzdGEgdW5hIGluY29ycmVjdGEgbWVkaWNpw7NuIG8gbGEgZmFsdGEgZGUgZGF0b3MgcXVlIHJlYWxtZW50ZSBkZXNjcmliYW4gbGEgc2l0dWFjacOzbiBkZSBlc3RvcyBwYcOtc2VzLg0KDQojIyMjICoqVGFibGEqKg0KDQpgYGB7cn0NCm1lZGlhX3JlZ2lvbmVzICU+JSAjZ3RUYWJsZQ0KICBzZWxlY3QocmVnaW9uLCB5ZWFyLCBtZWRpYV9ob21pY2lkaW9zKSAlPiUNCiAgZmlsdGVyKCF5ZWFyICVpbiUgYygyMDE5LCBOQSkpICU+JSANCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJyZWdpb24iLCB2YWx1ZXNfZnJvbSA9ICJtZWRpYV9ob21pY2lkaW9zIikgJT4lIA0KICBndChyb3duYW1lX2NvbCA9ICJ5ZWFyIikgJT4lIA0KICB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIsONbmRpY2UgZGUgaG9taWNpZGlvcyBwb3IgcmVnaW9uZXMiKSwNCiAgICAgICAgICAgICBzdWJ0aXRsZSA9IG1kKCJEZSAxOTkzIGEgMjAxOCIpKSAlPiUgDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICJzZWFncmVlbiIpICU+JQ0KICB0YWJfb3B0aW9ucyhoZWFkaW5nLnRpdGxlLmZvbnQuc2l6ZSA9IDI1LA0KICAgICAgICAgICAgICBoZWFkaW5nLnN1YnRpdGxlLmZvbnQuc2l6ZSA9IDIwLA0KICAgICAgICAgICAgICBjb2x1bW5fbGFiZWxzLmZvbnQud2VpZ2h0ID0gICJib2xkIiwNCiAgICAgICAgICAgICAgaGVhZGluZy5hbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIHRhYl9vcHRpb25zKHRhYmxlLmFsaWduID0gImNlbnRlciIpICU+JSANCiAgY29sc19hbGlnbihhbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIGNvbHNfbGFiZWwoYEVhc3QgQXNpYSAmIFBhY2lmaWNgID0gIkFzaWEgZGVsIEVzdGUgJiBQYWPDrWZpY28iLA0KICAgICAgICAgICAgIGBFdXJvcGUgJiBDZW50cmFsIEFzaWFgID0gIkV1cm9wYSAmIEFzaWEgQ2VudHJhbCIsIA0KICAgICAgICAgICAgIGBMYXRpbiBBbWVyaWNhICYgQ2FyaWJiZWFuYCA9ICJMYXRpbm8gQW3DqXJpY2EgJiBDYXJpYmUiLA0KICAgICAgICAgICAgIGBNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYWAgPSANCiAgICAgICAgICAgICAgICJPcmllbnRlIE1lZGlvICYgTm9ydGUgZGUgQWZyaWNhIiwgDQogICAgICAgICAgICAgYE5vcnRoIEFtZXJpY2FgID0gIkFtw6lyaWNhIGRlbCBOb3J0ZSIsIA0KICAgICAgICAgICAgIGBTb3V0aCBBc2lhYCA9ICJTdXIgZGUgQXNpYSIsIA0KICAgICAgICAgICAgIGBTdWItU2FoYXJhbiBBZnJpY2FgID0gIsOBZnJpY2EgU3ViLVNhaGFyaWFuYSIpICU+JSANCiAgZm10X251bWJlcihjb2x1bW5zPSAyOjgsIA0KICAgICAgICAgICAgIGRlY2ltYWxzID0gMiwNCiAgICAgICAgICAgICBkZWNfbWFyayA9ICIsIikNCmBgYA0KDQojIyMgNC4xLjMgTWVkaWEgZGUgaW5ncmVzb3MgcMO6YmxpY29zIHsudGFic2V0fQ0KDQpFbCBzaWd1aWVudGUgaW5kaWNhZG9yIHF1ZSB0cmFiYWphcmVtb3MgZXMgbGEgbWVkaWEgZGUgaW5ncmVzb3MgcMO6YmxpY29zIHBvciByZWdpw7NuLiBFc3RlIGluZGljYWRvciBlcyB1biBidWVuYSBhcHJveGltYWNpw7NuIGRlbCBnYXN0byBkZSBlc3RvcyBwYcOtc2VzLCBwdWVzdG8gcXVlIG1heW9yZXMgaW5ncmVzb3Mgc3VlbGUgaXIgYWNvbXBhw7FhZG8gZGUgbWF5b3IgZ2FzdG8uIEFkZW3DoXMsIGZyZWN1ZW50ZW1lbnRlIGxvcyBwYcOtc2VzIG3DoXMgc2VndXJvcyBzb24gYXF1ZWxsb3MgZW4gbG9zIHF1ZSBsYSBwcmVzacOzbiBmaXNjYWwgZXMgbcOhcyBhbHRhLiBFc3RvIHNlIGRlYmUsIGVudHJlIG90cm9zIGZhY3RvcmVzLCBhIHVuYSBtZWpvciBkb3RhY2nDs24gZGUgbWVkaW9zIHBhcmEgbG9zIGN1ZXJwb3MgZGUgc2VndXJpZGFkLg0KDQojIyMjICoqR3LDoWZpY28qKg0KDQpBIGxhIGhvcmEgZGUgZGVzY3JpYmlyIGxhIGV2b2x1Y2nDs24gZGUgdW5hIHZhcmlhYmxlIGVzIGhhYml0dWFsIGVsIHVzbyBkZSBncsOhZmljb3MgZGUgbMOtbmVhcy4gTm8gb2JzdGFudGUsIGV4aXN0ZW4gb3RyYXMgZm9ybWFzIG11eSDDunRpbGVzIGRlIHJlcHJlc2VudGFyIGxhIHZhcmlhY2nDs24gZGUgdW4gaW5kaWNhZG9yIGEgbG8gbGFyZ28gZGVsIHRpZW1wby4gRW4gZXN0ZSBjYXNvLCBoZW1vcyBoZWNobyB1c28gZGUgdW4gYm94cGxvdC4gRW4gw6lsLCBwb2RlbW9zIG9ic2VyY2FyIGxhIG1lZGlhIGRlIGxvcyBpbmdyZXNvcyBww7pibGljb3MgcG9yIGNhZGEgcmVnacOzbiwgYWRlbcOhcyBkZWwgcHJpbWVyIHkgdGVyY2VyIGN1YXJ0aWwuIEZpbmFsbWVudGUsIHRhbWJpw6luIG9ic2VydmFtb3MgY2FkYSB1bmEgZGUgbGFzIG9ic2VydmFjaW9uZXMgcGFyYSBjYWRhIGHDsW8uDQoNCmBgYHtyLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD03fQ0KbWVkaWFfcmVnaW9uZXMgPC0gcGFpc2VzICU+JSBncm91cF9ieShyZWdpb24sIHllYXIpICU+JQ0KICBzdW1tYXJpc2UobWVkaWFfY29ycnVwY2nDs24gPSBtZWFuKGNvcnJ1cHRpb25faW5kZXgsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBtZWRpYV9ob21pY2lkaW9zID0gbWVhbihob21pY2lkZV9yYXRlLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbWVkaWFfbWlsaXRhciA9IG1lYW4odG90YWxfbWlsaXRhcnksIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBtZWRpYV9nYXN0byA9IG1lYW4odG90YWxnciwgbmEucm09IFRSVUUpKSAlPiUNCiAgdW5ncm91cCgpICU+JSBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoeWVhcikpDQoNCm1lZGlhX3JlZ2lvbmVzICU+JSANCiAgc2VsZWN0KHJlZ2lvbiwgeWVhciwgbWVkaWFfZ2FzdG8pICU+JQ0KICBmaWx0ZXIoIXllYXIgPT0gaXMubmEoeWVhcikpICU+JSANCiAgbXV0YXRlKHllYXIgPSBhcy5jaGFyYWN0ZXIoeWVhcikpICU+JSANCiAgZ2dwbG90KGFlcyh4PSByZWdpb24sIHk9IG1lZGlhX2dhc3RvKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIA0KICBnZW9tX2ppdHRlcihhZXMoY29sb3I9IHllYXIpLCBzaXplPSAyKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiQXNpYSBkZWwgRXN0ZVxuJlxuUGFjw61maWNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFdXJvcGFcbiZcbkFzaWEgQ2VudHJhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGF0aW5vIEFtw6lyaWNhXG4mXG5DYXJpYmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9yaWVudGUgTWVkaW9cbiZcbk5vcnRlIGRlIEFmcmljYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQW3DqXJpY2FcbmRlbFxuTm9ydGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdXJcbmRlXG5Bc2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDgWZyaWNhXG5TdWItU2FoYXJpYW5hIikpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICBsYWJzKHRpdGxlID0gIlBvcmNlbnRhamUgaW5ncmVzb3MgcMO6YmxpY29zIHBvciByZWdpw7NuIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJEZSAxOTkzIGEgMjAxOSIsDQogICAgICAgeD0gIlJlZ2nDs24iLA0KICAgICAgIHk9ICJJbmdyZXNvcyBww7pibGljb3MgKCVQSUIpIiwNCiAgICAgICBjb2xvciA9ICJBw7FvIikgKw0KICB0aGVtZV9pcHN1bSgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSkpDQpgYGANCg0KQ2FiZSBkZXN0YWNhciBsYXMgZ3JhbmRlcyBkaWZlcmVuY2lhcyBxdWUgZXhpc3RlbiBlbnRyZSBsYXMgcmVnaW9uZXMgZW4gbG8gcmVmZXJlbnRlIGEgc3VzIHBvbMOtdGljYXMgZmlzY2FsZXMuIE1pZW50cmFzIGVuIGxvcyBwYcOtc2VzIGV1cm9wZW9zIGV4aXN0ZSB1bmEgaW1wb3J0YW50ZSBwcmVzacOzbiBmaXNjYWwsIGVuIHJlZ2lvbmVzIGNvbW8gZWwgc3VyIGRlIEFzw61hIGVzdGEgcHJlc2nDs24gZmlzY2FsIHNlIHJlZHVjZSBwcsOhY3RpY2FtZW50ZSBhIGxhIG1pdGFkLg0KDQpQb3Igb3RybyBsYWRvLCBvdHJvIGFzcGVjdG8gYSBkZXN0YWNhciBlcyBsYSBkaXNwZXJzacOzbiBkZSBlc3RhIHZhcmlhYmxlIGEgbG8gbGFyZ28gZGUgbG9zIGHDsW9zLiBDdXJpb3NhbWVudGUsIGVzdGEgZGlzcGVyc2nDs24gZXMgbWVub3IgcGFyYSBsYXMgcmVnaW9uZXMgY3V5YSBwcmVzacOzbiBmaXNjYWwgZXMgbXV5IGFsdGEgbyBtdXkgYmFqYS4gWSBlcyBtYXlvciBwYXJhIGxhcyByZWdpb25lcyBjdXlvIG5pdmVsIG1lZGlvIHNlIGVuY3VlbnRyYSBlbnRyZSBhbWJvcyBleHRyZW1vcy4NCg0KVGVybWluYW5kbyBjb24gZXN0YSBzZWNjacOzbiwgbGEgcHJpbmNpcGFsIGNvbmNsdXNpw7NuIG9idGVuaWRhIGVzIGxhIGltcG9ydGFudGUgcmVsYWNpw7NuIHF1ZSBleGlzdGUgZW50cmUgaW5ncmVzb3MgcMO6YmxpY29zIHkgcmlxdWV6YS4gUHVlc3RvIHF1ZSBwb2RlbW9zIG9ic2VydmFyLCBzb24gbGFzIHJlZ2lvbmVzIG3DoXMgcmljYXMgbGFzIHF1ZSBvYnRpZW5lbiBtYXlvcmVzIGluZ3Jlc29zIHDDumJsaWNvcy4gTWllbnRyYXMgcXVlIGVuIGxhIG90cmEgY2FyYSBkZSBsYSBtb25lZGEsIGFxdWVsbGFzIHJlZ2lvbmVzIG3DoXMgcG9icmVzIHNvbiBsYXMgcXVlIHByZXNlbnRhbiB1biBtZW5vciBuaXZlbC4NCg0KIyMjIyAqKlRhYmxhKioNCg0KYGBge3J9DQptZWRpYV9yZWdpb25lcyAlPiUgI2d0VGFibGUNCiAgc2VsZWN0KHJlZ2lvbiwgeWVhciwgbWVkaWFfZ2FzdG8pICU+JQ0KICBmaWx0ZXIoIXllYXIgJWluJSBjKDIwMTksIE5BKSkgJT4lIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gInJlZ2lvbiIsIHZhbHVlc19mcm9tID0gIm1lZGlhX2dhc3RvIikgJT4lDQogIGd0KHJvd25hbWVfY29sID0gInllYXIiKSAlPiUgDQogIHRhYl9oZWFkZXIodGl0bGUgPSBtZCgiR2FzdG8gcMO6YmxpY28gcG9yIHJlZ2lvbmVzIiksDQogICAgICAgICAgICAgc3VidGl0bGUgPSBtZCgiRGUgMTk5MyBhIDIwMTgiKSkgJT4lIA0KICB0YWJfb3B0aW9ucyhoZWFkaW5nLmJhY2tncm91bmQuY29sb3IgPSAic2llbm5hIikgJT4lDQogIHRhYl9vcHRpb25zKGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMjUsDQogICAgICAgICAgICAgIGhlYWRpbmcuc3VidGl0bGUuZm9udC5zaXplID0gMjAsDQogICAgICAgICAgICAgIGNvbHVtbl9sYWJlbHMuZm9udC53ZWlnaHQgPSAgImJvbGQiLA0KICAgICAgICAgICAgICBoZWFkaW5nLmFsaWduID0gImNlbnRlciIpICU+JSANCiAgdGFiX29wdGlvbnModGFibGUuYWxpZ24gPSAiY2VudGVyIikgJT4lIA0KICBjb2xzX2FsaWduKGFsaWduID0gImNlbnRlciIpICU+JSANCiAgY29sc19sYWJlbChgRWFzdCBBc2lhICYgUGFjaWZpY2AgPSAiQXNpYSBkZWwgRXN0ZSAmIFBhY8OtZmljbyIsDQogICAgICAgICAgICAgYEV1cm9wZSAmIENlbnRyYWwgQXNpYWAgPSAiRXVyb3BhICYgQXNpYSBDZW50cmFsIiwgDQogICAgICAgICAgICAgYExhdGluIEFtZXJpY2EgJiBDYXJpYmJlYW5gID0gIkxhdGlubyBBbcOpcmljYSAmIENhcmliZSIsDQogICAgICAgICAgICAgYE1pZGRsZSBFYXN0ICYgTm9ydGggQWZyaWNhYCA9IA0KICAgICAgICAgICAgICAgIk9yaWVudGUgTWVkaW8gJiBOb3J0ZSBkZSBBZnJpY2EiLCANCiAgICAgICAgICAgICBgTm9ydGggQW1lcmljYWAgPSAiQW3DqXJpY2EgZGVsIE5vcnRlIiwgDQogICAgICAgICAgICAgYFNvdXRoIEFzaWFgID0gIlN1ciBkZSBBc2lhIiwgDQogICAgICAgICAgICAgYFN1Yi1TYWhhcmFuIEFmcmljYWAgPSAiw4FmcmljYSBTdWItU2FoYXJpYW5hIikgJT4lIA0KICBmbXRfcGVyY2VudChjb2x1bW5zPSAyOjgsIA0KICAgICAgICAgICAgIGRlY2ltYWxzID0gMikNCmBgYA0KDQojIyMgNC4xLjQgTsO6bWVybyBtZWRpbyBkZSBtaWxpdGFyZXMgey50YWJzZXR9DQoNClBhcmEgdGVybWluYXIgY29uIGVsIGFuw6FsaXNpcyBwb3IgcmVnaW9uZXMsIG5vcyBmaWphcmVtb3MgZW4gbGEgZGltZW5zacOzbiBkZSBsb3MgZWrDqXJjaXRvcyBxdWUgY29uZm9ybWFuIGxvcyBkaWZlcmVudGVzIHBhw61zZXMgZGUgY2FkYSByZWdpw7NuLiBQYXJhIGVsbG8sIG9idGVuZHJlbW9zIGVsIG7Dum1lcm8gdG90YWwgZGUgbWlsaXRhcmVzIGRlIGNhZGEgcmVnacOzbiB5IGxvIHJlcHJlc2VudGFyZW1vcyBlbiBlbCBtYXBhIHF1ZSBzZSBtdWVzdHJhIGEgY29udGludWFjacOzbi4NCg0KIyMjIyAqKkdyw6FmaWNvKioNCg0KYGBge3J9DQptZWRpYV9yZWdpb25lcyA8LSBwYWlzZXMgJT4lIA0KICBzZWxlY3QocmVnaW9uLCBjb3VudHJ5X25hbWUsIHRvdGFsX21pbGl0YXJ5KSAlPiUgDQogIGdyb3VwX2J5KHJlZ2lvbiwgY291bnRyeV9uYW1lKSAlPiUgDQogIHN1bW1hcmlzZShtZWRpYV9taWxpdGFyID0gbWVhbih0b3RhbF9taWxpdGFyeSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgZ3JvdXBfYnkocmVnaW9uKSAlPiUgIA0KICBtdXRhdGUobWVkaWFfbWlsaXRhciA9IG1lYW4obWVkaWFfbWlsaXRhciwgbmEucm0gPSBUUlVFKSkgJT4lDQogIG11dGF0ZShpc28yID0gY291bnRyeWNvZGU6OmNvdW50cnljb2RlKA0KICAgIHNvdXJjZXZhciA9IGNvdW50cnlfbmFtZSwgb3JpZ2luID0gImNvdW50cnkubmFtZSIsDQogICAgZGVzdGluYXRpb24gPSAgImlzbzJjIiwgd2FybiA9IEZBTFNFKSwgLmFmdGVyID0gY291bnRyeV9uYW1lKSANCg0KbWFwYV9tdW5kbyA8LSBtYXBfZGF0YSgid29ybGQiKSAlPiUNCiAgbXV0YXRlKGlzbzIgPSBjb3VudHJ5Y29kZTo6Y291bnRyeWNvZGUoDQogICAgc291cmNldmFyID0gcmVnaW9uLCBvcmlnaW4gPSAiY291bnRyeS5uYW1lIiwNCiAgICBkZXN0aW5hdGlvbiA9ICAiaXNvMmMiLCB3YXJuID0gRkFMU0UpLCAuYWZ0ZXIgPSByZWdpb24pIA0KDQpwYWlzZXNfbWFwYSA8LSBmdWxsX2pvaW4obWFwYV9tdW5kbywgbWVkaWFfcmVnaW9uZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGJ5PSBjKCJpc28yIj0iaXNvMiIpKQ0KDQphIDwtIHBhaXNlc19tYXBhICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21fcG9seWdvbihhZXMoIHg9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgIGZpbGwgPSByZWdpb24ueSksIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKHRpdGxlID0gIk7Dum1lcm8gdG90YWwgZGUgbWlsaXRhcmVzIHBvciByZWdpw7NuIiwNCiAgICBmaWxsID0gIlJlZ2lvbmVzIikgKw0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKGJyZWFrcyA9IGMoIkVhc3QgQXNpYSAmIFBhY2lmaWMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFdXJvcGUgJiBDZW50cmFsIEFzaWEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMYXRpbiBBbWVyaWNhICYgQ2FyaWJiZWFuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcnRoIEFtZXJpY2EiLCAiU291dGggQXNpYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3ViLVNhaGFyYW4gQWZyaWNhIiksIA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkFzaWEgZGVsIEVzdGVcbiYgUGFjw61maWNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFdXJvcGFcbiYgQXNpYSBDZW50cmFsIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGF0aW5vIEFtw6lyaWNhXG4mIENhcmliZSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9yaWVudGUgTWVkaW9cbiYgTm9ydGUgZGUgQWZyaWNhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbcOpcmljYVxuZGVsIE5vcnRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3VyXG5kZSBBc2lhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDgWZyaWNhXG5TdWItU2FoYXJpYW5hIikpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGZhY2UgPSAiYm9sZCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMC41KSwNCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyPSAiYmxhY2siLCBzaXplPSAxLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZTIiKSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2U9ICJib2xkIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeD0gOTUsIHk9IDYyLCBsYWJlbCA9ICIxMjMuNTUwIiwgc2l6ZT0gNiwNCiAgICAgICAgICAgZm9udGZhY2U9MiwgY29sb3I9ICJicm93biIpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4PSAxODAsIHk9IDEwLCBsYWJlbCA9ICI0MjEuMjYyIiwgc2l6ZT0gNiwNCiAgICAgICAgICAgZm9udGZhY2U9MiwgY29sb3I9ICJyZWQiKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeD0gLTExMCwgeT0gLTEwLCBsYWJlbCA9ICI4MC40NjkiLCBzaXplPSA2LA0KICAgICAgICAgICBmb250ZmFjZT0yLCBjb2xvciA9ICJzZWFncmVlbiIpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4PSA3MiwgeT0gLTUsIGxhYmVsID0gIjUxNi43MzAiLCBzaXplPSA1LA0KICAgICAgICAgICBmb250ZmFjZT0yLCBjb2xvciA9ICJwdXJwbGUiKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeD0gLTQ1LCB5PSAzMCwgbGFiZWwgPSAiMTc4LjQ2OCIsIHNpemU9IDUsDQogICAgICAgICAgIGZvbnRmYWNlPTIsIGNvbG9yID0gInR1cnF1b2lzZTQiKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeD0gLTE3MCwgeT0gNDAsIGxhYmVsID0gIjc5Mi4zMjUiLCBzaXplPSA2LA0KICAgICAgICAgICBmb250ZmFjZT0yLCBjb2xvciA9ICJibHVlIikgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHg9IDIwLCB5PSAtNDAsIGxhYmVsID0gIjM4LjMwMSIsIHNpemU9IDYsDQogICAgICAgICAgIGZvbnRmYWNlPTIsIGNvbG9yID0gIm1hZ2VudGEiKSArDQogIGNvb3JkX2ZpeGVkICh4bGltPSBjKC0yMDAsMjAwKSwNCiAgICAgICAgICAgICAgIHlsaW09IGMoLTU4LDkwKSwNCiAgICAgICAgICAgICAgIHJhdGlvID0gMS4zKSANCg0KYQ0KYGBgDQoNClNpbiBlbWJhcmdvLCBsYSBvYnRlbmNpw7NuIGRlIGVzdGUgZGF0byBub3MgY3JlYSBsYSBkdWRhIGRlIGNvbm9jZXIgbGEgZGltZW5zacOzbiBkZSBsb3MgZWrDqXJjaXRvcyBkZSBjYWRhIHBhw61zLiBQdWVzdG8gcXVlIGFsIGFncmVnYXIgZWwgbsO6bWVybyB0b3RhbCBkZSBtaWxpdGFyZXMgZGUgY2FkYSBwYcOtcyBwb3IgcmVnacOzbiwgcGVyZGVtb3MgbGEgaW5mb3JtYWNpw7NuIHNvYnJlIHF1w6kgcGHDrXNlcyByZWFsaXphbiB1bmEgbWF5b3IgaW52ZXJzacOzbiBlbiBwZXJzb25hbCBtaWxpdGFyIGZyZW50ZSBhbCByZXN0by4gQWRlbcOhcywgcGFyYSBjb25vY2VyIHNpIHVuIHBhw61zIHNlIGVuY3VlbnRyYSBmdWVydGVtZW50ZSBtaWxpdGFyaXphZG8gaGVtb3MgZGUgdGVuZXIgZW4gY3VlbnRhIHN1IHBvYmxhY2nDs24uIFBvciBlbGxvLCBsYSBwcm9wb3JjacOzbiBkZSBtaWxpdGFyZXMgcmVzcGVjdG8gYSBsYSBwb2JsYWNpw7NuIHRvdGFsIG5vcyBheXVkYXLDoSBtw6FzIGFkZWxhbnRlIGEgY29ub2NlciBsYSBkaW1lbnNpw7NuIHJlbGF0aXZhIGRlIGxvcyBlasOpcmNpdG9zLg0KDQojIyMjICoqVGFibGEqKg0KDQpgYGB7cn0NCnBhaXNlcyAlPiUgc2VsZWN0KHJlZ2lvbiwgY291bnRyeV9uYW1lLCB0b3RhbF9taWxpdGFyeSkgJT4lDQogIGdyb3VwX2J5KHJlZ2lvbiwgY291bnRyeV9uYW1lKSAlPiUgDQogIHN1bW1hcmlzZShtZWRpYV9taWxpdGFyID0gbWVhbih0b3RhbF9taWxpdGFyeSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgZ3JvdXBfYnkocmVnaW9uKSAlPiUgIA0KICBzdW1tYXJpc2UobWVkaWFfbWlsaXRhciA9IG1lYW4obWVkaWFfbWlsaXRhciwgbmEucm0gPSBUUlVFKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgbXV0YXRlKHJlZ2lvbiA9IGNhc2Vfd2hlbigNCiAgcmVnaW9uID09ICJFYXN0IEFzaWEgJiBQYWNpZmljIiB+ICJBc2lhIGRlbCBFc3RlICYgUGFjw61maWNvIiwNCiAgcmVnaW9uID09ICJFdXJvcGUgJiBDZW50cmFsIEFzaWEiIH4gIkV1cm9wYSAmIEFzaWEgQ2VudHJhbCIsIA0KICByZWdpb24gPT0gIkxhdGluIEFtZXJpY2EgJiBDYXJpYmJlYW4iIH4gIkxhdGlubyBBbcOpcmljYSAmIENhcmliZSIsIA0KICByZWdpb24gPT0gIk1pZGRsZSBFYXN0ICYgTm9ydGggQWZyaWNhIiB+IA0KICAgICJPcmllbnRlIE1lZGlvICYgTm9ydGUgZGUgQWZyaWNhIiwgDQogIHJlZ2lvbiA9PSAiTm9ydGggQW1lcmljYSIgfiAiQW3DqXJpY2EgZGVsIE5vcnRlIiwgDQogIHJlZ2lvbiA9PSAiU291dGggQXNpYSIgfiAiU3VyIGRlIEFzaWEiLCANCiAgcmVnaW9uID09ICJTdWItU2FoYXJhbiBBZnJpY2EiIH4gIsOBZnJpY2EgU3ViLVNhaGFyaWFuYSIpKSAlPiUgDQogIGd0KHJvd25hbWVfY29sID0gInJlZ2lvbiIpICU+JSANCiAgdGFiX2hlYWRlcih0aXRsZSA9IG1kKCJNZWRpYSBkZSBtaWxpdGFyZXMgcG9yIHJlZ2nDs24iKSwNCiAgICAgICAgICAgICBzdWJ0aXRsZSA9IG1kKCJEZSAxOTkzIGEgMjAxOSIpKSAlPiUgDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICJvcmFuZ2UiKSAlPiUNCiAgdGFiX29wdGlvbnMoaGVhZGluZy50aXRsZS5mb250LnNpemUgPSAyNSwNCiAgICAgICAgICAgICAgaGVhZGluZy5zdWJ0aXRsZS5mb250LnNpemUgPSAyMCwNCiAgICAgICAgICAgICAgY29sdW1uX2xhYmVscy5mb250LndlaWdodCA9ICAiYm9sZCIsDQogICAgICAgICAgICAgIGhlYWRpbmcuYWxpZ24gPSAiY2VudGVyIikgJT4lIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5hbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIGNvbHNfYWxpZ24oYWxpZ24gPSAiY2VudGVyIikgJT4lIA0KICBjb2xzX2xhYmVsKGBtZWRpYV9taWxpdGFyYCA9ICJNZWRpYSBuw7ptZXJvIGRlIG1pbGl0YXJlcyIpICU+JSANCiAgZm10X251bWJlcihjb2x1bW5zPSAyLCANCiAgICAgICAgICAgICBkZWNpbWFscyA9IDAsDQogICAgICAgICAgICAgc2VwX21hcmsgPSAiLiIpDQpgYGANCg0KIyMgNC4yIEFuw6FsaXNpcyBwb3IgcGHDrXNlcw0KDQpBIGxhIGhvcmEgZGUgcmVhbGl6YXIgdW4gYW7DoWxpc2lzIHBvciBwYcOtc2VzIGhlbW9zIGRlIHNlciBjb25zY2llbnRlcyBkZWwgZ3JhbiBuw7ptZXJvIGRlIG9ic2VydmFjaW9uZXMgZGUgbGFzIHF1ZSBkaXNwb25lbW9zLiBFeGlzdGVuIGFscmVkZWRvciBkZSAyMDAgcGHDrXNlcyBlbiBlbCBtdW5kby4gUG9yIGxvIHF1ZSBsYSB2aXN1YWxpemFjacOzbiBkZSBsb3MgZGF0b3MgZGUgY2FkYSB1bm8gZGUgZXN0b3MgcGHDrXNlcyBlbiB1biBtaXNtbyBncsOhZmljbyBzZSBwdWVkZSB0b3JuYXIgdW4gcHJvYmxlbWEgYSBsYSBob3JhIGRlIHJlcHJlc2VudGFybG9zLiBQb3IgZWxsbywgZW4gZXN0YSBzZWNjacOzbiBzZSBtb3N0cmFyYW4gbG9zIGxvcyBwYcOtc2VzIG3DoXMgcmVsZXZhbnRlcyBwYXIgY2FkYSBpbmRpY2Fkb3IgZW4gY3Vlc3Rpw7NuLCBvIGVuIG90cmFzIHBhbGFicmFzLCBub3MgY2VudHJhcmVtb3MgZW4gYXF1ZWxsb3MgcGHDrXNlcyBxdWUgbWVqb3Igbm9zIGF5dWRlbiBhIGVudGVuZGVyIGxhIGluZm9ybWFjacOzbiBkZWwgZGF0YXNldC4NCg0KIyMjIDQuMi4xIE7Dum1lcm8gZGUgbWlsaXRhcmVzIHBvciBwYcOtcw0KDQpDb21lbnphcmVtb3MgZG9uZGUgbG8gZGVqYW1vcyBhbnRlcy4gUGFyYSBjb25vY2VyIHF1w6kgcGHDrXNlcyB0aWVuZW4gdW4gbWF5b3IgbsO6bWVybyBkZSBtaWxpdGFyZXMgcmVzcGVjdG8gYSBzdSBwb2JsYWNpw7NuLCBkaXZpZGltb3MgZWwgbsO6bWVybyB0b3RhbCBkZSBtaWxpdGFyZXMgcGFyYSBjYWRhIHBhw61zIGVuIGNhZGEgYcOxbyB5IGNhbGN1bGFtb3Mgc3UgbWVkaWEuIEVsIHJlc3VsdGFkbyBsbyBwb2RlbW9zIG1vc3RyYXIgZW4gZWwgc2lndWllbnRlIG1hcGEuDQoNCmBgYHtyfQ0KI2N1YXJ0aWxlcyA8LSBkZXNjcihlamVyY2l0byRtaWxpX3BjKQ0KDQplamVyY2l0byA8LSBwYWlzZXMgJT4lIA0KICBzZWxlY3QoY291bnRyeV9uYW1lLCB5ZWFyLCB0b3RhbF9taWxpdGFyeSwgcG9wdWxhdGlvbikgJT4lDQogIGRyb3BfbmEodG90YWxfbWlsaXRhcnksIHBvcHVsYXRpb24pICU+JSANCiAgbXV0YXRlKG1pbGlfcGMgPSB0b3RhbF9taWxpdGFyeS9wb3B1bGF0aW9uKSAlPiUNCiAgZ3JvdXBfYnkoY291bnRyeV9uYW1lKSAlPiUgbXV0YXRlKG1pbGlfcGMgPSBtZWFuKG1pbGlfcGMpKSAlPiUNCiAgbXV0YXRlKG1pbGlfcGMgPSBjYXNlX3doZW4oDQogICAgbWlsaV9wYyA8PSAwLjAwMjUyNzIyNjEgfiAxLA0KICAgIG1pbGlfcGMgPiAwLjAwMjUyNzIyNjEgJiBtaWxpX3BjIDwgMC4wMDQ5MDE3NDQwIH4gMiwgDQogICAgbWlsaV9wYyA+IDAuMDA0OTAxNzQ0MCAmIG1pbGlfcGMgPCAwLjAwODQ3MDc0NTUgfiAzLA0KICAgIG1pbGlfcGMgPj0gMC4wMDg0NzA3NDU1ICB+IDQsDQogICAgaXMubmEobWlsaV9wYykgfiAwKSkgJT4lIA0KICBtdXRhdGUoY291bnRyeV9uYW1lID0gaWZlbHNlKA0KICAgIGNvdW50cnlfbmFtZSA9PSAiU8ODwqNvIFRvbcODwqkgYW5kIFByaW5jaXBlIiwNCiAgICAiU8OjbyBUb23DqSBhbmQgUHJpbmNpcGUiLCBjb3VudHJ5X25hbWUpKSAlPiUgDQogIG11dGF0ZShpc28yID0gY291bnRyeWNvZGU6OmNvdW50cnljb2RlKA0KICAgIHNvdXJjZXZhciA9IGNvdW50cnlfbmFtZSwgb3JpZ2luID0gImNvdW50cnkubmFtZSIsDQogICAgZGVzdGluYXRpb24gPSAgImlzbzJjIiwgd2FybiA9IEZBTFNFKSwgLmFmdGVyID0gY291bnRyeV9uYW1lKSAlPiUNCiAgbXV0YXRlKG1pbGlfcGMgPSBhcy5jaGFyYWN0ZXIobWlsaV9wYykpDQoNCm1hcGFfbXVuZG8gPC0gbWFwX2RhdGEoIndvcmxkIikgJT4lIA0KICBtdXRhdGUoaXNvMiA9IGNvdW50cnljb2RlOjpjb3VudHJ5Y29kZSgNCiAgICBzb3VyY2V2YXIgPSByZWdpb24sIG9yaWdpbiA9ICJjb3VudHJ5Lm5hbWUiLA0KICAgIGRlc3RpbmF0aW9uID0gICJpc28yYyIsIHdhcm4gPSBGQUxTRSksIC5hZnRlciA9IHJlZ2lvbikgDQoNCnBhaXNlc19tYXBhMiA8LSBmdWxsX2pvaW4obWFwYV9tdW5kbywgZWplcmNpdG8sIGJ5PSBjKCJpc28yIj0iaXNvMiIpKQ0KDQpsIDwtIHBhaXNlc19tYXBhMiAlPiUNCiAgZ2dwbG90KCkgKw0KICBnZW9tX3BvbHlnb24oYWVzKCB4PSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gbWlsaV9wYyksDQogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsNCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShicmVha3MgPSBjKDQsIDMsIDIsIDEsIDApLCANCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9IGMoIm4gPiAwLjg0JSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMC40OSUgPCBuIDwgMC44NCUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMC4yNSUgPCBuIDwgMC40OSUiLCAibiA8IDAuMjUlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpbiBkYXRvcyIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUG9yY2VudGFqZSBkZSBtaWxpdGFyZXMgcG9yIHBhw61zIiwNCiAgICBzdWJ0aXRsZSA9ICJNZWRpYSBkZWwgcGVyaW9kbyAxOTkzLTIwMTkiLA0KICAgIGZpbGwgPSAiUG9yY2VudGFqZSBkZSBtaWxpdGFyZXMiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgZmFjZSA9ICJib2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyPSAiYmxhY2siLCBzaXplPSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSJsaWdodGJsdWUyIikpICsNCiAgY29vcmRfZml4ZWQgKHhsaW09IGMoLTIwMCwyMDApLA0KICAgICAgICAgICAgICAgeWxpbT0gYygtNTgsOTApLA0KICAgICAgICAgICAgICAgcmF0aW8gPSAxLjMpIA0KDQpsDQoNCmBgYA0KDQpMb3MgaW50ZXJ2YWxvcyBjYWxjdWxhZG9zIHBhcmEgbGEgcmVwcmVzZW50YWNpw7NuIGRlbCBtYXBhIGhhbiBzaWRvIG9idGVuaWRvcyBkZSBsb3MgY3VhcnRpbGVzIGRlIGxhIHZhcmlhYmxlICptaWxpX3BjKi4gU2luIGVtYmFyZ28sIGVudHJlIGVuIHRlcmNlciBjdWFydGlsIHkgZWwgdmFsb3IgbcOhcyBhbHRvIGV4aXN0ZSB1bmEgZ3JhbiBkaXNwZXJzacOzbi4gUG9yIGVsbG8sIHJlc3VsdGEgaW50ZXJlc2FudGUgY29ub2NlciBjdcOhbCBlcyBlbCBwb3JjZW50YWplIGRlIG1pbGl0YXJlcyBlbiBsb3MgcGHDrXNlcyBtw6FzIG1pbGl0YXJpemFkb3MuDQoNCmBgYHtyfQ0KZWplcmNpdG8yIDwtIHBhaXNlcyAlPiUgDQogIHNlbGVjdChjb3VudHJ5X25hbWUsIHllYXIsIHRvdGFsX21pbGl0YXJ5LCBwb3B1bGF0aW9uKSAlPiUgDQogIGRyb3BfbmEodG90YWxfbWlsaXRhcnksIHBvcHVsYXRpb24pICU+JSANCiAgbXV0YXRlKG1pbGlfcGMgPSB0b3RhbF9taWxpdGFyeS9wb3B1bGF0aW9uKSAlPiUgDQogIGdyb3VwX2J5KGNvdW50cnlfbmFtZSkgJT4lIHN1bW1hcmlzZShtaWxpX3BjID0gbWVhbihtaWxpX3BjKSkgJT4lIA0KICBzbGljZV9tYXgob3JkZXJfYnkgPSBtaWxpX3BjLCBuPSA1KSAlPiUgDQogIG11dGF0ZShjb3VudHJ5X25hbWUgPSBmb3JjYXRzOjphc19mYWN0b3IoY291bnRyeV9uYW1lKSkgJT4lIA0KICBtdXRhdGUoY291bnRyeV9uYW1lID0gZm9yY2F0czo6ZmN0X3Jlb3JkZXIoDQogICAgY291bnRyeV9uYW1lLCBtaWxpX3BjLCAuZGVzYyA9IEZBTFNFKSkNCg0KYSA8LSBnZ3Bsb3QoZWplcmNpdG8yKSArIA0KICBnZW9tX2NvbChhZXMoeD1jb3VudHJ5X25hbWUsIHk9IG1pbGlfcGMpLCBmaWxsID0gInNpZW5uYSIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMC4wNiksIA0KICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDAuMDYsIDAuMDIpLCANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIkJydW5laSIsICJJc3JhZWwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpbmdhcHVyIiwgIkNvcmVhIGRlbCBOb3J0ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXJpdHJlYSIpKSArDQogIGxhYnModGl0bGUgPSAiVG9wIDUgcGHDrXNlcyBjb24gbWF5b3JcbnBvcmNlbnRhamUgZGUgbWlsaXRhcmVzIiwNCiAgICAgICB4PSAiIiwNCiAgICAgICB5PSIiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX2lwc3VtKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KZGQgPC0gZ2dwbG90bHkoYSwgd2lkdGggPSA2MDAsIGhlaWdodCA9IDUyMCkNCg0KaHRtbHRvb2xzOjpkaXYoZGQsIGFsaWduID0gImNlbnRlciIpDQpgYGANCg0KIyMjIDQuMi4yIFRhc2EgZGUgZGVzZW1wbGVvDQoNCk90cm8gZGUgbG9zIGluZGljYWRvcmVzIGRlIGxvcyBxdWUgZGlzcG9uZW1vcyBlcyBkZSBsYSB0YXNhIGRlIGRlc2VtcGxlby4gQSBjb250aW51YWNpw7NuLCB2aXN1YWxpemFyZW1vcyBjdcOhbGVzIHNvbiBsb3MgcGHDrXNlcyBxdWUgZGUgbWVkaWEgaGFuIG1hbnRlbmlkbyB1biBtYXlvciB5IHVuIG1lbm9yIG5pdmVsIGRlIGRlc2VtcGxlbyBhIGxvIGxhcmdvIGRlbCBwZXJpb2RvIGFuYWxpemFkby4NCg0KIyMjIyAgey50YWJzZXR9DQoNCiMjIyMjICoqTWF5b3IgZGVzZW1wbGVvKioNCg0KYGBge3J9DQpkZXNlbXBfbWF4IDwtIHBhaXNlcyAlPiUgZ3JvdXBfYnkoY291bnRyeV9uYW1lKSAlPiUgDQogIG11dGF0ZSh1bmVtcGxveW1lbnRfcmF0ZSA9IHVuZW1wbG95bWVudF9yYXRlLzEwMCkgJT4lIA0KICBzdW1tYXJpc2UoZGVzZW1wID0gbWVhbih1bmVtcGxveW1lbnRfcmF0ZSkpICU+JSBkcm9wX25hKCkgJT4lIA0KICBzbGljZV9tYXgob3JkZXJfYnkgPSBkZXNlbXAsIG49IDUpDQoNCmRlc2VtcF9tYXggJT4lICNndFRhYmxlDQogIG11dGF0ZShjb3VudHJ5X25hbWUgPSBjYXNlX3doZW4oDQogICAgY291bnRyeV9uYW1lID09ICJOb3J0aCBNYWNlZG9uaWEiIH4gIk1hY2Vkb25pYSBkZWwgTm9ydGUiLA0KICAgIGNvdW50cnlfbmFtZSA9PSAiTGVzb3RobyIgfiAiTGVzb3RvIiwNCiAgICBjb3VudHJ5X25hbWUgPT0gIlNvdXRoIEFmcmljYSIgfiAiU3Vkw6FmcmljYSIsDQogICAgY291bnRyeV9uYW1lID09ICJCb3NuaWEgYW5kIEhlcnplZ292aW5hIiB+IA0KICAgICAgIkJvc25pYSAmIEhlcnplZ292aW5hIiwNCiAgICBjb3VudHJ5X25hbWUgPT0gIkVzd2F0aW5pIiB+ICJTdWF6aWxhbmRpYSIpKSAlPiUgDQogIGd0KHJvd25hbWVfY29sID0gImNvdW50cnlfbmFtZSIpICU+JSANCiAgdGFiX2hlYWRlcih0aXRsZSA9IG1kKCJUb3AgNSBtYXlvciB0YXNhIGRlIGRlc2VtcGxlbyIpLA0KICAgICAgICAgICAgIHN1YnRpdGxlID0gbWQoIkRlIDE5OTMgYSAyMDE5IikpICU+JSANCiAgdGFiX29wdGlvbnMoaGVhZGluZy5iYWNrZ3JvdW5kLmNvbG9yID0gInRhbjIiKSAlPiUgDQogIHRhYl9vcHRpb25zKGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMjUsIA0KICAgICAgICAgICAgICBoZWFkaW5nLnN1YnRpdGxlLmZvbnQuc2l6ZSA9IDIwLCAgDQogICAgICAgICAgICAgIGNvbHVtbl9sYWJlbHMuZm9udC53ZWlnaHQgPSAgImJvbGQiLCANCiAgICAgICAgICAgICAgaGVhZGluZy5hbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIHRhYl9vcHRpb25zKHRhYmxlLmFsaWduID0gImNlbnRlciIpICU+JSANCiAgY29sc19hbGlnbihhbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIGNvbHNfbGFiZWwoZGVzZW1wID0gIkRlc2VtcGxlbyBtZWRpbyIpICU+JSANCiAgZm10X3BlcmNlbnQoY29sdW1ucz0gMiwgDQogICAgICAgICAgICAgZGVjaW1hbHMgPSAyLA0KICAgICAgICAgICAgIGRlY19tYXJrID0gIiwiKQ0KYGBgDQoNCiMjIyMjICoqTWVub3IgZGVzZW1wbGVvKioNCg0KYGBge3J9DQpkZXNlbXBfbWluIDwtIHBhaXNlcyAlPiUgZ3JvdXBfYnkoY291bnRyeV9uYW1lKSAlPiUgDQogIG11dGF0ZSh1bmVtcGxveW1lbnRfcmF0ZSA9IHVuZW1wbG95bWVudF9yYXRlLzEwMCkgJT4lIA0KICBzdW1tYXJpc2UoZGVzZW1wID0gbWVhbih1bmVtcGxveW1lbnRfcmF0ZSkpICU+JSBkcm9wX25hKCkgJT4lIA0KICBzbGljZV9taW4ob3JkZXJfYnkgPSBkZXNlbXAsIG49IDUpIA0KDQpkZXNlbXBfbWluICU+JSAjZ3RUYWJsZQ0KICBtdXRhdGUoY291bnRyeV9uYW1lID0gaWZlbHNlKA0KICAgIGNvdW50cnlfbmFtZSA9PSAiQ2FtYm9kaWEiLCAiQ2FtYm95YSIsIGNvdW50cnlfbmFtZSkpICU+JQ0KICBndChyb3duYW1lX2NvbCA9ICJjb3VudHJ5X25hbWUiKSAlPiUgDQogIHRhYl9oZWFkZXIodGl0bGUgPSBtZCgiVG9wIDUgbWVub3IgdGFzYSBkZSBkZXNlbXBsZW8iKSwNCiAgICAgICAgICAgICBzdWJ0aXRsZSA9IG1kKCJEZSAxOTkzIGEgMjAxOSIpKSAlPiUgDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICJ0YW4yIikgJT4lIA0KICB0YWJfb3B0aW9ucyhoZWFkaW5nLnRpdGxlLmZvbnQuc2l6ZSA9IDI1LCANCiAgICAgICAgICAgICAgaGVhZGluZy5zdWJ0aXRsZS5mb250LnNpemUgPSAyMCwgIA0KICAgICAgICAgICAgICBjb2x1bW5fbGFiZWxzLmZvbnQud2VpZ2h0ID0gICJib2xkIiwgDQogICAgICAgICAgICAgIGhlYWRpbmcuYWxpZ24gPSAiY2VudGVyIikgJT4lIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5hbGlnbiA9ICJjZW50ZXIiKSAlPiUgDQogIGNvbHNfYWxpZ24oYWxpZ24gPSAiY2VudGVyIikgJT4lIA0KICBjb2xzX2xhYmVsKGRlc2VtcCA9ICJEZXNlbXBsZW8gbWVkaW8iKSAlPiUgDQogIGZtdF9wZXJjZW50KGNvbHVtbnM9IDIsIA0KICAgICAgICAgICAgICBkZWNpbWFscyA9IDIsDQogICAgICAgICAgICAgIGRlY19tYXJrID0gIiwiKQ0KYGBgDQoNCiMjIyMgDQoNCkNvbW8gcG9kZW1vcyBvYnNlcnZhciwgZXhpc3RlIHVuYSBncmFuIGRpZmVyZW5jaWEgZW50cmUgbG9zIHBhw61zZXMgY29uIG1heW9yIHkgbWVub3IgZGVzZW1wbGVvLiBDYWJlIHByZWd1bnRhcm5vcyBjb21vIGhhIGV2b2x1Y2lvbmFkbyBlc3RlIGluZGljYWRvciBhIGxvIGxhcmdvIGRlbCBwZXJpb2RvIHBhcmEgY2FkYSBncnVwbyBkZSBwYcOtc2VzLg0KDQpgYGB7cn0NCmIgPC0gcGFpc2VzICU+JSANCiAgc2VsZWN0KGNvdW50cnlfbmFtZSwgeWVhciwgdW5lbXBsb3ltZW50X3JhdGUpICU+JSAgDQogIG11dGF0ZShjb3VudHJ5X25hbWUgPSBjYXNlX3doZW4oDQogICAgY291bnRyeV9uYW1lID09ICJOb3J0aCBNYWNlZG9uaWEiIH4gIk1hY2Vkb25pYSBkZWwgTm9ydGUiLA0KICAgIGNvdW50cnlfbmFtZSA9PSAiTGVzb3RobyIgfiAiTGVzb3RvIiwNCiAgICBjb3VudHJ5X25hbWUgPT0gIlNvdXRoIEFmcmljYSIgfiAiU3Vkw6FmcmljYSIsDQogICAgY291bnRyeV9uYW1lID09ICJCb3NuaWEgYW5kIEhlcnplZ292aW5hIiB+IA0KICAgICAgIkJvc25pYSAmIEhlcnplZ292aW5hIiwNCiAgICBjb3VudHJ5X25hbWUgPT0gIkVzd2F0aW5pIiB+ICJTdWF6aWxhbmRpYSIsDQogICAgY291bnRyeV9uYW1lID09ICJDYW1ib2RpYSIgfiAiQ2FtYm95YSIsDQogICAgVFJVRSB+IGNvdW50cnlfbmFtZSkpICU+JSANCiAgZmlsdGVyKGNvdW50cnlfbmFtZSAlaW4lIGMoIk15YW5tYXIiLCAiQ2FtYm95YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSd2FuZGEiLCAiQmFocmFpbiIsICJRYXRhciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNYWNlZG9uaWEgZGVsIE5vcnRlIiwgIkxlc290byIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdWTDoWZyaWNhIiwgIkJvc25pYSAmIEhlcnplZ292aW5hIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlN1YXppbGFuZGlhIikpICU+JSANCiAgbXV0YXRlKHVuZW1wbG95bWVudF9yYXRlID0gdW5lbXBsb3ltZW50X3JhdGUvMTAwKSAlPiUgDQogIGdncGxvdChhZXMoeD0geWVhciwgeT0gdW5lbXBsb3ltZW50X3JhdGUsIGNvbG9yPSBjb3VudHJ5X25hbWUpKSArDQogIGdlb21fbGluZShzaXplID0gMS4yKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDAuNCksDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsNCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiQmFocmFpbiIsICJCb3NuaWFcbiYgSGVyemVnb3ZpbmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDYW1ib3lhIiwgIkxlc290byIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNYWNlZG9uaWFcbmRlbCBOb3J0ZSIsICJNeWFubWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUWF0YXIiLCAiUndhbmRhIiwgIlN1YXppbGFuZGlhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3Vkw6FmcmljYSIpKSArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsNCiAgbGFicyh0aXRsZSA9ICJFdm9sdWNpw7NuIGRlbCBUT1AgNVxubWF5b3IgeSBtZW5vciB0YXNhIGRlIGRlc2VtcGxlbyIsDQogICAgICAgeCA9ICJUYXNhIGRlIGRlc2VtcGxlbyIsDQogICAgICAgeSA9ICJBw7FvIiwNCiAgICAgICBjb2xvciA9ICJQYcOtc2VzIikgKw0KICB0aGVtZV9pcHN1bSgpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKQ0KDQpwcCA8LSBnZ3Bsb3RseShiLCB3aWR0aCA9IDYwMCwgaGVpZ2h0ID0gNTAwKQ0KDQpodG1sdG9vbHM6OmRpdihwcCwgYWxpZ24gPSAiY2VudGVyIiApDQpgYGANCg0KQ29tbyBwb2TDrWFtb3MgaW1hZ2luYXIsIGxvcyBwYcOtc2VzIGNvbiBiYWphcyB0YXNhcyBkZSBkZXNlbXBsZW8gaGFuIG1hdGVuaWRvIGNvbnN0YW50ZSBlc3RlIGluZGljYWRvciBhIGxvIGxhcmdvIGRlbCBwZXJpb2RvLCBtaWVudHJhcyBxdWUgbG9zIHBhw61zZXMgY29uIHVuIGRlc2VtcGxlbyBtYXlvciBwcmVzZW50YW4gdW5hIG1heW9yIHZhcmlhYmlsaWRhZCBlbiBlc3RlIGluZGljYWRvci4NCg0KIyMjIDQuMi4zIEtpbG9ncmFtb3MgZGUgcGVzY2Egc2Vnw7puIGxhIHBvYmxhY2nDs24NCg0KRGl2ZXJzYXMgY2F1c2FzIG8gbW90aXZvcyBwdWVkZW4gZXN0YXIgZGV0csOhcyBkZSBsYSBwaXJhdGVyw61hLiBVbiBpbmRpY2Fkb3IgcXVlIG5vcyBwdWVkZSBheXVkYXIgYSBlbnRlbmRlciBlc3RlIHRpcG8gZGUgYXRhcXVlcyBlbiBsYXMgY29zdGFzIGRlIHVuIHBhw61zIGVzIGxhIGNhbnRpZGFkIGRlIHBlc2NhIHBlciBjw6FwaXRhIGRlIHVuIHBhw61zLiBFc3RlIGluZGljYWRvciBub3MgbXVlc3RyYSBjdcOhbCBlcyBsYSBpbXBvcnRhbmNpYSBxdWUgdGllbmUgZXN0YSBhY3RpdmlkYWQgcGFyYSBsb3MgcGHDrXNlcy4gVW5hIGZvcm1hIHZpc3VhbCBkZSBtb3N0cmFyIGVzdG9zIGRhdG9zIGVzIGEgdHJhdsOpcyBkZSB1biBncsOhZmljbyAid29yZGNsb3VkIi4NCg0KYGBge3IsIG91dC53aWR0aCA9ICIxMDAlIn0NCmxpYnJhcnkod29yZGNsb3VkMikNCg0KcGVzY2EgPC0gcGFpc2VzICU+JSANCiAgbXV0YXRlKGZpc2ggPSB0b3RhbF9maXNoZXJpZXNfcGVyX3RvbioxMDAwL3BvcHVsYXRpb24pICU+JSANCiAgZ3JvdXBfYnkoY291bnRyeV9uYW1lKSAlPiUgDQogIHN1bW1hcmlzZShmaXNoX3BjID0gbWVhbihmaXNoLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIG11dGF0ZShmaXNoX3BjID0gcm91bmQoZmlzaF9wYywgZGlnaXRzID0gMikpICU+JSANCiAgbXV0YXRlKGNvdW50cnlfbmFtZSA9IGNhc2Vfd2hlbigNCiAgICBjb3VudHJ5X25hbWUgPT0gIkdyZWVubGFuZCIgfiAiR3JvZW5sYW5kaWEiLA0KICAgIGNvdW50cnlfbmFtZSA9PSAiSWNlbGFuZCIgfiAiSXNsYW5kaWEiLA0KICAgIGNvdW50cnlfbmFtZSA9PSAiTWFyc2hhbGwgSXNsYW5kcyIgfiAiSXNsYXMgTWFyc2hhbGwiLA0KICAgIGNvdW50cnlfbmFtZSA9PSAiTWFsZGl2ZXMiIH4gIk1hbGRpdmFzIiwNCiAgICBjb3VudHJ5X25hbWUgPT0gIkZhcm9lIElzbGFuZHMiIH4gIklzbGFzIEZhcm9lIiwNCiAgICBjb3VudHJ5X25hbWUgPT0gIlN0LiBWaW5jZW50IGFuZCB0aGUgR3JlbmFkaW5lcyIgfiANCiAgICAgICJTYW4gVmljZW50ZSB5IGxhcyBHcmFuYWRpbmFzIiwgDQogICAgY291bnRyeV9uYW1lID09ICJOb3J3YXkiIH4gIk5vcnVlZ2EiLA0KICAgIFRSVUUgfiBjb3VudHJ5X25hbWUpKSAlPiUgDQogIHNsaWNlX21heChvcmRlcl9ieSA9IGZpc2hfcGMsIG49MjAwKQ0KDQp3b3JkY2xvdWQyKHBlc2NhLCBzaGFwZT0gImRpYW1vbmQiLCBzaXplID0gMC44KQ0KYGBgDQoNCkNsYXJhbWVudGUsIG9ic2VydmFtb3MgcXVlIGxhcyBJc2xhcyBGZXJvZSwgSXNsYW5kaWEgeSBHcm9lbmxhbmRpYSBzb24gbG9zIHBhw61zZXMgZW4gbG9zIHF1ZSBtw6FzIGtpbG9ncmFtb3MgcG9yIGhhYml0YW50ZSBzZSBwZXNjYSwgc2VndWlkb3MgZGUgbGVqb3MgcG9yIG90cm9zIHBhw61zZXMgY29tbyBOb3J1ZWdhLCBsYXMgSXNsYXMgTWFyc2hhbGwgbyBsYXMgU2V5Y2hlbGxlcy4gTm8gb2JzdGFudGUsIGxsYW1hIGxhIGF0ZW5jacOzbiBxdWUgbG9zIHRyZXMgcHJpbmNpcGFsZXMgdGVycml0b3JlcyBlbiBsb3MgY3XDoWxlcyBsYSBwZXNjYSBlcyB1bmEgZGUgbGFzIHByaW5jaXBhbGVzIGFjdGl2aWRhZGVzIHNlYW4gZG9zIHRlcnJpdG9yaW9zIGF1dMOzbm9tb3MgZGVsIFJlaW5vIGRlIERpbmFtYXJjYSAoTGFzIElzbGFzIEZlcm9lIHkgR3JvZW5sYW5kaWEpIHkgdW4gcGHDrXMgY29uIHVuIHBhc2FkbyB2aW5jdWxhZG8gYSBlc3RlIHJlaW5vLCBjb21vIGVzIElzbGFuZGlhLg0KDQojIyMgNC4yLjQgUElCIHBlciBjYXBpdGENCg0KUGFyYSB0ZXJtaW5hciBjb24gZXN0YSBzZWNjacOzbiwgcHJlc3RhcmVtb3MgZXNwZWNpYWwgYXRlbmNpw7NuIGFsIFBJQiBwZXIgY8OhcGl0YSB5IGFsIFBJQiBpbmR1c3RyaWFsIHBlciBjw6FwaXRhLiBDb21vIGJpZW4gc2FiZW1vcywgZWwgUElCIHBlciBjw6FwaXRhIGVzIHVubyBkZSBsb3MgaW5kaWNhZG9yZXMgbcOhcyB1c2Fkb3MgcGFyYSBtZWRpciBsYSByaXF1ZXphIGRlIHVuIHBhw61zLiBFc3RlIG1pZGUgbGEgcHJvZHVjY2nDs24gZGUgdW4gcGHDrXMgcG9yIGNhZGEgaGFiaXRhbnRlLiBEZSBlc3RhIGZvcm1hLCBlcyBwb3NpYmxlIHJlYWxpemFyIGNvbXBhcmFjaW9uZXMgZW50cmUgcGHDrXNlcyBkZSBkaXN0aW50YSBkaW1lbnNpw7NuIHkgcG9ibGFjacOzbi4gUG9yIG90cmEgcGFydGUsIGVsIFBJQiBpbmR1c3RyaWFsIG5vcyBpbmRpY2EgYSBxdcOpIHBvcmNlbnRhamUgZGVsIFBJQiBjb250cmlidXllIGxhIGluZHVzdHJpYSBkZSB1biBwYcOtcy4gUmVzdWx0YSBpbnRlcmVzYW50ZSBjb25vY2VyIGN1w6FsIGVzIGxhIHJlbGFjacOzbiBlbnRyZSBhbWJhcyB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KZ2RwX3BjIDwtIHBhaXNlcyAlPiUgZ3JvdXBfYnkoY291bnRyeV9uYW1lKSAlPiUgDQogIG11dGF0ZShpbmRfcGMgPSBpbmR1c3RyeW9mZ2RwKkdEUCkgJT4lIA0KICBzZWxlY3QoY291bnRyeV9uYW1lLCB5ZWFyLCByZWdpb24sIEdEUCwgaW5kX3BjKSAlPiUgIA0KICBkcm9wX25hKGluZF9wYykgIA0KDQpnZHBfcGMgJT4lIGdncGxvdChhZXMoeD0gR0RQLCB5PSBpbmRfcGMpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAic2FsbW9uMiIsIHNpemUgPSAyKSArDQogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGxhYmVscyA9IGMoIkFzaWEgZGVsIEVzdGVcbiYgUGFjw61maWNvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXVyb3BhXG4mIEFzaWEgQ2VudHJhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhdGlubyBBbcOpcmljYVxuJiBDYXJpYmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPcmllbnRlIE1lZGlvXG4mIE5vcnRlIGRlIEFmcmljYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFtw6lyaWNhXG5kZWwgTm9ydGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdXJcbmRlIEFzaWEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDgWZyaWNhXG5TdWItU2FoYXJpYW5hIikpICsgDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRyYW5zaXRpb25fc3RhdGVzKHllYXIpICsNCiAgbGFicyh0aXRsZSA9ICJFdm9sdWNpw7NuIGRlbCBQSUIgaW5kdXN0cmlhbCBwZXIgY2FwaXRhDQplbiBmdW5jacOzbiBkZWwgUElCIHBlciBjYXBpdGFcbiBZZWFyIDoge2Nsb3Nlc3Rfc3RhdGV9IiwgDQogICAgICAgeSA9ICJQSUIgaW5kdXN0cmlhbCBwZXIgY2FwaXRhIiwNCiAgICAgICB4ID0gIlBJQiBwZXIgY2FwaXRhIiwNCiAgICAgICBjb2xvciA9ICJSZWdpb25lcyIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGhqdXN0ID0gMC41LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksDQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSkpDQpgYGANCg0KQSBtZWRpZGEgcXVlIGF1bWVudGEgZWwgUElCIHBlciBjw6FwaXRhIGRlIHVuIHBhw61zLCBhdW1lbnRhIGVsIFBJQiBpbmR1c3RyaWFsIHBlciBjw6FwaXRhLiBFc3RhIGNvbmNsdXNpw7NuIHBhcmVjZSBvYnZpYSBpbmNsdXNvIGFudGVzIGRlIHJlYWxpemFyIGVsIGdyw6FmaWNvIGFudGVyaW9yLiBTaW4gZW1iYXJnbywgZGVsIGdyw6FmaWNvIHBvZGVtb3MgZXh0cmFlciB1bmEgaWRlYSBiYXN0YW50ZSBpbnRlcmVzYW50ZS4gQ29uZm9ybWUgYXVtZW50YSBlbCBQSUIgcGVyIGPDoXBpdGEsIGFkZW1hcyBkZSBhdW1lbnRhciBlbCBQSUIgcGVyIGPDoXBpdGEgaW5kdXN0cmlhbCwgdGFtYmnDqW4gbG8gaGFjZSBsYSB2YXJpYW56YSBlbnRyZSBhbWJhcyB2YXJpYWJsZXMuIEVzdGUgaGVjaG8gbm9zIGluZGljYSBxdWUsIGF1bnF1ZSBlcyBjaWVydG8gcXVlIGVsIGRlc2Fycm9sbG8gaW5kdXN0cmlhbCBlcyB1biBwb3RlbnRlIG1vdG9yIHBhcmEgZWwgY3JlY2ltaWVudG8sIG5vIGVzIGVsIMO6bmljby4gRXN0byBzZSBkZWJlIGEgcXVlIGNvbmZvcm1lIHVuIHBhw61zIGF1bWVudGEgc3UgcmlxdWV6YSBvdHJvcyBzZWN0b3JlcyBjb21pZW56YW4gYSBnYW5hciB1biBtYXlvciBwZXNvLCBjb21vIGVzIGVsIGNhc28gZGVsIHNlY3RvciBzZXJ2aWNpb3MuIEFzw60sIG5vIGVzIGRlIGV4dHJhw7FhciBxdWUgZW50cmUgbG9zIHBhw61zZXMgbcOhcyByaWNvcyBlbmNvbnRyZW1vcyBtYXlvcmVzIGRpZmVyZW5jaWFzIGVuIGN1YW50byBhIGxhIGNvbnRyaWJ1Y2nDs24gcXVlIHJlYWxpemEgc3UgaW5kdXN0cmlhIGEgbGEgcmlxdWV6YSBkZWwgcGHDrXMuDQoNCiMgNS4gQ29uY2x1c2lvbmVzDQoNCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoIkhtaXNjIikNCmxpYnJhcnkoY29ycnBsb3QpDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQpjb3VudHJ5X2NvZGVzIDwtIHJlYWRfY3N2KCJkYXRvcy9jb3VudHJ5X2NvZGVzLmNzdiIpDQoNCmNvdW50cnlfaW5kaWNhdG9ycyA8LSByZWFkX2NzdigiZGF0b3MvY291bnRyeV9pbmRpY2F0b3JzLmNzdiIpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHJlYWRfY3N2KCJkYXRvcy9waXJhdGVfYXR0YWNrcy5jc3YiKQ0KDQpjb3VudHJ5X2RhdGEgPC0gZnVsbF9qb2luKGNvdW50cnlfY29kZXMsIGNvdW50cnlfaW5kaWNhdG9ycywgYnkgPSBjKCJjb3VudHJ5IiA9ICJjb3VudHJ5IikpDQoNCmNvdW50cnlfZGF0YSA8LSBjb3VudHJ5X2RhdGEgfD4gbXV0YXRlKHllYXIgPSBhcy5jaGFyYWN0ZXIoeWVhcikpDQoNCnBpcmF0ZV9hdHRhY2tzIDwtIHBpcmF0ZV9hdHRhY2tzIHw+IHNlcGFyYXRlKGRhdGUsIGMoInllYXIiLCAibW9udGgiLCAiZGF5IiksICItIiApIHw+ICBtdXRhdGUoYXR0YWNrX3R5cGUgPSBpZl9lbHNlKGF0dGFja190eXBlID09ICJCb2FyZGluZyIgLCAiQm9hcmRlZCIsIGF0dGFja190eXBlKSkgfD4gZHBseXI6OnNlbGVjdCgtYyg0LCA4LCAxMjoxNiwgMTgpKQ0KDQpwaXJhdGVfYXR0YWNrcyA8LSBwaXJhdGVfYXR0YWNrcyB8PiBtdXRhdGUoeWVhciA9IGFzLmNoYXJhY3Rlcih5ZWFyKSkNCg0Kcm0oY291bnRyeV9jb2RlcywgY291bnRyeV9pbmRpY2F0b3JzKQ0KDQpmdWxsX2J5X25lYXJlc3QgPC0gZnVsbF9qb2luKHBpcmF0ZV9hdHRhY2tzLCBjb3VudHJ5X2RhdGEsIGJ5ID0gYygibmVhcmVzdF9jb3VudHJ5IiA9ICJjb3VudHJ5IiwgInllYXIiID0gInllYXIiKSl8PiBmaWx0ZXIoIWlzLm5hKGxvbmdpdHVkZSkpIA0KYGBgDQoNCkVuIGVzdGUgY29ycmVsb2dyYW1hIHZlbW9zIGxvcyBjb2VmaWNpZW50ZXMgZGUgY29ycmVsYWNpw7NuIGVudHJlIGxhcyB2YXJpYWJsZXMgZGUgbGFzIHF1ZSBkaXNwb25lbW9zIGRlIGxvcyBwYcOtc2VzLCBtw6FzIHVuYSBudWV2YSB2YXJpYWJsZSBxdWUgZXMgZWwgbsO6bWVybyBkZSBhdGFxdWVzIHBpcmF0YSBvY3Vycmlkb3MgZW4gbGFzIGFndWFzIGRlIGNhZGEgcGHDrXMgZW4gdW4gZGV0ZXJtaW5hZG8gYcOxby4gQ29tbyB2ZW1vcywgYWxndW5hcyByZWxhY2lvbmVzIHNvbiBqdXN0YW1lbnRlIGxhcyBxdWUgcG9kcsOtYW1vcyBlc3BlcmFyOiBsb3MgcGHDrXNlcyBtw6FzIGdyYW5kZXMgc3VlbGVuIHRlbmVyIGVqw6lyY2l0b3MgbcOhcyBncmFuZGVzLCBldGMuIFNpbiBlbWJhcmdvLCBjdWFuZG8gcG9uZW1vcyBlbCBmb2NvIGVuIGxhIHJlbGFjacOzbiBjb24gZWwgbsO6bWVybyBkZSBhdGFxdWVzLCBxdWUgZXMgbG8gcXVlIG3DoXMgaW50ZXJlc2EgZW4gZXN0ZSB0cmFiYWpvLCBlbmNvbnRyYW1vcyByZWxhY2lvbmVzIGTDqWJpbGVzIGRlIGRpZsOtY2lsIGludGVycHJldGFjacOzbi4gQ3JlZW1vcyBxdWUgZXN0YSB2w61hIGRlIGFuw6FsaXNpcyBjYXJlY2UgZGUgbWF5b3IgaW50ZXLDqXMuDQoNCmBgYHtyfQ0KZnVsbF9ieV9uZWFyZXN0IDwtIGZ1bGxfam9pbihwaXJhdGVfYXR0YWNrcywgY291bnRyeV9kYXRhLCBieSA9IGMoIm5lYXJlc3RfY291bnRyeSIgPSAiY291bnRyeSIsICJ5ZWFyIiA9ICJ5ZWFyIikpfD4gZmlsdGVyKCFpcy5uYShsb25naXR1ZGUpKSANCg0KZnVsbF9ieV9uZWFyZXN0IDwtIGZ1bGxfYnlfbmVhcmVzdCB8PiBzZWxlY3QoMSw3LDExOjIxKSB8PiAgZ3JvdXBfYnkobmVhcmVzdF9jb3VudHJ5LCB5ZWFyKSB8PiBtdXRhdGUobmF0dGFja3MgPSBuKCkpIHw+IHVuZ3JvdXAoKSB8PiBkaXN0aW5jdCgpJT4lIHNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkNCg0KY29yIDwtIGNvcihmdWxsX2J5X25lYXJlc3QsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQ0KDQpjb3JycGxvdChjb3IsIHR5cGU9InVwcGVyIiwgb3JkZXI9ImhjbHVzdCIsIGluc2lnID0gImJsYW5rIikNCmBgYA0KDQpQYXJhIGNvbmNsdWlyLCByZWNvbm9jZXJlbW9zIHF1ZSBlc3RlIHRyYWJham8gaGEgc2lkbyBleGl0b3NvIGlkZW50aWZpY2FuZG8gZW4gbG9zIGRhdG9zIGNpZXJ0b3MgcGF0cm9uZXMgZW4gbG9zIGF0YXF1ZXMgcGlyYXRhIHlhIGFwcmVjaWFkb3MgcG9yIGxhIGxpdGVyYXR1cmEsIGNvbW8gbGEgcHJldmFsZW5jaWEgZGUgc2VjdWVzdHJvcyBlbiBsYSBjb3N0YSBkZSDDgWZyaWNhIG8gZWwgbW92aW1pZW50byBkZSBsYXMgem9uYXMgY2FsaWVudGVzIGRlIEFzaWEgYSDDgWZyaWNhLiBObyBoYSBoYWJpZG8gZWwgbWlzbW8gw6l4aXRvIGJ1c2NhbmRvIGNvcnJlbGFjaW9uZXMgY29uIGxhcyB2YXJpYWJsZXMgZGUgbGFzIHF1ZSBkaXNwb25lbW9zIGRlIGxvcyBwYcOtc2VzLCBsbyBjdWFsIG5vIHF1aWVyZSBkZWNpciwgYSBudWVzdHJvIGp1aWNpbywgcXVlIG5vIGV4aXN0YW4gb3RyYXMgbWFuZXJhcyBkZSBlbnJpcXVlY2VyIGVzdGUgYW7DoWxpc2lzLg0KDQojIDYuIEJpYmxpb2dyYWbDrWENCg0KOjo6IHsjcmVmc30NCjo6Og0KDQo8YnI+PGJyPg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Kc2Vzc2lvbmluZm86OnNlc3Npb25faW5mbygpICU+JSBkZXRhaWxzOjpkZXRhaWxzKHN1bW1hcnkgPSAnSW5mb3JtYWNpw7NuIGRlIG1pIFItc2VzacOzbjonKSANCmBgYA0KDQo8YnI+PGJyPg0KDQo6Ojogey50b2NpZnktZXh0ZW5kLXBhZ2UgZGF0YS11bmlxdWU9InRvY2lmeS1leHRlbmQtcGFnZSIgc3R5bGU9ImhlaWdodDogMDsifQ0KOjo6DQo=