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

Para la asignatura de “Programación y manejo de datos en la era del Big Data” he decidido realizar un ensayo sobre como se esta desenvolviendo el sector turístico, tanto a nivel nacional, dada su gran relevancia al ser uno de los principlaes motores de la economía española, como internacional.

Resumen: El sector turístico es uno de los principales moteres económicos de cualquier economía, teniendo este una gran repercusión positiva para la misma. No obstante este sector ha sido uno de los principales perjudicados tras la pandemia de 2020, viviendo durante el periodo de tiempo estudiado en un escenario de incertidumbre caracterizado, por una parte, por por la disminución de sus ingresos desde el inicio de dicho acontecimiento, y por otra, por la imposición de diversas restricciones que han frenado la actividad económica del sector. Y es ahora, momento en el que vivimos un cierto periodo de recuperación económica, cuando nos planteamos en que situación nos encontramos respecto a la situación pre pandemia y como el contexto en el que vivimos puede variar por las nuevas varientes del COVID-19.

Palabras Clave: Turismo, Ingresos, Europa, Motor económico, España, Hoteles, Covid-19, Ómicron, Incertidumbre, Recupración, Crisis.


2. Motivaciones

Podemos entender el turismo como el conjunto de desplazamientos que realizan los individuos, tanto a un nivel nacional como internacional, de forma voluntaria fuera de su residencia habitual. Dentro de dichos desplazamientos, según las preferencias de los propios turistas, estos se pueden decantar por vivir una serie de experiencias u otras, como pueda ser el turismo de sol y playa (predominante en nuestro país) o uno más enfocado a la cultura o gastronomía.

No obstante, sea cual sea la elección final del consumidor, todas estas tienen una repercusión positiva para la economía, ya que estimulan tanto la demanda externa como interna generando en el pais perceptor un incremento en los ingresos, tanto a nivel micro como macro, con sus consecuentes efectos positivos sobre el empleo local, la inversión en todo tipo de infraestructuras y el PIB, entre muchos otros efectos.

En el momento de estar desarrollando este ensayo, el sector turistico a nivel munidal se encuentra en una situación complicada, donde a pesar de la leve recuperación que estabamos viviendo, la nueva variante del Covid-19 (Omicron) a causado un nuevo escenario de incertidumbre que ha provocado la aparición de nuevas restricciones y un incremento en el numero de cancelaciones. Esto lo podemos observar en los tweets siguientes, donde se recoge lo anteriormente comentado



La principal motivación para la redacción de este articulo ha sido:

  • Observar como han evolucionado a lo largo del tiempo el número de turistas que han obtenido las economías europeas, para realizar una comparacion pre y post crisis sanitaria.

  • Analizar como se distribuye parte del sector turístico en España y como han variado los ingresos que este recibe en los últimos años.


3. Datos utilizados

Comentarios

Para poder realizar el trabajo, la obtención de toda la información relevante ha sido adquirida en bases de datos como el INE y Eurostat.

Para poder utilizar estos datos han sido necesario modificarlos antes de adaptarlos a las gráficas deseadas. Este procedimiento lo podemos encontrar dentro del apartado “tidy”, donde podemos observar dichas modificaciones.

Además, el apartado “paquetes” podemos encontrar los paquetes necesarios para la elaboración tanto de empleados para la limpieza de datos, como los utilizados para la realización de los diferentes gráficos.


Tidy


turismo_europa <- read_excel("datos/turismo_europa.xlsx", 
                             col_types = c("text", "numeric", "numeric", "numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", "numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", "numeric", "numeric", "numeric", "numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric", "numeric", 
"numeric", "numeric"))

turismo_europa <- turismo_europa %>% pivot_longer(cols = 2:59, names_to = "date")

#rio::export(turismo_europa, "./datos/turismo_europa.csv")

turismo_europa <- read_csv("datos/turismo_europa.csv", 
                           col_types = cols(date = col_date(format = "%Y/%m")))

turismo_europa$code <- tolower(countrycode(turismo_europa$Country, origin = 'country.name', destination = 'iso2c'))

gasto_turistico_esp <- read_excel("datos/gasto_turistico_esp.xls")

gasto_turistico_esp <- gasto_turistico_esp %>% pivot_longer(cols = 2:53, names_to = "date") %>% 
  drop_na()

#rio::export(gasto_turistico_esp, "./datos/gasto_turistico_esp.csv")

gasto_turistico_esp <- read_csv("datos/gasto_turistico_esp.csv", 
    col_types = cols(date = col_date(format = "%Y/%m")))


gasto_comunidades_autonomas <- read_excel("datos/gasto_comunidades_autonomas.xls")

gasto_comunidades_autonomas <- gasto_comunidades_autonomas %>% pivot_longer(cols = 2:51, names_to = "date") %>% 
  arrange(date)

#rio::export(gasto_comunidades_autonomas, "./datos/gasto_comunidades_autonomas.csv")

gasto_comunidades_autonomas <- read_csv("datos/gasto_comunidades_autonomas.csv", 
    col_types = cols(date = col_date(format = "%Y/%m")))

gasto_tur <- full_join(gasto_comunidades_autonomas, gasto_turistico_esp, by = c("location" = "location", "date" = "date", "value" = "value"))

CCAA <- rio::import("https://github.com/perezp44/archivos_download.2/raw/main/CCAA.rds")

load(here::here("datos", "geometrias_BigData_2021.RData"))

# Para la realización del mapa de España es necesario la descarga de unas geometrías que no han podido ser depositadas en el repositorio por su tamaño superior a 25MB, por ello pongo a vuestra disposición el enlace siguiente el cual nos redirige al paquete de dichas geometrias, https://github.com/rOpenSpain/LAU2boundaries4spain

n_hoteles <- read_excel("datos/n_hoteles.xlsx")

categorias <- read_excel("datos/categorias.xlsx")

Paquetes

  • library(tidyverse)
  • library(readr)
  • library(readxl)
  • library(rio)
  • library(ggplot2)
  • library(plotly)
  • library(treemap)
  • library(DT)
  • library(gt)
  • library(gganimate)
  • library(countrycode)
  • library(ggflags)
  • options(scipen = 999)
  • pacman::p_load(knitr, here, tidyverse, patchwork, ggrepel)
  • pacman::p_load(sf, rnaturalearth, rnaturalearthdata)
  • library(pjpv.datos.01)


4 Estudio del turismo en Europa

Europa es uno de los principales destinos turísticos a nivel mundial, jugando esta actividad un papel importante en todas las economías desarrolladas, pero sobre todo en aquellas menos desarrolladas donde este supone un incremento en la ocupación (sobre todo en perosnas jovenes) teniendo una serie de efectos bilateral que benefician a la economía en general.

Por ello, el Fondo de Desarrollo Regional (FEDER) fomenta la inversión para mejorar la competitividad y sostenibilidad del turismo, beneficiando así a los paises e incentivandolos a innovar y mejorar los servicios ofrecidos.


4.1 Evolución del turismo (2017-2021)

4.1.1 Tendencia del turismo

Tendencia

En primer lugar, podemos observar como ha evolucionado la llegada de turistas a los diferentes paises europeos, haciendo incapie en el computo global que recibe Europa y remarcando la contribución de España en ello.

p1a <- turismo_europa %>% filter(Country %in% c("European_Union"))
p1b <- turismo_europa %>% filter(Country %in% c("Spain"))
p1 <- turismo_europa 

p <- ggplot() +
  geom_line(data = p1, aes(date, value/10^6, colour = Country), alpha = 0.3) +
  geom_line(data = p1a, aes(date, value/10^6), color = "#0288d1", size = 1.2) +
  geom_point(data = p1a, aes(date, value/10^6), color = "#0288d1", size = 1.5) +
  geom_line(data = p1b, aes(date, value/10^6), color = "#b71c1c", size = 1.2) +
  geom_point(data = p1b, aes(date, value/10^6), color = "#b71c1c", size = 1.5) +
  geom_hline(yintercept = 0,
             size = 1,
             colour = "black") +
  scale_x_date(date_labels="%Y-%m",date_breaks  ="3 months")+
  
  annotate("rect",
           xmin = as.Date("2020-03-01"),
           xmax = as.Date("2020-05-01"),
           ymin = -Inf,
           ymax = Inf,
           alpha = 0.4,
           fill = "pink") +
  annotate(geom = "label",
           x= as.Date("2021-10-01"),
           y = 55,
           label = "Europa",
           size = 4,
           color = "#0288d1")  +
  annotate(geom = "label",
           x= as.Date("2021-10-01"),
           y = 15,
           label = "España",
           size = 4,
           color = "#b71c1c")  +
  
  theme(axis.text.x = element_text(angle = 70, hjust = 1)) + 
  theme(plot.title = element_text(family = "serif"),
    panel.background = element_rect(fill = "white"),
    plot.background = element_rect(fill = "white"),
    legend.position = "none") +labs(x = NULL, y = "Turismo", subtitle = "Datos expresados en millones de personas ",
    caption = "Fuente:Elaboración propia con datos del Euroestat.")
  


Como podemos observar en el gráfico, la llegada de turistas presenta una fuerte temporalidad, teniendo su pico más elevado en los meses de julio y agosto. Esto debido al desplazamineto de la población hacia paises como España o Italia que en este época del año se caracterizan por su buen clima y gran oferta de turismo de sol y playa.

Otro dato a destacar es que en la época pre-pandemia el máximo de cada año superaba al del anterior, tendencia que se rompe tras la gran caida que hubo en marzo de 2020, a causa del COVID-19 y las travas que supuso para el desplazamiento de la población ( confinamientos, imposibilidad de viajar…), hecho que a marcado un antes y despues, ya que, además de que la temporalidad se ha incrementado y prolongado en el tiempo, aun no hemos recuperado los niveles previos a la crisis sanitaria, aunque se puede observar como estamos camino a lograrlo ya que el pico de este año supera al predecesor.

Para más detalle de como han evolucionado todas las economías puede consultar la tabla.



Tabla
  
datatable(turismo_europa, class ="stripe hover compact row-border" , filter = 'top')


4.1.2 ¿Que paises reciben un mayor número de turistas?

Julio

Como he mencionado en el apartado anterior, los meses donde hay mayor afluencia de turistas son julio y agosto, por ello en los graficos siguintes vamos a observar que paises recibieron un mayor número de visitantes en dichos meses en el periodo 2017-2020 (ver pestaña agosto).

turismo_barras1 <- turismo_europa %>% 
  filter(Country != "European_Union") %>% 
  group_by(date) %>% 
  arrange(date, desc(value)) %>% 
  mutate(ranking = row_number()) %>%
  filter(ranking <=5) %>% 
  ungroup() %>% 
  filter(date == "2017-07-01" | date == "2018-07-01" | date == "2019-07-01" | date == "2020-07-01")



a11 <- ggplot(turismo_barras1, aes(ranking, value), size = 20) +
  geom_col(aes(ranking, value, fill = Country)) +
  scale_fill_brewer(palette = "Set3") +
  scale_x_reverse() +
  coord_flip(clip = "off", expand = FALSE) +
  theme_light() +
  facet_wrap(
    vars(date), nrow = 2, ncol = 2) + 
  
  theme(axis.text.x = element_text(colour = "white"),
    plot.background = element_rect(fill = "white")) +
  labs(y = "Turismo", subtitle = "Máximo turismo en agosto ",
    caption = "Fuente: Elaboración propia con datos del Euroestat ") +
  theme(panel.background = element_rect(colour = "white")) + 
  theme(panel.background = element_rect(linetype = "solid")) 

a11 <- ggplotly(a11)

a11

Una vez vistas ambas pestañas, podemos concluir con que los paises con una mayor afluencia turística son Francia, Alemania, Reino Unido, Italia y España, estando estos simepre en el top 5 de economías estudiadas manteniendo en la mayoria de casos su posición en este top.

Un factor a destacar, es que a pesar de ser las referentes en el ambito turístico europeo, todas ellas vieron disminuir en cierta medida el numero de turistas recibido en 2020, hecho que concuerda con la conclusion del computo global de Europa del primer apartado.



Agosto
turismo_barras <- turismo_europa %>% 
  filter(Country != "European_Union") %>% 
  group_by(date) %>% 
  arrange(date, desc(value)) %>% 
  mutate(ranking = row_number()) %>%
  filter(ranking <=5) %>% 
  ungroup() %>% 
  filter(date == "2017-08-01" | date == "2018-08-01" | date == "2019-08-01" | date == "2020-08-01")



a1 <- ggplot(turismo_barras, aes(ranking, value), size = 20) +
  geom_col(aes(ranking, value, fill = Country)) +
  scale_fill_brewer(palette = "Set3") +
  scale_x_reverse() +
  coord_flip(clip = "off", expand = FALSE) +
  theme_light() +
  facet_wrap(
    vars(date), nrow = 2, ncol = 2) + 
  
  theme(axis.text.x = element_text(colour = "white"),
    plot.background = element_rect(fill = "white")) +
  labs(y = "Turismo", subtitle = "Máximo turismo en agosto ",
    caption = "Fuente: Elaboración propia con datos del Euroestat ") +
  theme(panel.background = element_rect(colour = "white")) + 
  theme(panel.background = element_rect(linetype = "solid")) +
  theme(legend.position = "none")

a1 <- ggplotly(a1)

a1

4.1.3 ¿A quien le afecto más la crisis sanitaria?

Cuadros

En estos dos cuadros podemos observar como a la economía de Slovenia no le afecto de forma significativamente negativa la crisis sanitaria, sino todo lo contrario, ya que el nivel de turismo respecto al mes de agosto del año anterior se vió incremenetado.

Sin emabargo, el pais mas afectado fue Liechtenstein, donde el turismo en agosto disminuyó en un 50% respecto al año de anterior.

Si se desea saber como evolucionó cada economía lo puede observar en la tabla.



impacto <- turismo_europa %>% filter(date == "2019-08-01" | date == "2020-08-01")

impacto <- impacto %>% filter(Country != "European_Union") %>% 
  group_by(Country) %>% 
  mutate(crecimiento = value - lag(value)) %>% 
  mutate(incremento = crecimiento / first(value) * 100 ) %>% 
  ungroup()

max <- impacto %>% slice_max(incremento, n = 1) %>% 
  select(Country, incremento)

min <- impacto %>% slice_min(incremento, n = 1) %>% 
  select(Country, incremento)
  
  
  
bandera_max <- c("http://banderasmundo.es/banderas/eslovenia.png")


max_inc <- max %>% group_by(Country) %>% 
  add_column(bandera_max) %>% ungroup()


Tabla_max <- max_inc %>% gt()

Tabla_max <- Tabla_max %>%
  tab_header(title = md("**País menos perjudicado**"),subtitle = md("A fecha: 01-08-2020"))

Tabla_max <- Tabla_max %>%
  tab_options(heading.background.color = "#ffb74d") %>% tab_options(heading.title.font.size = 15, heading.subtitle.font.size = 13,  column_labels.font.weight =  "bold")


Tabla_max <- Tabla_max  %>%
  gt::text_transform(locations = cells_body(columns = vars(bandera_max)), fn = function(x) {gt::web_image(x, height = 50)}) %>%  cols_align(
    align = "center")

Tabla_max
País menos perjudicado
A fecha: 01-08-2020
Country incremento bandera_max
Slovenia 172.2913

bandera_min <- c("http://banderasmundo.es/banderas/liechtenstein.png")


min_inc <-min %>% group_by(Country) %>% 
  add_column(bandera_min) %>% ungroup()



Tabla_min <- min_inc %>% gt()

Tabla_min <- Tabla_min %>%
  tab_header(title = md("**Pais más perjudicado**"),subtitle = md("A fecha: 01-08-2020"))

Tabla_min <- Tabla_min %>%
  tab_options(heading.background.color = "#ffb74d") %>% tab_options(heading.title.font.size = 15, heading.subtitle.font.size = 13,  column_labels.font.weight =  "bold")


Tabla_min <- Tabla_min  %>%
  gt::text_transform(locations = cells_body(columns = vars(bandera_min)), fn = function(x) {gt::web_image(x, height = 50)}) %>%  cols_align(
    align = "center")

Tabla_min
Pais más perjudicado
A fecha: 01-08-2020
Country incremento bandera_min
Liechtenstein -50.68966

Tabla

impacto_tabla <- impacto %>% select(Country, date, incremento) %>% 
  drop_na()

datatable(impacto_tabla, class ="stripe hover compact row-border" , filter = 'top')

4.2 Imortancia de cada país en la actualidad

4.2.1 Treemap

A traves de este treemap podemos concluir lo que deciamos ya en apartados anteriores, los paises con una mayor numero de turistas en Agosto de 2021 siguen siendo Alemania, Iatlia y España. Este hecho no sorprende ya que es una continuación de la tendencia anteriormente descrita, sin embargo cabe destacar que el número de personas que decidieron desplazarse este año ha superado al predecesor, como se puede observar tanto en el gráfico como en la tabla del primer apartado, siendo esto consecuencia de la mejora de la crisis sanitaria por el gran avance en la vacunación contra el covid, que ha permitido la eliminación de numerosas restricciones.

El hecho de que no aparezcan paises como Francia y Reino Unido se debe a la falta de datos en el Eurostat de estos paises para el perido estudiado de 2021.

p2 <- turismo_europa %>% filter(date == "2021-08-01") %>% 
  filter(Country != "European_Union") %>% 
  slice_max(value, n =15)
  


p2 <- treemap(p2,
              index="Country",
              vSize="value",
              type="index",
              title="Turismo en la UE (Agosto 2021)",
              palette="Set3",
              border.col=c("white"), 
              border.lwds=3, 
              fontface.labels=1,
              bg.labels=c("transparent"),              
              align.labels=c("center", "center"),                                  
                              overlap.labels=0.5)


4.2.2 Gráfico de barras

Aquí podemos observar lo anteriormente descrito, las principales economías suelen ser siempre las mismas, presentando por una parte todas la misma temporalidad (reflejada en la disminución del numero de turistas en los mismos meses) y por otra, la disminución de turistas por el COVID-19.


barras <- turismo_europa %>% 
  filter( Country != "European_Union")

barras  <- barras  %>% 
  group_by(date) %>% 
  arrange(date, desc(value)) %>% 
  mutate(ranking = row_number()) %>%
  filter(ranking <=9) %>% 
  ungroup() 

barras$date <- as.character(barras$date)


tabla_1 <- ggplot(barras, aes(ranking, value, country = code, size = 15)) +
  geom_col(aes(ranking, value,  fill = "#ffb74d")) +
  
  geom_flag(aes(ranking, value, country = code), size = 10) +
  geom_text(aes(ranking, value, label = as.factor(value), size = 20), hjust= -0.5) +
  geom_text(aes(x=9, y=30000000, label = as.factor(date)), vjust = 0.2, alpha = 0.5,  col = "gray", size = 10) +
  
  scale_x_reverse() +
  coord_flip(clip = "off", expand = FALSE) +
  theme_light() +
  theme(
    panel.grid = element_blank(), 
    legend.position = "none",
    axis.ticks.y = element_blank(),
    axis.title.y = element_blank(),
    axis.text.y = element_blank()) +
    theme(axis.line = element_line(colour = NA),
                              axis.ticks = element_line(colour = NA),
                              panel.grid.major = element_line(colour = NA),
                              panel.grid.minor = element_line(colour = NA),
                              axis.text = element_text(colour = NA),
                              plot.background = element_rect(colour = NA)) +labs(x = NULL, y = NULL)+
  labs(title = "Evolución del turismo en Europa",
       subtitle = "Tursimo desde 2017 hasta 2021.",
       caption = "Fuente: Elaboración propia con datos de Euroestat") +
  lims(y = c(NA, 40000000)) +
  
  transition_states(as.factor(date),transition_length = 1, state_length = 0, wrap = FALSE)

tabla_1 <- tabla_1 +  theme(legend.position = "none") 

#gganimate::animate(tabla_1, nframes = 450, fps = 25) 


5 Estudio del turismo en España

El turismo es uno de los principales motores de la economía española, otorgando empleo aproximadamnete a 2 millones de personas, con los que se recibe de promedio a 80 millones de turistas al año (antes de la pamdemia) que dejan aproximadamnete unos 90.000 millones de euros en ingresos. Por ello, no es de extrañar la elevada inversión llevada a cabo para mejorar el sector.

Todas estas inversiones han derivado en que España se convierta en uno de los paises más competitivos en el sector turístico, quedando esto demostrado en el ranking elaborado por el Worl Economic Forum, otorgandole la primera posición de entre 140 economías.

Esto es posible por la gran oferta turistica de la que dispone nuestro país, pudiendo decantarse por experiencias más enfocadas en el sol y playa o más cultrales y naturales, hospedandose en la gran densidad hotelera instalada en nuetsro país.


5.1 Estudio de la oferta hotelera

5.1.2 Número de hoteles por CCAA

En este gráfico podemos observar el numero de establecimientos hoteleros por comunidad autonoma, siendo Andalucia la comunidad con mayor presencia de estos con 1557 establecimientos, seguido de comunidades como Cataluña, Madrid o Valencia, que como veremos en el apartado 5.2 son las comunidades que mayor número de turistas, y por ende ingresos, reciben.

Algo que puede sorprender es el hecho del número de hoteles de los que disponen las islas baleares y canarias, hecho que se explica por su reducida dimensión, y el hecho de que comunidades como Galicia y Castilla y Leon, que a priori no están consideradas como comunidades que reciban un numero considerable de turistas, posean un mayor número de hoteles que la Comunitat Valenciana y la Comunidad de Madrid.


num <- ggplot() +
  geom_col(data = n_hoteles, aes( x = reorder(location, n_hoteles), y = n_hoteles, fill = n_hoteles)) +
   scale_fill_continuous(low="#ffecb3", high="#ff8f00") +
  
  coord_flip() +
  
  theme(panel.background = element_rect(fill = "white"),
    plot.background = element_rect(fill = "white")) +
  labs(x = NULL, y = NULL, fill = "Hoteles",
    caption = "Fuente: Elaboración propia ") + 
  theme(legend.position = "none")

num <- ggplotly(num)

num


5.1.2 Categoría de dichos hoteles

Gráfico de Dona

Dichos hoteles están clasificados segun una clasificación de estrellas oro, de 1 a 5 estrellas, siendo la quinta la de mayor prestigio (aunque esta regulación cambia de comuindad en comunidad por lo que no se siguen los mismos criterios para cada decisión).

Como podemos observar en el gráfico de Dona, los hoteles de 2,3 y 4 estrellas represnetan una mayor proporcion en España.

Además también disponemos de la información sobre los hostales, que al igual que los hoteles se clasifican con estrellas, pero esta vez de plata. En este caso observamos como los hotales de una estrella son los principales en nuestro pais.

Si desea conocer los porcentajes con detalle puede acudir a la tabla


categoria_hotel <- categorias %>% filter( categoria == "hoteles") %>% 
  mutate(total = sum(numero)) %>% 
  mutate(porcentaje = (numero / total) * 100) 

n <- ggplot(categoria_hotel ,aes(x=2,y=porcentaje, fill = estrellas))+
  geom_bar(stat = "identity",
           color="white")+
  
  scale_fill_manual(values=c("#81c784","#7e57c2","#2196f3","#ffee58", "#f44336")) +
  
  coord_polar(theta = "y")+
  xlim(0.5,2.5)  +
  theme_void()+
  
  theme(axis.line = element_line(colour = "white"),
    axis.ticks = element_line(colour = "white"),
    panel.background = element_rect(fill = "white"),
    plot.background = element_rect(fill = "white"),
    legend.position = "none") +
    labs(x = NULL, y = NULL, fill = NULL)+labs(title = "Categoria de los hoteles",
    caption = "Fuente: Elaboración propia ") + 
  theme(panel.grid.major = element_line(colour = "white"),
        panel.grid.minor = element_line(colour = "white"),
        panel.background = element_rect(colour = "white")) + 
  theme(legend.position = "bottom", legend.direction = "horizontal") + 
  theme(panel.grid.major = element_line(colour = NA),
        panel.grid.minor = element_line(colour = NA),
        axis.title = element_text(colour = "white"),
        panel.background = element_rect(colour = NA),
        plot.background = element_rect(colour = NA))

#n
 
  

categoria_hostal <- categorias %>% filter( categoria == "hostales") %>% 
  mutate(total = sum(numero)) %>% 
  mutate( porcentaje = (numero / total) * 100)


m <- ggplot(categoria_hostal ,aes(x=2,y=porcentaje, fill = estrellas))+
  geom_bar(stat = "identity",
           color="white")+
  
  scale_fill_manual(values=c("#81c784","#7e57c2","#2196f3","#ffee58", "#f44336")) +
  
  coord_polar(theta = "y")+
  xlim(0.5,2.5)  +
  theme_void()+
  
  theme(axis.line = element_line(colour = "white"),
        axis.ticks = element_line(colour = "white"),
        panel.background = element_rect(fill = "white"),
        plot.background = element_rect(fill = "white"),
        legend.position = "none") +
  labs(x = NULL, y = NULL, fill = NULL)+labs(title = "Categoria de los hostales",
                                             caption = "Fuente: Elaboración propia ") + 
  theme(panel.grid.major = element_line(colour = "white"),
        panel.grid.minor = element_line(colour = "white"),
        panel.background = element_rect(colour = "white")) + 
  theme(legend.position = "bottom", legend.direction = "horizontal") + 
  theme(panel.grid.major = element_line(colour = NA),
    panel.grid.minor = element_line(colour = NA),
    axis.title = element_text(colour = "white"),
    panel.background = element_rect(colour = NA),
    plot.background = element_rect(colour = NA))


#m

Tablas
  
datatable(categoria_hotel, class ="stripe hover compact row-border" , filter = 'top')

datatable(categoria_hostal, class ="stripe hover compact row-border" , filter = 'top')

5.2 Estudio de los ingresos por turismo

5.2.1 Evolución de los ingresos

El sector turístico supone una fuente de ingresos muy grande para España, de unos 90.000 millones de euros al año como he comentado anteiormente, no obstante desde la crisis vivida en 2020 los ingresos decayeron de manera muy considerable, y a pesar de que vivimos en un periodo de cierta recuperación, tanto económica como de libertad de movimiento, los ingresos del año 2021 distan mucho de ser semblantes a los de años anteriores.


# Gráfico de España

gasto_esp <- gasto_tur %>% filter(location == "Spain")

gasto_esp$date <- as.Date(gasto_esp$date)

gasto_esp_2 <- gasto_esp %>% filter(date == "2020-02-01" | date == "2020-03-01" | date == "2020-04-01" | date == "2020-05-01" | date == "2020-06-01")

m1 <- ggplot() +
  geom_line(data = gasto_esp, aes(date, value), color = "#616161", size = 1.5) +
  geom_point(data = gasto_esp, aes(date, value ), color = "#616161", size = 1.5) +
  
  geom_line(data = gasto_esp_2, aes(date, value), color = "#d50000", size = 1.5) +
  geom_point(data = gasto_esp_2, aes(date, value), color = "#d50000", size = 1.5) +
  
  
  geom_hline(yintercept =0,
             size = 0.25,
             colour = "black") +
  
  
  scale_x_date(date_labels="%Y-%m",date_breaks  ="3 months") +
  theme(axis.text.x = element_text(angle = 70, hjust = 1)) +
  
  theme(panel.background = element_rect(fill = "white"),
    plot.background = element_rect(fill = "white")) +
  
  labs(title = "Evolución de los ingresos en España",
    x = NULL, y = "Ingresos", subtitle = "En millones de euros")


# Gráfico de las comunidades 

gasto_comu <- gasto_tur %>%  filter(location != "Spain") %>% 
  filter(location %in% c("Andalucía", "Cataluña", "Comunitat Valenciana", "Madrid, Comunidad de"))

m2 <- ggplot() +
  geom_line(data = gasto_comu, aes(date, value, color = location), size = 1.5) +
  geom_point(data = gasto_comu, aes(date, value, color = location), size = 1.5) +
  
  geom_hline(yintercept =0,
            size = 0.25,
            colour = "black") +
  
  
  scale_x_date(date_labels="%Y-%m",date_breaks  ="2 months") +
  
  
  theme(axis.text.x = element_text(angle = 70, hjust = 1))  + 
  
  
  scale_color_manual(breaks = c("Andalucía", "Cataluña", "Comunitat Valenciana", "Madrid, Comunidad de"),
                     values=c("#00b0ff", "#90caf9", "#ff9800", "#ffcc80")) +
  
  
  theme(panel.background = element_rect(fill = "white"),
    plot.background = element_rect(fill = "white"),
    legend.position = "bottom", legend.direction = "horizontal") +
  
  labs(title = "Evolución de los ingresos por CCAA",
    x = NULL, y = "Ingresos ", colour = NULL,
    subtitle = "En millones de euros ", caption = "Fuente: Elaboración propia con datos del INE")


#m2 + inset_element(m1, left = 0.6, right = 1, bottom = 0.5, top = 1.05)
  


5.3 Principales Comunidades Aurónomas

5.3.1 Comunidades Autónomas con más ingresos

Mapa

En este apartado podemos apreciar como las CCAA con mayor nivel de ingresos por turismo son Cataluña, Andalucía, Comunitat Valenciana, Comunidad de Madrid, Illes Balears y Canarias.

Si desea conocer los ingresos en cada perido puede consultar la tabla


rm(gasto_comunidades_autonomas, gasto_turistico_esp, IGN_nomencla_muni, municipios_2020, rio_ebro_4, rios_espanya, world)

CCAA_2 <- Provincias %>% group_by(ine_ccaa, ine_ccaa.n) %>% summarize()

CCAA_3 <- CCAA_2 %>% sf::st_drop_geometry()


#unir aqui los datos del gasto con su geometría

canarias <- CCAA_2 %>% filter(ine_ccaa.n == "Canarias")
peninsula <- CCAA_2 %>% filter( !(ine_ccaa.n == "Canarias"))

my_shift <- st_bbox(peninsula)[c(1,2)]- (st_bbox(canarias)[c(1,2)]) + c(-2.4, -1.1)
canarias$geometry <- canarias$geometry + my_shift
st_crs(canarias)  <- st_crs(peninsula)
peninsula_y_canarias <- rbind(peninsula, canarias)

peninsula_y_canarias_1 <-peninsula_y_canarias %>% sf::st_drop_geometry()

gasto_ccaa <- full_join(gasto_tur, peninsula_y_canarias, by = c("location" = "ine_ccaa.n"))

gasto_ccaa <- gasto_ccaa %>% filter(date == "2021-08-01")

p1 <- ggplot() +
   geom_sf(data = peninsula_y_canarias) +
  geom_sf(data = gasto_ccaa, aes(geometry = geometry, fill = value )) +
  theme_void()  +
  theme(plot.subtitle = element_text(family = "serif", face = "italic"),
        plot.title = element_text(family = "serif", face =  "italic")) +
  labs(title = "Gasto turístico", fill = "Ingresos")  +
  scale_fill_continuous(low="#ffecb3",high="#ef6c00") +
  labs(title = "",
       caption = "Datos extraidos de INE")

p1



Tabla

gasto_tur_2 <- gasto_tur %>% rename(ingresos = value)

datatable(gasto_tur_2, class ="stripe hover compact row-border" , filter = 'top')

5.3.2 Consecuencias del Covid-19

Impacto

En estos cuadros podemos observar cuales fueron las comunidades, de las anteriormente mencionadas, que sufrieron en mayor y menor medida las consecuenicas del COVID-19.


impacto_2 <- gasto_tur %>% filter(date == "2019-08-01" | date == "2020-08-01")

impacto_2 <- impacto_2 %>% filter(location != c("Spain", "Otras Comunidades Autónomas")) %>% 
  group_by(location) %>% 
  mutate(crecimiento = value - lag(value)) %>% 
  mutate(incremento = crecimiento / first(value) * 100 ) %>% 
  ungroup()

max_2 <- impacto_2 %>% slice_max(incremento, n = 1) %>% 
  select(location, incremento)



bandera_valencia <- ("imagenes/comunidad_valenciana.png")


max_inc <- max_2 %>% group_by(location) %>% 
  add_column(bandera_valencia) %>% 
  ungroup()


Tabla_max_b <- max_inc %>% gt()

Tabla_max_b <- Tabla_max_b %>%
  tab_header(title = md("**Comunidad menos perjudicada**"),subtitle = md("A fecha: 01-08-2020"))

Tabla_max_b <- Tabla_max_b %>%
  tab_options(heading.background.color = "#ffb74d") %>% 
  tab_options(heading.title.font.size = 15, heading.subtitle.font.size = 13,  column_labels.font.weight =  "bold")


Tabla_max_b <- Tabla_max_b  %>%
  gt::text_transform(locations = cells_body(columns = vars(bandera_valencia)), fn = function(x) {gt::web_image(x, height = 50)}) %>%  
  cols_align(
    align = "center")

Tabla_max_b
Comunidad menos perjudicada
A fecha: 01-08-2020
location incremento bandera_valencia
Comunitat Valenciana -71.21637

min_2 <- impacto_2 %>% slice_min(incremento, n = 1) %>% 
  select(location, incremento)

bandera_madrid <- ("imagenes/madrid.png")


min_inc <- min_2 %>% group_by(location) %>% 
  add_column(bandera_madrid) %>% ungroup()


Tabla_mix_b <- min_inc %>% gt()

Tabla_mix_b <- Tabla_mix_b %>%
  tab_header(title = md("**Comunidad más perjudicada**"),subtitle = md("A fecha: 01-08-2020"))

Tabla_mix_b <- Tabla_mix_b %>%
  tab_options(heading.background.color = "#ffb74d") %>% tab_options(heading.title.font.size = 15, heading.subtitle.font.size = 13,  column_labels.font.weight =  "bold")


Tabla_mix_b <- Tabla_mix_b  %>%
  gt::text_transform(locations = cells_body(columns = vars(bandera_madrid)), fn = function(x) {gt::web_image(x, height = 50)}) %>%  cols_align(
    align = "center")

Tabla_mix_b
Comunidad más perjudicada
A fecha: 01-08-2020
location incremento bandera_madrid
Madrid, Comunidad de -89.14468

Recuperación

Aquí vemos como los papeles se invierte, y la comunidad que más cayó en 2020 es la que mayor recuperación presenta en 2021 y viceversa.


recu <-  gasto_tur %>% filter(date == "2020-08-01" | date == "2021-08-01")

recu <- recu %>% filter(location != c("Spain", "Otras Comunidades Autónomas")) %>% 
  group_by(location) %>% 
  mutate(crecimiento = value - lag(value)) %>% 
  mutate(incremento = crecimiento / first(value) * 100 ) %>% 
  ungroup()

recu_max <- recu %>% slice_max(incremento, n = 1) %>% 
  select(location, incremento)

bandera_madrid <- ("imagenes/madrid.png")

recu_1 <- recu_max %>% group_by(location) %>% 
  add_column(bandera_madrid) %>% ungroup()


Tabla_max_c <- recu_1 %>% gt()

Tabla_max_c <- Tabla_max_c %>%
  tab_header(title = md("**Comunidad con una mayor recuperación**"),subtitle = md("A fecha: 01-08-2021"))

Tabla_max_c <- Tabla_max_c %>%
  tab_options(heading.background.color = "#ffb74d") %>% tab_options(heading.title.font.size = 15, heading.subtitle.font.size = 13,  column_labels.font.weight =  "bold")


Tabla_max_c <- Tabla_max_c  %>%
  gt::text_transform(locations = cells_body(columns = vars(bandera_madrid)), fn = function(x) {gt::web_image(x, height = 50)}) %>%  cols_align(
    align = "center")

Tabla_max_c
Comunidad con una mayor recuperación
A fecha: 01-08-2021
location incremento bandera_madrid
Madrid, Comunidad de 288.5023

recu_min <- recu %>% slice_min(incremento, n = 1) %>% 
  select(location, incremento)

bandera_valencia <- ("imagenes/comunidad_valenciana.png")

recu_2 <- recu_min %>% group_by(location) %>% 
  add_column(bandera_valencia ) %>% ungroup()


Tabla_min_c <- recu_2 %>% gt()

Tabla_min_c <- Tabla_min_c %>%
  tab_header(title = md("**Comunidad con una menor recuperación**"),subtitle = md("A fecha: 01-08-2021"))

Tabla_min_c <- Tabla_min_c %>%
  tab_options(heading.background.color = "#ffb74d") %>% tab_options(heading.title.font.size = 15, heading.subtitle.font.size = 13,  column_labels.font.weight =  "bold")


Tabla_min_c <- Tabla_min_c  %>%
  gt::text_transform(locations = cells_body(columns = vars(bandera_valencia)), fn = function(x) {gt::web_image(x, height = 50)}) %>%  cols_align(
    align = "center")

Tabla_min_c
Comunidad con una menor recuperación
A fecha: 01-08-2021
location incremento bandera_valencia
Comunitat Valenciana 96.28821

6 Conclusiones

Para finalizar el trabajo destacar como el turismo es uno de los principales motores de las economías europeas, sobre todo de la española, proporcionando esta una fuente de ingresos muy importante, con lo que todo ello conlleva (empleo, bienestar, PIB…). Por ello es preocupnate la situación actual en la que vivimos, ya que a pesar de que en la actualidad experimentamos una cierta recuperación económica, están surgiendo nuevas variantes del COVId-19, como la Omicron, que están poniendo en jaque a las econmias mencionadas en el trabajo, por lo cual no se descarta la imposición de nuevas restricciones que puedan refrenar dicha recuperación afectando así de forma muy negativa a este sector en concreto.


Respecto a la elaboración del trabajo, destacar como la elaboración del ensayo grupal me ha servido de utilidad en el momento de tratar de manejar los datos, así como para la elaboración de gráficas que antes suponian un plus de dificultad. Además, la realización de este me ha permitido acabar de asentar los conociminetos adquiridos tanto en la asignatura como los que adquirimos junto a mis compañeros y yo al realizar el otro trabajo.


7. Referencias

Para realizar los comentarios y gráficos que hemos ido analizando a lo largo del trabajo me he basado en artículos y datos que expondré a continuación .

Para poder realizar dichos comentarios, he consultado estos artículos:

Para realizar gráficos animados, he consultado las explicaciones de como implementar el paquete gganimate en el proyecto.

Para poder realizar un mapa de España y sus CCAA me he basado en este tutorial de la asignatura.

Además, para la poder determinar de forma muy visual la proporción de turistas por pais he elaborado un treemap bansadome en esta página.

También he consulatdo la página R-Graph como inspiración para algunos gráficos.

Para determinar la escala de colores, tanto del CSS como de los gráficos he consultado estas paletas

Por último, destacar que tambíen he consultado los trabajos realizados por mis compañeros en años anteriores. Los puedes encontrar aqui



Para concluir este apartado incluimos la session info:

sessioninfo::session_info() %>% details::details(summary = 'current session info') 
current session info

- 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     2022-01-04                  

- Packages -------------------------------------------------------------------
 package           * version    date       lib
 assertthat          0.2.1      2019-03-21 [1]
 backports           1.2.1      2020-12-09 [1]
 base64enc           0.1-3      2015-07-28 [1]
 bit                 4.0.4      2020-08-04 [1]
 bit64               4.0.5      2020-08-30 [1]
 broom               0.7.9      2021-07-27 [1]
 bslib               0.3.1      2021-10-06 [1]
 cellranger          1.1.0      2016-07-27 [1]
 checkmate           2.0.0      2020-02-06 [1]
 class               7.3-19     2021-05-03 [2]
 classInt            0.4-3      2020-04-07 [1]
 cli                 3.0.1      2021-07-17 [1]
 clipr               0.7.1      2020-10-08 [1]
 colorspace          2.0-2      2021-06-24 [1]
 commonmark          1.7        2018-12-01 [1]
 countrycode       * 1.3.0      2021-07-15 [1]
 crayon              1.4.2      2021-10-29 [1]
 crosstalk           1.1.1      2021-01-12 [1]
 curl                4.3.2      2021-06-23 [1]
 data.table          1.14.0     2021-02-21 [1]
 DBI                 1.1.1      2021-01-15 [1]
 dbplyr              2.1.1      2021-04-06 [1]
 desc                1.3.0      2021-03-05 [1]
 details             0.2.1      2020-01-12 [1]
 digest              0.6.28     2021-09-23 [1]
 dplyr             * 1.0.7      2021-06-18 [1]
 DT                * 0.19       2021-09-02 [1]
 e1071               1.7-8      2021-07-28 [1]
 ellipsis            0.3.2      2021-04-29 [1]
 evaluate            0.14       2019-05-28 [1]
 fansi               0.5.0      2021-05-25 [1]
 farver              2.1.0      2021-02-28 [1]
 fastmap             1.1.0      2021-01-25 [1]
 forcats           * 0.5.1      2021-01-27 [1]
 foreign             0.8-81     2020-12-22 [2]
 fs                  1.5.0      2020-07-31 [1]
 generics            0.1.1      2021-10-25 [1]
 gganimate         * 1.0.7      2020-10-15 [1]
 ggflags           * 0.0.2      2021-11-03 [1]
 ggplot2           * 3.3.5      2021-06-25 [1]
 ggrepel           * 0.9.1      2021-01-15 [1]
 gifski              1.4.3-1    2021-05-02 [1]
 glue                1.4.2      2020-08-27 [1]
 gridBase            0.4-7      2014-02-24 [1]
 grImport2           0.2-0      2019-11-25 [1]
 gt                * 0.3.1      2021-08-07 [1]
 gtable              0.3.0      2019-03-25 [1]
 haven               2.4.3      2021-08-04 [1]
 here              * 1.0.1      2020-12-13 [1]
 highr               0.9        2021-04-16 [1]
 hms                 1.1.1      2021-09-26 [1]
 htmltools           0.5.2      2021-08-25 [1]
 htmlwidgets         1.5.4      2021-09-08 [1]
 httpuv              1.6.3      2021-09-09 [1]
 httr                1.4.2      2020-07-20 [1]
 igraph              1.2.8      2021-11-07 [1]
 jpeg                0.1-9      2021-07-24 [1]
 jquerylib           0.1.4      2021-04-26 [1]
 jsonlite            1.7.2      2020-12-09 [1]
 KernSmooth          2.23-20    2021-05-03 [2]
 klippy              0.0.0.9500 2021-11-12 [1]
 knitr             * 1.36       2021-09-29 [1]
 labeling            0.4.2      2020-10-20 [1]
 later               1.3.0      2021-08-18 [1]
 lattice             0.20-44    2021-05-02 [2]
 lazyeval            0.2.2      2019-03-15 [1]
 lifecycle           1.0.1      2021-09-24 [1]
 lubridate           1.8.0      2021-10-07 [1]
 magrittr            2.0.1      2020-11-17 [1]
 mime                0.12       2021-09-28 [1]
 modelr              0.1.8      2020-05-19 [1]
 munsell             0.5.0      2018-06-12 [1]
 openxlsx            4.2.4      2021-06-16 [1]
 pacman              0.5.1      2019-03-11 [1]
 patchwork         * 1.1.1      2020-12-17 [1]
 pillar              1.6.4      2021-10-18 [1]
 pjpv.datos.01     * 0.0.0.9000 2021-11-26 [1]
 pkgconfig           2.0.3      2019-09-22 [1]
 plotly            * 4.10.0     2021-10-09 [1]
 png                 0.1-7      2013-12-03 [1]
 prettyunits         1.1.1      2020-01-24 [1]
 progress            1.2.2      2019-05-16 [1]
 promises            1.2.0.1    2021-02-11 [1]
 proxy               0.4-26     2021-06-07 [1]
 purrr             * 0.3.4      2020-04-17 [1]
 R6                  2.5.1      2021-08-19 [1]
 RColorBrewer        1.1-2      2014-12-07 [1]
 Rcpp                1.0.7      2021-07-07 [1]
 readr             * 2.0.1      2021-08-10 [1]
 readxl            * 1.3.1      2019-03-13 [1]
 reprex              2.0.1      2021-08-05 [1]
 rio               * 0.5.27     2021-06-21 [1]
 rlang               0.4.12     2021-10-18 [1]
 rmarkdown           2.11       2021-09-14 [1]
 rnaturalearth     * 0.1.0      2017-03-21 [1]
 rnaturalearthdata * 0.1.0      2017-02-21 [1]
 rprojroot           2.0.2      2020-11-15 [1]
 rstudioapi          0.13       2020-11-12 [1]
 rvest               1.0.1      2021-07-26 [1]
 s2                  1.0.7      2021-09-28 [1]
 sass                0.4.0      2021-05-12 [1]
 scales              1.1.1      2020-05-11 [1]
 sessioninfo         1.1.1      2018-11-05 [1]
 sf                * 1.0-2      2021-07-26 [1]
 shiny               1.7.1      2021-10-02 [1]
 sp                  1.4-5      2021-01-10 [1]
 stringi             1.7.5      2021-10-04 [1]
 stringr           * 1.4.0      2019-02-10 [1]
 tibble            * 3.1.6      2021-11-07 [1]
 tidyr             * 1.1.4      2021-09-27 [1]
 tidyselect          1.1.1      2021-04-30 [1]
 tidyverse         * 1.3.1      2021-04-15 [1]
 treemap           * 2.4-3      2021-08-22 [1]
 tweenr              1.0.2      2021-03-23 [1]
 tweetrmd            0.0.9      2021-12-03 [1]
 tzdb                0.1.2      2021-07-20 [1]
 units               0.7-2      2021-06-08 [1]
 utf8                1.2.2      2021-07-24 [1]
 vctrs               0.3.8      2021-04-29 [1]
 viridisLite         0.4.0      2021-04-13 [1]
 vroom               1.5.4      2021-08-05 [1]
 withr               2.4.2      2021-04-18 [1]
 wk                  0.5.0      2021-07-13 [1]
 xfun                0.27       2021-10-18 [1]
 XML                 3.99-0.7   2021-08-17 [1]
 xml2                1.3.2      2020-04-23 [1]
 xtable              1.8-4      2019-04-21 [1]
 yaml                2.2.1      2020-02-01 [1]
 zip                 2.2.0      2021-05-31 [1]
 source                                 
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 Github (rensa/ggflags@e3c6e51)         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 Github (rlesur/klippy@378c247)         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 Github (perezp44/pjpv.datos.01@90ad8f4)
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.2)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 Github (gadenbuie/tweetrmd@075102b)    
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         
 CRAN (R 4.1.1)                         

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


LS0tDQp0aXRsZTogIlJlbGV2YW5jaWEgZGVsIHNlY3RvciB0dXLDrXN0aWNvIGVuIGxhIGVjb25vbcOtYSBwcmUgeSBwb3N0IENvdmlkLTE5Ig0KYXV0aG9yOiAiRnJhbmNpc2NvIE1hcnTDrW5leiBDYWJhbGxlcm8gKGZyYW1hMzZAYWx1bW5pLnV2LmVzKS4gXG5cbiBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEiDQpkYXRlOiAiRGljaWVtYnJlIGRlIDIwMjEgKGFjdHVhbGl6YWRvIGVsIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVknKWApIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjc3M6ICIuL2Fzc2V0cy9lc3RpbG9fMS5jc3MiDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSINCiAgICB0aGVtZTogZGFyaw0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiB5ZXMNCiAgICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIGRmX3ByaW50OiBrYWJsZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCmBgYHtyIHBhY2thZ2VzLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShyaW8pDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkodHJlZW1hcCkNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShnZ2FuaW1hdGUpDQpsaWJyYXJ5KGNvdW50cnljb2RlKQ0KbGlicmFyeShnZ2ZsYWdzKQ0KcGFjbWFuOjpwX2xvYWQoa25pdHIsIGhlcmUsIHRpZHl2ZXJzZSwgcGF0Y2h3b3JrLCBnZ3JlcGVsKQ0KcGFjbWFuOjpwX2xvYWQoc2YsIHJuYXR1cmFsZWFydGgsIHJuYXR1cmFsZWFydGhkYXRhKQ0KbGlicmFyeShwanB2LmRhdG9zLjAxKQ0KDQpgYGANCg0KDQoNCg0KYGBge3IgY2h1bmstc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgICNyZXN1bHRzID0gImhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgIGNhY2hlID0gRkFMU0UsIGNhY2hlLnBhdGggPSAiL2NhY2hlcy8iLCBjb21tZW50ID0gIiM+IiwNCiAgICAgICAgICAgICAgICAgICAgICAjZmlnLndpZHRoID0gNywgI2ZpZy5oZWlnaHQ9IDcsICAgDQogICAgICAgICAgICAgICAgICAgICAgI291dC53aWR0aCA9IDcsIG91dC5oZWlnaHQgPSA3LA0KICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gVFJVRSwgIGZpZy5zaG93ID0gImhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hc3AgPSAwLjYyOCwgb3V0LndpZHRoID0gIjk1JSIsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGRldiA9ICJwbmciLCBkZXYuYXJncyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkNCg0KYGBgDQoNCmBgYHtyIG9wdGlvbnMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCg0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQoNCmBgYA0KDQoNCmBgYHtyIGtsaXBweSwgZWNobyA9IEZBTFNFfQ0KDQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoInRvcCIsICJyaWdodCIpKSAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpDQoNCmBgYA0KDQo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij48ZGl2Lz4NCg0KPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+DQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gY2FzaSBpZ3VhbCwgc29sbyBIQVMgZGUgU1VTVElUVUlSICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+DQpUcmFiYWpvIGVsYWJvcmFkbyBwYXJhIGxhIGFzaWduYXR1cmEgIlByb2dyYW1hY2nDs24geSBtYW5lam8gZGUgZGF0b3MgZW4gbGEgZXJhIGRlbCBCaWcgRGF0YSIgZGUgbGEgVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIGR1cmFudGUgZWwgY3Vyc28gMjAyMS0yMDIyLiBFbCByZXBvIGRlbCB0cmFiYWpvIGVzdMOhIFthcXXDrV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyYW4yMjAwL3RyYWJham9fQmlnRGF0YV9lcXVpcG8pe3RhcmdldD0iX2JsYW5rIn0uIA0KDQo8IS0tIEVsIHDDoXJyYWZvIGRlIGFiYWpvIGhhcyBkZSBkZWphcmxvIGV4YWN0YW1lbnRlIGlndWFsLCBOTyBoYXMgZGUgY2FtYmlhciBuYWRhLS0+DQoNCkxhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmEgeSBsb3MgdHJhYmFqb3MgZGUgbWlzIGNvbXBhw7Flcm9zIHB1ZWRlbiB2ZXJzZSBbYXF1w61dKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIxLTIyLXdlYi8wNy10cmFiYWpvcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8aHIgY2xhc3M9ImxpbmVhLXJlZCI+DQoNCg0KIyMgMS4gSW50cm9kdWNjacOzbg0KDQpQYXJhIGxhIGFzaWduYXR1cmEgZGUgIlByb2dyYW1hY2nDs24geSBtYW5lam8gZGUgZGF0b3MgZW4gbGEgZXJhIGRlbCBCaWcgRGF0YSIgaGUgZGVjaWRpZG8gcmVhbGl6YXIgdW4gZW5zYXlvIHNvYnJlIGNvbW8gc2UgZXN0YSBkZXNlbnZvbHZpZW5kbyBlbCAqKnNlY3RvciB0dXLDrXN0aWNvKiosIHRhbnRvIGEgbml2ZWwgbmFjaW9uYWwsIGRhZGEgc3UgZ3JhbiByZWxldmFuY2lhIGFsIHNlciB1bm8gZGUgbG9zIHByaW5jaXBsYWVzIG1vdG9yZXMgZGUgbGEgZWNvbm9tw61hIGVzcGHDsW9sYSwgY29tbyBpbnRlcm5hY2lvbmFsLiAgDQoNCioqUmVzdW1lbjoqKiBFbCBzZWN0b3IgdHVyw61zdGljbyBlcyB1bm8gZGUgbG9zIHByaW5jaXBhbGVzIG1vdGVyZXMgZWNvbsOzbWljb3MgZGUgY3VhbHF1aWVyIGVjb25vbcOtYSwgdGVuaWVuZG8gZXN0ZSB1bmEgZ3JhbiByZXBlcmN1c2nDs24gcG9zaXRpdmEgcGFyYSBsYSBtaXNtYS4gTm8gb2JzdGFudGUgZXN0ZSBzZWN0b3IgaGEgc2lkbyB1bm8gZGUgbG9zIHByaW5jaXBhbGVzIHBlcmp1ZGljYWRvcyB0cmFzIGxhICBwYW5kZW1pYSBkZSAyMDIwLCB2aXZpZW5kbyBkdXJhbnRlIGVsIHBlcmlvZG8gZGUgdGllbXBvIGVzdHVkaWFkbyBlbiB1biBlc2NlbmFyaW8gZGUgaW5jZXJ0aWR1bWJyZSBjYXJhY3Rlcml6YWRvLCBwb3IgdW5hIHBhcnRlLCBwb3IgcG9yIGxhIGRpc21pbnVjacOzbiBkZSBzdXMgaW5ncmVzb3MgZGVzZGUgZWwgaW5pY2lvIGRlIGRpY2hvIGFjb250ZWNpbWllbnRvLCB5IHBvciBvdHJhLCBwb3IgbGEgaW1wb3NpY2nDs24gZGUgZGl2ZXJzYXMgcmVzdHJpY2Npb25lcyBxdWUgaGFuIGZyZW5hZG8gbGEgYWN0aXZpZGFkIGVjb27Ds21pY2EgZGVsIHNlY3Rvci4gWSBlcyBhaG9yYSwgbW9tZW50byBlbiBlbCBxdWUgdml2aW1vcyB1biBjaWVydG8gcGVyaW9kbyBkZSByZWN1cGVyYWNpw7NuIGVjb27Ds21pY2EsIGN1YW5kbyBub3MgcGxhbnRlYW1vcyBlbiBxdWUgc2l0dWFjacOzbiBub3MgZW5jb250cmFtb3MgcmVzcGVjdG8gYSBsYSBzaXR1YWNpw7NuIHByZSBwYW5kZW1pYSB5IGNvbW8gZWwgY29udGV4dG8gZW4gZWwgcXVlIHZpdmltb3MgcHVlZGUgdmFyaWFyIHBvciBsYXMgbnVldmFzIHZhcmllbnRlcyBkZWwgQ09WSUQtMTkuDQoNCg0KKipQYWxhYnJhcyBDbGF2ZToqKiBUdXJpc21vLCBJbmdyZXNvcywgRXVyb3BhLCBNb3RvciBlY29uw7NtaWNvLCBFc3Bhw7FhLCBIb3RlbGVzLCBDb3ZpZC0xOSwgw5NtaWNyb24sIEluY2VydGlkdW1icmUsIFJlY3VwcmFjacOzbiwgQ3Jpc2lzLg0KDQo8YnI+DQoNCiMjIDIuIE1vdGl2YWNpb25lcw0KDQpQb2RlbW9zIGVudGVuZGVyIGVsICoqdHVyaXNtbyoqIGNvbW8gZWwgY29uanVudG8gZGUgZGVzcGxhemFtaWVudG9zIHF1ZSByZWFsaXphbiBsb3MgaW5kaXZpZHVvcywgdGFudG8gYSB1biBuaXZlbCBuYWNpb25hbCBjb21vIGludGVybmFjaW9uYWwsIGRlIGZvcm1hIHZvbHVudGFyaWEgZnVlcmEgZGUgc3UgcmVzaWRlbmNpYSBoYWJpdHVhbC4gRGVudHJvIGRlIGRpY2hvcyBkZXNwbGF6YW1pZW50b3MsIHNlZ8O6biBsYXMgcHJlZmVyZW5jaWFzIGRlIGxvcyBwcm9waW9zIHR1cmlzdGFzLCBlc3RvcyBzZSBwdWVkZW4gZGVjYW50YXIgcG9yIHZpdmlyIHVuYSBzZXJpZSBkZSBleHBlcmllbmNpYXMgdSBvdHJhcywgY29tbyBwdWVkYSBzZXIgZWwgdHVyaXNtbyBkZSBzb2wgeSBwbGF5YSAocHJlZG9taW5hbnRlIGVuIG51ZXN0cm8gcGHDrXMpIG8gdW5vIG3DoXMgZW5mb2NhZG8gYSBsYSBjdWx0dXJhIG8gZ2FzdHJvbm9tw61hLiANCg0KTm8gb2JzdGFudGUsIHNlYSBjdWFsIHNlYSBsYSBlbGVjY2nDs24gZmluYWwgZGVsIGNvbnN1bWlkb3IsIHRvZGFzIGVzdGFzIHRpZW5lbiB1bmEgcmVwZXJjdXNpw7NuIHBvc2l0aXZhIHBhcmEgbGEgZWNvbm9tw61hLCB5YSBxdWUgZXN0aW11bGFuIHRhbnRvIGxhIGRlbWFuZGEgZXh0ZXJuYSBjb21vIGludGVybmEgZ2VuZXJhbmRvIGVuIGVsIHBhaXMgcGVyY2VwdG9yIHVuIGluY3JlbWVudG8gZW4gbG9zIGluZ3Jlc29zLCB0YW50byBhIG5pdmVsIG1pY3JvIGNvbW8gbWFjcm8sIGNvbiBzdXMgY29uc2VjdWVudGVzIGVmZWN0b3MgcG9zaXRpdm9zIHNvYnJlIGVsIGVtcGxlbyBsb2NhbCwgbGEgaW52ZXJzacOzbiBlbiB0b2RvIHRpcG8gZGUgaW5mcmFlc3RydWN0dXJhcyB5IGVsIFBJQiwgZW50cmUgbXVjaG9zIG90cm9zIGVmZWN0b3MuIA0KDQpFbiBlbCBtb21lbnRvIGRlIGVzdGFyIGRlc2Fycm9sbGFuZG8gZXN0ZSBlbnNheW8sIGVsIHNlY3RvciB0dXJpc3RpY28gYSBuaXZlbCBtdW5pZGFsIHNlIGVuY3VlbnRyYSBlbiB1bmEgc2l0dWFjacOzbiBjb21wbGljYWRhLCBkb25kZSBhIHBlc2FyIGRlIGxhIGxldmUgcmVjdXBlcmFjacOzbiBxdWUgZXN0YWJhbW9zIHZpdmllbmRvLCBsYSBudWV2YSB2YXJpYW50ZSBkZWwgQ292aWQtMTkgKE9taWNyb24pIGEgY2F1c2FkbyB1biBudWV2byBlc2NlbmFyaW8gZGUgaW5jZXJ0aWR1bWJyZSBxdWUgaGEgcHJvdm9jYWRvIGxhIGFwYXJpY2nDs24gZGUgbnVldmFzIHJlc3RyaWNjaW9uZXMgeSB1biBpbmNyZW1lbnRvIGVuIGVsIG51bWVybyBkZSBjYW5jZWxhY2lvbmVzLiBFc3RvIGxvIHBvZGVtb3Mgb2JzZXJ2YXIgZW4gbG9zIHR3ZWV0cyBzaWd1aWVudGVzLCBkb25kZSBzZSByZWNvZ2UgbG8gYW50ZXJpb3JtZW50ZSBjb21lbnRhZG8NCg0KDQo8YnI+DQoNCjo6OiBjb2x1bW5zDQo6Ojogey5jb2x1bW4gd2lkdGg9IjMyJSJ9DQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjYwJSJ9DQp0d2VldHJtZDo6dHdlZXRfZW1iZWQoImh0dHBzOi8vdHdpdHRlci5jb20vbWluY290dXJnb2Ivc3RhdHVzLzE0NzM2MzE5MDc3OTk4NzU1ODc/dD0wZlpERmtUOTNlTWFmZ0hLVHRXQWNRJnM9MDgiLCB0aGVtZSA9ICJsaWdodCIsIGFsaWduID0gImNlbnRlciIsIGRudCA9IFRSVUUsIG1heHdpZHRoID0gNDAwKQ0KYGBgDQo6OjoNCg0KOjo6IHsuY29sdW1uIHdpZHRoPSIxJSJ9DQo8IS0tIGFuIGVtcHR5IERpdiAod2l0aCBhIHdoaXRlIHNwYWNlKSBoYWNpZW5kbyBkZSBzZXBhcmFkb3IgLS0+DQo6OjoNCg0KOjo6IHsuY29sdW1uIHdpZHRoPSIzMiUifQ0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI2MCUifQ0KdHdlZXRybWQ6OnR3ZWV0X2VtYmVkKCJodHRwczovL3R3aXR0ZXIuY29tL0VQdHVyaXNtby9zdGF0dXMvMTQ3MzM4Mjc2NjUzMjIwMjUwMD90PUpWNkRkbFBFOWxiN1dxWHhYZDlGdncmcz0wOCIsIHRoZW1lID0gImxpZ2h0IiwgYWxpZ24gPSAiY2VudGVyIiwgZG50ID0gVFJVRSwgbWF4d2lkdGggPSA0MDApDQpgYGANCjo6Og0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjElIn0NCjwhLS0gYW4gZW1wdHkgRGl2ICh3aXRoIGEgd2hpdGUgc3BhY2UpIGhhY2llbmRvIGRlIHNlcGFyYWRvciAtLT4NCjo6Og0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjMyJSJ9DQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjYwJSJ9DQp0d2VldHJtZDo6dHdlZXRfZW1iZWQoImh0dHBzOi8vdHdpdHRlci5jb20vRVB0dXJpc21vL3N0YXR1cy8xNDczOTQyNTQxNTg2MzQxODkwIiwgdGhlbWUgPSAibGlnaHQiLCBhbGlnbiA9ICJjZW50ZXIiLCBkbnQgPSBUUlVFLCBtYXh3aWR0aCA9IDQwMCkNCmBgYA0KOjo6DQo6OjoNCg0KPGJyPg0KDQoNCkxhIHByaW5jaXBhbCAqKm1vdGl2YWNpw7NuKiogcGFyYSBsYSByZWRhY2Npw7NuIGRlIGVzdGUgYXJ0aWN1bG8gaGEgc2lkbzoNCg0KICAtIE9ic2VydmFyIGNvbW8gaGFuIGV2b2x1Y2lvbmFkbyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8gZWwgbsO6bWVybyBkZSB0dXJpc3RhcyBxdWUgaGFuIG9idGVuaWRvIGxhcyBlY29ub23DrWFzIGV1cm9wZWFzLCBwYXJhIHJlYWxpemFyIHVuYSBjb21wYXJhY2lvbiBwcmUgeSBwb3N0IGNyaXNpcyBzYW5pdGFyaWEuDQogIA0KICAtIEFuYWxpemFyIGNvbW8gc2UgZGlzdHJpYnV5ZSBwYXJ0ZSBkZWwgc2VjdG9yIHR1csOtc3RpY28gZW4gRXNwYcOxYSB5IGNvbW8gaGFuIHZhcmlhZG8gbG9zIGluZ3Jlc29zIHF1ZSBlc3RlIHJlY2liZSBlbiBsb3Mgw7psdGltb3MgYcOxb3MuDQoNCjxicj4NCg0KIyMgMy4gRGF0b3MgdXRpbGl6YWRvc3sudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCg0KIyMjIENvbWVudGFyaW9zDQoNClBhcmEgcG9kZXIgcmVhbGl6YXIgZWwgdHJhYmFqbywgbGEgb2J0ZW5jacOzbiBkZSB0b2RhIGxhIGluZm9ybWFjacOzbiByZWxldmFudGUgaGEgc2lkbyBhZHF1aXJpZGEgZW4gYmFzZXMgZGUgZGF0b3MgY29tbyAgZWwgSU5FIHkgRXVyb3N0YXQuDQoNClBhcmEgcG9kZXIgdXRpbGl6YXIgZXN0b3MgZGF0b3MgaGFuIHNpZG8gbmVjZXNhcmlvIG1vZGlmaWNhcmxvcyBhbnRlcyBkZSBhZGFwdGFybG9zIGEgbGFzIGdyw6FmaWNhcyBkZXNlYWRhcy4gRXN0ZSBwcm9jZWRpbWllbnRvIGxvIHBvZGVtb3MgZW5jb250cmFyIGRlbnRybyBkZWwgYXBhcnRhZG8gInRpZHkiLCBkb25kZSBwb2RlbW9zIG9ic2VydmFyIGRpY2hhcyBtb2RpZmljYWNpb25lcy4NCg0KDQpBZGVtw6FzLCBlbCBhcGFydGFkbyAicGFxdWV0ZXMiIHBvZGVtb3MgZW5jb250cmFyIGxvcyBwYXF1ZXRlcyBuZWNlc2FyaW9zIHBhcmEgbGEgZWxhYm9yYWNpw7NuIHRhbnRvIGRlIGVtcGxlYWRvcyBwYXJhIGxhIGxpbXBpZXphIGRlIGRhdG9zLCBjb21vIGxvcyB1dGlsaXphZG9zIHBhcmEgbGEgcmVhbGl6YWNpw7NuIGRlIGxvcyBkaWZlcmVudGVzIGdyw6FmaWNvcy4NCg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCiMjIyBUaWR5IA0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UgfQ0KDQp0dXJpc21vX2V1cm9wYSA8LSByZWFkX2V4Y2VsKCJkYXRvcy90dXJpc21vX2V1cm9wYS54bHN4IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGMoInRleHQiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQoibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIA0KIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQoibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIA0KIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQoibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIA0KIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQoibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIA0KIm51bWVyaWMiLCAibnVtZXJpYyIsICJudW1lcmljIiwgDQoibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIA0KIm51bWVyaWMiLCAibnVtZXJpYyIpKQ0KDQp0dXJpc21vX2V1cm9wYSA8LSB0dXJpc21vX2V1cm9wYSAlPiUgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjU5LCBuYW1lc190byA9ICJkYXRlIikNCg0KI3Jpbzo6ZXhwb3J0KHR1cmlzbW9fZXVyb3BhLCAiLi9kYXRvcy90dXJpc21vX2V1cm9wYS5jc3YiKQ0KDQp0dXJpc21vX2V1cm9wYSA8LSByZWFkX2NzdigiZGF0b3MvdHVyaXNtb19ldXJvcGEuY3N2IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKGRhdGUgPSBjb2xfZGF0ZShmb3JtYXQgPSAiJVkvJW0iKSkpDQoNCnR1cmlzbW9fZXVyb3BhJGNvZGUgPC0gdG9sb3dlcihjb3VudHJ5Y29kZSh0dXJpc21vX2V1cm9wYSRDb3VudHJ5LCBvcmlnaW4gPSAnY291bnRyeS5uYW1lJywgZGVzdGluYXRpb24gPSAnaXNvMmMnKSkNCg0KDQpgYGANCg0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UgfQ0KDQpnYXN0b190dXJpc3RpY29fZXNwIDwtIHJlYWRfZXhjZWwoImRhdG9zL2dhc3RvX3R1cmlzdGljb19lc3AueGxzIikNCg0KZ2FzdG9fdHVyaXN0aWNvX2VzcCA8LSBnYXN0b190dXJpc3RpY29fZXNwICU+JSBwaXZvdF9sb25nZXIoY29scyA9IDI6NTMsIG5hbWVzX3RvID0gImRhdGUiKSAlPiUgDQogIGRyb3BfbmEoKQ0KDQojcmlvOjpleHBvcnQoZ2FzdG9fdHVyaXN0aWNvX2VzcCwgIi4vZGF0b3MvZ2FzdG9fdHVyaXN0aWNvX2VzcC5jc3YiKQ0KDQpnYXN0b190dXJpc3RpY29fZXNwIDwtIHJlYWRfY3N2KCJkYXRvcy9nYXN0b190dXJpc3RpY29fZXNwLmNzdiIsIA0KICAgIGNvbF90eXBlcyA9IGNvbHMoZGF0ZSA9IGNvbF9kYXRlKGZvcm1hdCA9ICIlWS8lbSIpKSkNCg0KDQpnYXN0b19jb211bmlkYWRlc19hdXRvbm9tYXMgPC0gcmVhZF9leGNlbCgiZGF0b3MvZ2FzdG9fY29tdW5pZGFkZXNfYXV0b25vbWFzLnhscyIpDQoNCmdhc3RvX2NvbXVuaWRhZGVzX2F1dG9ub21hcyA8LSBnYXN0b19jb211bmlkYWRlc19hdXRvbm9tYXMgJT4lIHBpdm90X2xvbmdlcihjb2xzID0gMjo1MSwgbmFtZXNfdG8gPSAiZGF0ZSIpICU+JSANCiAgYXJyYW5nZShkYXRlKQ0KDQojcmlvOjpleHBvcnQoZ2FzdG9fY29tdW5pZGFkZXNfYXV0b25vbWFzLCAiLi9kYXRvcy9nYXN0b19jb211bmlkYWRlc19hdXRvbm9tYXMuY3N2IikNCg0KZ2FzdG9fY29tdW5pZGFkZXNfYXV0b25vbWFzIDwtIHJlYWRfY3N2KCJkYXRvcy9nYXN0b19jb211bmlkYWRlc19hdXRvbm9tYXMuY3N2IiwgDQogICAgY29sX3R5cGVzID0gY29scyhkYXRlID0gY29sX2RhdGUoZm9ybWF0ID0gIiVZLyVtIikpKQ0KDQpnYXN0b190dXIgPC0gZnVsbF9qb2luKGdhc3RvX2NvbXVuaWRhZGVzX2F1dG9ub21hcywgZ2FzdG9fdHVyaXN0aWNvX2VzcCwgYnkgPSBjKCJsb2NhdGlvbiIgPSAibG9jYXRpb24iLCAiZGF0ZSIgPSAiZGF0ZSIsICJ2YWx1ZSIgPSAidmFsdWUiKSkNCg0KYGBgDQoNCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFIH0NCg0KQ0NBQSA8LSByaW86OmltcG9ydCgiaHR0cHM6Ly9naXRodWIuY29tL3BlcmV6cDQ0L2FyY2hpdm9zX2Rvd25sb2FkLjIvcmF3L21haW4vQ0NBQS5yZHMiKQ0KDQpsb2FkKGhlcmU6OmhlcmUoImRhdG9zIiwgImdlb21ldHJpYXNfQmlnRGF0YV8yMDIxLlJEYXRhIikpDQoNCiMgUGFyYSBsYSByZWFsaXphY2nDs24gZGVsIG1hcGEgZGUgRXNwYcOxYSBlcyBuZWNlc2FyaW8gbGEgZGVzY2FyZ2EgZGUgdW5hcyBnZW9tZXRyw61hcyBxdWUgbm8gaGFuIHBvZGlkbyBzZXIgZGVwb3NpdGFkYXMgZW4gZWwgcmVwb3NpdG9yaW8gcG9yIHN1IHRhbWHDsW8gc3VwZXJpb3IgYSAyNU1CLCBwb3IgZWxsbyBwb25nbyBhIHZ1ZXN0cmEgZGlzcG9zaWNpw7NuIGVsIGVubGFjZSBzaWd1aWVudGUgZWwgY3VhbCBub3MgcmVkaXJpZ2UgYWwgcGFxdWV0ZSBkZSBkaWNoYXMgZ2VvbWV0cmlhcywgaHR0cHM6Ly9naXRodWIuY29tL3JPcGVuU3BhaW4vTEFVMmJvdW5kYXJpZXM0c3BhaW4NCg0KYGBgDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQoNCm5faG90ZWxlcyA8LSByZWFkX2V4Y2VsKCJkYXRvcy9uX2hvdGVsZXMueGxzeCIpDQoNCmNhdGVnb3JpYXMgPC0gcmVhZF9leGNlbCgiZGF0b3MvY2F0ZWdvcmlhcy54bHN4IikNCg0KYGBgDQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMjIFBhcXVldGVzDQoNCiAtIGxpYnJhcnkodGlkeXZlcnNlKQ0KIC0gbGlicmFyeShyZWFkcikNCiAtIGxpYnJhcnkocmVhZHhsKQ0KIC0gbGlicmFyeShyaW8pDQogLSBsaWJyYXJ5KGdncGxvdDIpDQogLSBsaWJyYXJ5KHBsb3RseSkNCiAtIGxpYnJhcnkodHJlZW1hcCkNCiAtIGxpYnJhcnkoRFQpDQogLSBsaWJyYXJ5KGd0KQ0KIC0gbGlicmFyeShnZ2FuaW1hdGUpDQogLSBsaWJyYXJ5KGNvdW50cnljb2RlKQ0KIC0gbGlicmFyeShnZ2ZsYWdzKQ0KIC0gb3B0aW9ucyhzY2lwZW4gPSA5OTkpIA0KIC0gcGFjbWFuOjpwX2xvYWQoa25pdHIsIGhlcmUsIHRpZHl2ZXJzZSwgcGF0Y2h3b3JrLCBnZ3JlcGVsKQ0KIC0gcGFjbWFuOjpwX2xvYWQoc2YsIHJuYXR1cmFsZWFydGgsIHJuYXR1cmFsZWFydGhkYXRhKQ0KIC0gbGlicmFyeShwanB2LmRhdG9zLjAxKQ0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCjxicj4NCg0KIyMgNCBFc3R1ZGlvIGRlbCB0dXJpc21vIGVuICoqRXVyb3BhKioNCg0KRXVyb3BhIGVzIHVubyBkZSBsb3MgcHJpbmNpcGFsZXMgZGVzdGlub3MgdHVyw61zdGljb3MgYSBuaXZlbCBtdW5kaWFsLCBqdWdhbmRvIGVzdGEgYWN0aXZpZGFkIHVuIHBhcGVsICBpbXBvcnRhbnRlIGVuIHRvZGFzIGxhcyBlY29ub23DrWFzIGRlc2Fycm9sbGFkYXMsIHBlcm8gc29icmUgdG9kbyBlbiBhcXVlbGxhcyBtZW5vcyBkZXNhcnJvbGxhZGFzIGRvbmRlIGVzdGUgc3Vwb25lIHVuIGluY3JlbWVudG8gZW4gbGEgb2N1cGFjacOzbiAoc29icmUgdG9kbyBlbiBwZXJvc25hcyBqb3ZlbmVzKSB0ZW5pZW5kbyB1bmEgc2VyaWUgZGUgZWZlY3RvcyBiaWxhdGVyYWwgcXVlIGJlbmVmaWNpYW4gYSBsYSBlY29ub23DrWEgZW4gZ2VuZXJhbC4gDQoNClBvciBlbGxvLCBlbCBGb25kbyBkZSBEZXNhcnJvbGxvIFJlZ2lvbmFsIChGRURFUikgZm9tZW50YSBsYSBpbnZlcnNpw7NuIHBhcmEgbWVqb3JhciBsYSBjb21wZXRpdGl2aWRhZCB5IHNvc3RlbmliaWxpZGFkIGRlbCB0dXJpc21vLCBiZW5lZmljaWFuZG8gYXPDrSBhIGxvcyBwYWlzZXMgZSBpbmNlbnRpdmFuZG9sb3MgYSBpbm5vdmFyIHkgbWVqb3JhciBsb3Mgc2VydmljaW9zIG9mcmVjaWRvcy4NCg0KPGJyPg0KDQojIyMgNC4xIEV2b2x1Y2nDs24gZGVsIHR1cmlzbW8gKDIwMTctMjAyMSkgDQoNCiMjIyMgNC4xLjEgVGVuZGVuY2lhIGRlbCB0dXJpc21vIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyMjIFRlbmRlbmNpYSANCg0KRW4gcHJpbWVyIGx1Z2FyLCBwb2RlbW9zIG9ic2VydmFyIGNvbW8gaGEgZXZvbHVjaW9uYWRvIGxhIGxsZWdhZGEgZGUgdHVyaXN0YXMgYSBsb3MgZGlmZXJlbnRlcyBwYWlzZXMgZXVyb3Blb3MsIGhhY2llbmRvIGluY2FwaWUgZW4gZWwgY29tcHV0byBnbG9iYWwgcXVlIHJlY2liZSAqKkV1cm9wYSoqIHkgcmVtYXJjYW5kbyBsYSBjb250cmlidWNpw7NuIGRlICoqRXNwYcOxYSoqIGVuIGVsbG8uDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQpwMWEgPC0gdHVyaXNtb19ldXJvcGEgJT4lIGZpbHRlcihDb3VudHJ5ICVpbiUgYygiRXVyb3BlYW5fVW5pb24iKSkNCnAxYiA8LSB0dXJpc21vX2V1cm9wYSAlPiUgZmlsdGVyKENvdW50cnkgJWluJSBjKCJTcGFpbiIpKQ0KcDEgPC0gdHVyaXNtb19ldXJvcGEgDQoNCnAgPC0gZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHAxLCBhZXMoZGF0ZSwgdmFsdWUvMTBeNiwgY29sb3VyID0gQ291bnRyeSksIGFscGhhID0gMC4zKSArDQogIGdlb21fbGluZShkYXRhID0gcDFhLCBhZXMoZGF0ZSwgdmFsdWUvMTBeNiksIGNvbG9yID0gIiMwMjg4ZDEiLCBzaXplID0gMS4yKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IHAxYSwgYWVzKGRhdGUsIHZhbHVlLzEwXjYpLCBjb2xvciA9ICIjMDI4OGQxIiwgc2l6ZSA9IDEuNSkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHAxYiwgYWVzKGRhdGUsIHZhbHVlLzEwXjYpLCBjb2xvciA9ICIjYjcxYzFjIiwgc2l6ZSA9IDEuMikgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBwMWIsIGFlcyhkYXRlLCB2YWx1ZS8xMF42KSwgY29sb3IgPSAiI2I3MWMxYyIsIHNpemUgPSAxLjUpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwNCiAgICAgICAgICAgICBzaXplID0gMSwNCiAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscz0iJVktJW0iLGRhdGVfYnJlYWtzICA9IjMgbW9udGhzIikrDQogIA0KICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgIHhtaW4gPSBhcy5EYXRlKCIyMDIwLTAzLTAxIiksDQogICAgICAgICAgIHhtYXggPSBhcy5EYXRlKCIyMDIwLTA1LTAxIiksDQogICAgICAgICAgIHltaW4gPSAtSW5mLA0KICAgICAgICAgICB5bWF4ID0gSW5mLA0KICAgICAgICAgICBhbHBoYSA9IDAuNCwNCiAgICAgICAgICAgZmlsbCA9ICJwaW5rIikgKw0KICBhbm5vdGF0ZShnZW9tID0gImxhYmVsIiwNCiAgICAgICAgICAgeD0gYXMuRGF0ZSgiMjAyMS0xMC0wMSIpLA0KICAgICAgICAgICB5ID0gNTUsDQogICAgICAgICAgIGxhYmVsID0gIkV1cm9wYSIsDQogICAgICAgICAgIHNpemUgPSA0LA0KICAgICAgICAgICBjb2xvciA9ICIjMDI4OGQxIikgICsNCiAgYW5ub3RhdGUoZ2VvbSA9ICJsYWJlbCIsDQogICAgICAgICAgIHg9IGFzLkRhdGUoIjIwMjEtMTAtMDEiKSwNCiAgICAgICAgICAgeSA9IDE1LA0KICAgICAgICAgICBsYWJlbCA9ICJFc3Bhw7FhIiwNCiAgICAgICAgICAgc2l6ZSA9IDQsDQogICAgICAgICAgIGNvbG9yID0gIiNiNzFjMWMiKSAgKw0KICANCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA3MCwgaGp1c3QgPSAxKSkgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAic2VyaWYiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgK2xhYnMoeCA9IE5VTEwsIHkgPSAiVHVyaXNtbyIsIHN1YnRpdGxlID0gIkRhdG9zIGV4cHJlc2Fkb3MgZW4gbWlsbG9uZXMgZGUgcGVyc29uYXMgIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTpFbGFib3JhY2nDs24gcHJvcGlhIGNvbiBkYXRvcyBkZWwgRXVyb2VzdGF0LiIpDQogIA0KDQpgYGANCg0KPGNlbnRlcj48aW1nIHNyYz0iaW1hZ2VuZXMvUnBsb3QucG5nIiB3aWR0aCA9ICIxMDAwcHgiIC8+PC9jZW50ZXI+DQoNCjxicj4NCg0KQ29tbyBwb2RlbW9zIG9ic2VydmFyIGVuIGVsIGdyw6FmaWNvLCBsYSBsbGVnYWRhIGRlIHR1cmlzdGFzIHByZXNlbnRhIHVuYSBmdWVydGUgKip0ZW1wb3JhbGlkYWQqKiwgdGVuaWVuZG8gc3UgcGljbyBtw6FzIGVsZXZhZG8gZW4gbG9zIG1lc2VzIGRlIGp1bGlvIHkgYWdvc3RvLiBFc3RvIGRlYmlkbyBhbCBkZXNwbGF6YW1pbmV0byBkZSBsYSBwb2JsYWNpw7NuIGhhY2lhIHBhaXNlcyBjb21vIEVzcGHDsWEgbyBJdGFsaWEgcXVlIGVuIGVzdGUgw6lwb2NhIGRlbCBhw7FvIHNlIGNhcmFjdGVyaXphbiBwb3Igc3UgYnVlbiBjbGltYSB5IGdyYW4gb2ZlcnRhIGRlIHR1cmlzbW8gZGUgc29sIHkgcGxheWEuDQoNCk90cm8gZGF0byBhIGRlc3RhY2FyIGVzIHF1ZSBlbiBsYSDDqXBvY2EgKipwcmUtcGFuZGVtaWEqKiBlbCBtw6F4aW1vIGRlIGNhZGEgYcOxbyBzdXBlcmFiYSBhbCBkZWwgYW50ZXJpb3IsIHRlbmRlbmNpYSBxdWUgc2Ugcm9tcGUgdHJhcyBsYSBncmFuIGNhaWRhIHF1ZSBodWJvIGVuIG1hcnpvIGRlIDIwMjAsIGEgY2F1c2EgZGVsIENPVklELTE5IHkgbGFzIHRyYXZhcyBxdWUgc3VwdXNvIHBhcmEgZWwgZGVzcGxhemFtaWVudG8gZGUgbGEgcG9ibGFjacOzbiAoIGNvbmZpbmFtaWVudG9zLCBpbXBvc2liaWxpZGFkIGRlIHZpYWphci4uLiksIGhlY2hvIHF1ZSBhIG1hcmNhZG8gdW4gYW50ZXMgeSBkZXNwdWVzLCB5YSBxdWUsIGFkZW3DoXMgZGUgcXVlIGxhIHRlbXBvcmFsaWRhZCBzZSBoYSBpbmNyZW1lbnRhZG8geSBwcm9sb25nYWRvIGVuIGVsIHRpZW1wbywgYXVuIG5vIGhlbW9zIHJlY3VwZXJhZG8gbG9zIG5pdmVsZXMgcHJldmlvcyBhIGxhIGNyaXNpcyBzYW5pdGFyaWEsIGF1bnF1ZSBzZSBwdWVkZSBvYnNlcnZhciBjb21vIGVzdGFtb3MgY2FtaW5vIGEgbG9ncmFybG8geWEgcXVlIGVsIHBpY28gZGUgZXN0ZSBhw7FvIHN1cGVyYSBhbCBwcmVkZWNlc29yLiANCg0KUGFyYSBtw6FzIGRldGFsbGUgZGUgY29tbyBoYW4gZXZvbHVjaW9uYWRvIHRvZGFzIGxhcyBlY29ub23DrWFzIHB1ZWRlIGNvbnN1bHRhciBsYSAqKnRhYmxhKiouDQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQo8YnI+DQoNCg0KIyMjIyMgVGFibGEgDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgd2FybmluZz0gRkFMU0V9DQogIA0KZGF0YXRhYmxlKHR1cmlzbW9fZXVyb3BhLCBjbGFzcyA9InN0cmlwZSBob3ZlciBjb21wYWN0IHJvdy1ib3JkZXIiICwgZmlsdGVyID0gJ3RvcCcpDQoNCmBgYA0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KPGJyPg0KDQojIyMjIDQuMS4yIMK/UXVlIHBhaXNlcyByZWNpYmVuIHVuIG1heW9yIG7Dum1lcm8gZGUgdHVyaXN0YXM/IHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyMjIEp1bGlvDQoNCkNvbW8gaGUgbWVuY2lvbmFkbyBlbiBlbCBhcGFydGFkbyBhbnRlcmlvciwgbG9zIG1lc2VzIGRvbmRlIGhheSBtYXlvciBhZmx1ZW5jaWEgZGUgdHVyaXN0YXMgc29uICoqanVsaW8qKiB5ICoqYWdvc3RvKiosIHBvciBlbGxvIGVuIGxvcyBncmFmaWNvcyBzaWd1aW50ZXMgdmFtb3MgYSBvYnNlcnZhciBxdWUgcGFpc2VzIHJlY2liaWVyb24gdW4gbWF5b3IgbsO6bWVybyBkZSB2aXNpdGFudGVzIGVuIGRpY2hvcyBtZXNlcyBlbiBlbCBwZXJpb2RvICoqMjAxNy0yMDIwKiogKHZlciBwZXN0YcOxYSAqKmFnb3N0byoqKS4gDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQp0dXJpc21vX2JhcnJhczEgPC0gdHVyaXNtb19ldXJvcGEgJT4lIA0KICBmaWx0ZXIoQ291bnRyeSAhPSAiRXVyb3BlYW5fVW5pb24iKSAlPiUgDQogIGdyb3VwX2J5KGRhdGUpICU+JSANCiAgYXJyYW5nZShkYXRlLCBkZXNjKHZhbHVlKSkgJT4lIA0KICBtdXRhdGUocmFua2luZyA9IHJvd19udW1iZXIoKSkgJT4lDQogIGZpbHRlcihyYW5raW5nIDw9NSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBmaWx0ZXIoZGF0ZSA9PSAiMjAxNy0wNy0wMSIgfCBkYXRlID09ICIyMDE4LTA3LTAxIiB8IGRhdGUgPT0gIjIwMTktMDctMDEiIHwgZGF0ZSA9PSAiMjAyMC0wNy0wMSIpDQoNCg0KDQphMTEgPC0gZ2dwbG90KHR1cmlzbW9fYmFycmFzMSwgYWVzKHJhbmtpbmcsIHZhbHVlKSwgc2l6ZSA9IDIwKSArDQogIGdlb21fY29sKGFlcyhyYW5raW5nLCB2YWx1ZSwgZmlsbCA9IENvdW50cnkpKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MyIpICsNCiAgc2NhbGVfeF9yZXZlcnNlKCkgKw0KICBjb29yZF9mbGlwKGNsaXAgPSAib2ZmIiwgZXhwYW5kID0gRkFMU0UpICsNCiAgdGhlbWVfbGlnaHQoKSArDQogIGZhY2V0X3dyYXAoDQogICAgdmFycyhkYXRlKSwgbnJvdyA9IDIsIG5jb2wgPSAyKSArIA0KICANCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSkgKw0KICBsYWJzKHkgPSAiVHVyaXNtbyIsIHN1YnRpdGxlID0gIk3DoXhpbW8gdHVyaXNtbyBlbiBhZ29zdG8gIiwNCiAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSBjb24gZGF0b3MgZGVsIEV1cm9lc3RhdCAiKSArDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIikpICsgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QobGluZXR5cGUgPSAic29saWQiKSkgDQoNCmExMSA8LSBnZ3Bsb3RseShhMTEpDQoNCmExMQ0KDQpgYGANCg0KVW5hIHZleiB2aXN0YXMgYW1iYXMgcGVzdGHDsWFzLCBwb2RlbW9zIGNvbmNsdWlyIGNvbiBxdWUgbG9zIHBhaXNlcyBjb24gdW5hIG1heW9yIGFmbHVlbmNpYSB0dXLDrXN0aWNhIHNvbiAqKkZyYW5jaWEqKiwgKipBbGVtYW5pYSoqLCAqKlJlaW5vIFVuaWRvKiosICoqSXRhbGlhKiogeSAqKkVzcGHDsWEqKiwgZXN0YW5kbyBlc3RvcyBzaW1lcHJlIGVuIGVsIHRvcCA1IGRlIGVjb25vbcOtYXMgZXN0dWRpYWRhcyBtYW50ZW5pZW5kbyBlbiBsYSBtYXlvcmlhIGRlIGNhc29zIHN1IHBvc2ljacOzbiBlbiBlc3RlIHRvcC4NCg0KVW4gZmFjdG9yIGEgZGVzdGFjYXIsIGVzIHF1ZSBhIHBlc2FyIGRlIHNlciBsYXMgcmVmZXJlbnRlcyBlbiBlbCBhbWJpdG8gdHVyw61zdGljbyBldXJvcGVvLCB0b2RhcyBlbGxhcyB2aWVyb24gZGlzbWludWlyIGVuIGNpZXJ0YSBtZWRpZGEgZWwgbnVtZXJvIGRlIHR1cmlzdGFzIHJlY2liaWRvIGVuIDIwMjAsIGhlY2hvIHF1ZSBjb25jdWVyZGEgY29uIGxhIGNvbmNsdXNpb24gZGVsIGNvbXB1dG8gZ2xvYmFsIGRlIEV1cm9wYSBkZWwgcHJpbWVyIGFwYXJ0YWRvLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSANCg0KPGJyPg0KDQoNCiMjIyMjIEFnb3N0byANCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFIH0NCnR1cmlzbW9fYmFycmFzIDwtIHR1cmlzbW9fZXVyb3BhICU+JSANCiAgZmlsdGVyKENvdW50cnkgIT0gIkV1cm9wZWFuX1VuaW9uIikgJT4lIA0KICBncm91cF9ieShkYXRlKSAlPiUgDQogIGFycmFuZ2UoZGF0ZSwgZGVzYyh2YWx1ZSkpICU+JSANCiAgbXV0YXRlKHJhbmtpbmcgPSByb3dfbnVtYmVyKCkpICU+JQ0KICBmaWx0ZXIocmFua2luZyA8PTUpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgZmlsdGVyKGRhdGUgPT0gIjIwMTctMDgtMDEiIHwgZGF0ZSA9PSAiMjAxOC0wOC0wMSIgfCBkYXRlID09ICIyMDE5LTA4LTAxIiB8IGRhdGUgPT0gIjIwMjAtMDgtMDEiKQ0KDQoNCg0KYTEgPC0gZ2dwbG90KHR1cmlzbW9fYmFycmFzLCBhZXMocmFua2luZywgdmFsdWUpLCBzaXplID0gMjApICsNCiAgZ2VvbV9jb2woYWVzKHJhbmtpbmcsIHZhbHVlLCBmaWxsID0gQ291bnRyeSkpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQzIikgKw0KICBzY2FsZV94X3JldmVyc2UoKSArDQogIGNvb3JkX2ZsaXAoY2xpcCA9ICJvZmYiLCBleHBhbmQgPSBGQUxTRSkgKw0KICB0aGVtZV9saWdodCgpICsNCiAgZmFjZXRfd3JhcCgNCiAgICB2YXJzKGRhdGUpLCBucm93ID0gMiwgbmNvbCA9IDIpICsgDQogIA0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpKSArDQogIGxhYnMoeSA9ICJUdXJpc21vIiwgc3VidGl0bGUgPSAiTcOheGltbyB0dXJpc21vIGVuIGFnb3N0byAiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGNvbiBkYXRvcyBkZWwgRXVyb2VzdGF0ICIpICsNCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAid2hpdGUiKSkgKyANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChsaW5ldHlwZSA9ICJzb2xpZCIpKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KYTEgPC0gZ2dwbG90bHkoYTEpDQoNCmExDQoNCmBgYA0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gDQoNCiMjIyMgNC4xLjMgwr9BIHF1aWVuIGxlIGFmZWN0byBtw6FzIGxhIGNyaXNpcyBzYW5pdGFyaWE/IHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIyMjIEN1YWRyb3MgDQoNCkVuIGVzdG9zIGRvcyBjdWFkcm9zIHBvZGVtb3Mgb2JzZXJ2YXIgY29tbyBhIGxhIGVjb25vbcOtYSBkZSBTbG92ZW5pYSBubyBsZSBhZmVjdG8gZGUgZm9ybWEgc2lnbmlmaWNhdGl2YW1lbnRlIG5lZ2F0aXZhIGxhIGNyaXNpcyBzYW5pdGFyaWEsIHNpbm8gdG9kbyBsbyBjb250cmFyaW8sIHlhIHF1ZSBlbCBuaXZlbCBkZSB0dXJpc21vIHJlc3BlY3RvIGFsIG1lcyBkZSBhZ29zdG8gZGVsIGHDsW8gYW50ZXJpb3Igc2UgdmnDsyBpbmNyZW1lbmV0YWRvLiANCg0KU2luIGVtYWJhcmdvLCBlbCBwYWlzIG1hcyBhZmVjdGFkbyBmdWUgTGllY2h0ZW5zdGVpbiwgZG9uZGUgZWwgdHVyaXNtbyBlbiBhZ29zdG8gZGlzbWludXnDsyBlbiB1biA1MCUgcmVzcGVjdG8gYWwgYcOxbyBkZSBhbnRlcmlvci4gDQoNClNpIHNlIGRlc2VhIHNhYmVyIGNvbW8gZXZvbHVjaW9uw7MgY2FkYSBlY29ub23DrWEgbG8gcHVlZGUgb2JzZXJ2YXIgZW4gbGEgKip0YWJsYSoqLg0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjQ3JSJ9DQoNCmBgYHtyfQ0KDQoNCmltcGFjdG8gPC0gdHVyaXNtb19ldXJvcGEgJT4lIGZpbHRlcihkYXRlID09ICIyMDE5LTA4LTAxIiB8IGRhdGUgPT0gIjIwMjAtMDgtMDEiKQ0KDQppbXBhY3RvIDwtIGltcGFjdG8gJT4lIGZpbHRlcihDb3VudHJ5ICE9ICJFdXJvcGVhbl9VbmlvbiIpICU+JSANCiAgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIA0KICBtdXRhdGUoY3JlY2ltaWVudG8gPSB2YWx1ZSAtIGxhZyh2YWx1ZSkpICU+JSANCiAgbXV0YXRlKGluY3JlbWVudG8gPSBjcmVjaW1pZW50byAvIGZpcnN0KHZhbHVlKSAqIDEwMCApICU+JSANCiAgdW5ncm91cCgpDQoNCm1heCA8LSBpbXBhY3RvICU+JSBzbGljZV9tYXgoaW5jcmVtZW50bywgbiA9IDEpICU+JSANCiAgc2VsZWN0KENvdW50cnksIGluY3JlbWVudG8pDQoNCm1pbiA8LSBpbXBhY3RvICU+JSBzbGljZV9taW4oaW5jcmVtZW50bywgbiA9IDEpICU+JSANCiAgc2VsZWN0KENvdW50cnksIGluY3JlbWVudG8pDQogIA0KICANCiAgDQpiYW5kZXJhX21heCA8LSBjKCJodHRwOi8vYmFuZGVyYXNtdW5kby5lcy9iYW5kZXJhcy9lc2xvdmVuaWEucG5nIikNCg0KDQptYXhfaW5jIDwtIG1heCAlPiUgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIA0KICBhZGRfY29sdW1uKGJhbmRlcmFfbWF4KSAlPiUgdW5ncm91cCgpDQoNCg0KVGFibGFfbWF4IDwtIG1heF9pbmMgJT4lIGd0KCkNCg0KVGFibGFfbWF4IDwtIFRhYmxhX21heCAlPiUNCiAgdGFiX2hlYWRlcih0aXRsZSA9IG1kKCIqKlBhw61zIG1lbm9zIHBlcmp1ZGljYWRvKioiKSxzdWJ0aXRsZSA9IG1kKCJBIGZlY2hhOiAwMS0wOC0yMDIwIikpDQoNClRhYmxhX21heCA8LSBUYWJsYV9tYXggJT4lDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICIjZmZiNzRkIikgJT4lIHRhYl9vcHRpb25zKGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMTUsIGhlYWRpbmcuc3VidGl0bGUuZm9udC5zaXplID0gMTMsICBjb2x1bW5fbGFiZWxzLmZvbnQud2VpZ2h0ID0gICJib2xkIikNCg0KDQpUYWJsYV9tYXggPC0gVGFibGFfbWF4ICAlPiUNCiAgZ3Q6OnRleHRfdHJhbnNmb3JtKGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IHZhcnMoYmFuZGVyYV9tYXgpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OndlYl9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgIGNvbHNfYWxpZ24oDQogICAgYWxpZ24gPSAiY2VudGVyIikNCg0KVGFibGFfbWF4DQoNCmBgYA0KDQo6OjoNCg0KOjo6IHsuY29sdW1uIHdpZHRoPSIxJSJ9DQo8IS0tIGFuIGVtcHR5IERpdiAod2l0aCBhIHdoaXRlIHNwYWNlKSBoYWNpZW5kbyBkZSBzZXBhcmFkb3IgLS0+DQo6OjoNCg0KOjo6IHsuY29sdW1uIHdpZHRoPSI0NyUifQ0KDQoNCmBgYHtyfQ0KDQpiYW5kZXJhX21pbiA8LSBjKCJodHRwOi8vYmFuZGVyYXNtdW5kby5lcy9iYW5kZXJhcy9saWVjaHRlbnN0ZWluLnBuZyIpDQoNCg0KbWluX2luYyA8LW1pbiAlPiUgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIA0KICBhZGRfY29sdW1uKGJhbmRlcmFfbWluKSAlPiUgdW5ncm91cCgpDQoNCg0KDQpUYWJsYV9taW4gPC0gbWluX2luYyAlPiUgZ3QoKQ0KDQpUYWJsYV9taW4gPC0gVGFibGFfbWluICU+JQ0KICB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqUGFpcyBtw6FzIHBlcmp1ZGljYWRvKioiKSxzdWJ0aXRsZSA9IG1kKCJBIGZlY2hhOiAwMS0wOC0yMDIwIikpDQoNClRhYmxhX21pbiA8LSBUYWJsYV9taW4gJT4lDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICIjZmZiNzRkIikgJT4lIHRhYl9vcHRpb25zKGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMTUsIGhlYWRpbmcuc3VidGl0bGUuZm9udC5zaXplID0gMTMsICBjb2x1bW5fbGFiZWxzLmZvbnQud2VpZ2h0ID0gICJib2xkIikNCg0KDQpUYWJsYV9taW4gPC0gVGFibGFfbWluICAlPiUNCiAgZ3Q6OnRleHRfdHJhbnNmb3JtKGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IHZhcnMoYmFuZGVyYV9taW4pKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OndlYl9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgIGNvbHNfYWxpZ24oDQogICAgYWxpZ24gPSAiY2VudGVyIikNCg0KVGFibGFfbWluDQoNCmBgYA0KDQo6OjoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQojIyMjIyBUYWJsYQ0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UgfQ0KDQppbXBhY3RvX3RhYmxhIDwtIGltcGFjdG8gJT4lIHNlbGVjdChDb3VudHJ5LCBkYXRlLCBpbmNyZW1lbnRvKSAlPiUgDQogIGRyb3BfbmEoKQ0KDQpkYXRhdGFibGUoaW1wYWN0b190YWJsYSwgY2xhc3MgPSJzdHJpcGUgaG92ZXIgY29tcGFjdCByb3ctYm9yZGVyIiAsIGZpbHRlciA9ICd0b3AnKQ0KDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMjIDQuMiBJbW9ydGFuY2lhIGRlIGNhZGEgcGHDrXMgZW4gbGEgYWN0dWFsaWRhZCANCg0KIyMjIyA0LjIuMSBUcmVlbWFwDQoNCkEgdHJhdmVzIGRlIGVzdGUgdHJlZW1hcCBwb2RlbW9zIGNvbmNsdWlyIGxvIHF1ZSBkZWNpYW1vcyB5YSBlbiBhcGFydGFkb3MgYW50ZXJpb3JlcywgbG9zIHBhaXNlcyBjb24gdW5hIG1heW9yIG51bWVybyBkZSB0dXJpc3RhcyBlbiBBZ29zdG8gZGUgMjAyMSBzaWd1ZW4gc2llbmRvIEFsZW1hbmlhLCBJYXRsaWEgeSBFc3Bhw7FhLiANCkVzdGUgaGVjaG8gbm8gc29ycHJlbmRlIHlhIHF1ZSBlcyB1bmEgY29udGludWFjacOzbiBkZSBsYSAqKnRlbmRlbmNpYSoqIGFudGVyaW9ybWVudGUgZGVzY3JpdGEsIHNpbiBlbWJhcmdvIGNhYmUgZGVzdGFjYXIgcXVlIGVsIG7Dum1lcm8gZGUgcGVyc29uYXMgcXVlIGRlY2lkaWVyb24gZGVzcGxhemFyc2UgZXN0ZSBhw7FvIGhhIHN1cGVyYWRvIGFsIHByZWRlY2Vzb3IsIGNvbW8gc2UgcHVlZGUgb2JzZXJ2YXIgdGFudG8gZW4gZWwgZ3LDoWZpY28gY29tbyBlbiBsYSB0YWJsYSBkZWwgcHJpbWVyIGFwYXJ0YWRvLCBzaWVuZG8gZXN0byBjb25zZWN1ZW5jaWEgZGUgbGEgbWVqb3JhIGRlIGxhIGNyaXNpcyBzYW5pdGFyaWEgcG9yIGVsIGdyYW4gYXZhbmNlIGVuIGxhIHZhY3VuYWNpw7NuIGNvbnRyYSBlbCBjb3ZpZCwgcXVlIGhhIHBlcm1pdGlkbyBsYSBlbGltaW5hY2nDs24gZGUgbnVtZXJvc2FzIHJlc3RyaWNjaW9uZXMuDQoNCipFbCBoZWNobyBkZSBxdWUgbm8gYXBhcmV6Y2FuIHBhaXNlcyBjb21vIEZyYW5jaWEgeSBSZWlubyBVbmlkbyBzZSBkZWJlIGEgbGEgZmFsdGEgZGUgZGF0b3MgZW4gZWwgRXVyb3N0YXQgZGUgZXN0b3MgcGFpc2VzIHBhcmEgZWwgcGVyaWRvIGVzdHVkaWFkbyBkZSAyMDIxLioNCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFIH0NCnAyIDwtIHR1cmlzbW9fZXVyb3BhICU+JSBmaWx0ZXIoZGF0ZSA9PSAiMjAyMS0wOC0wMSIpICU+JSANCiAgZmlsdGVyKENvdW50cnkgIT0gIkV1cm9wZWFuX1VuaW9uIikgJT4lIA0KICBzbGljZV9tYXgodmFsdWUsIG4gPTE1KQ0KICANCg0KDQpwMiA8LSB0cmVlbWFwKHAyLA0KICAgICAgICAgICAgICBpbmRleD0iQ291bnRyeSIsDQogICAgICAgICAgICAgIHZTaXplPSJ2YWx1ZSIsDQogICAgICAgICAgICAgIHR5cGU9ImluZGV4IiwNCiAgICAgICAgICAgICAgdGl0bGU9IlR1cmlzbW8gZW4gbGEgVUUgKEFnb3N0byAyMDIxKSIsDQogICAgICAgICAgICAgIHBhbGV0dGU9IlNldDMiLA0KICAgICAgICAgICAgICBib3JkZXIuY29sPWMoIndoaXRlIiksIA0KICAgICAgICAgICAgICBib3JkZXIubHdkcz0zLCANCiAgICAgICAgICAgICAgZm9udGZhY2UubGFiZWxzPTEsDQogICAgICAgICAgICAgIGJnLmxhYmVscz1jKCJ0cmFuc3BhcmVudCIpLCAgICAgICAgICAgICAgDQogICAgICAgICAgICAgIGFsaWduLmxhYmVscz1jKCJjZW50ZXIiLCAiY2VudGVyIiksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcmxhcC5sYWJlbHM9MC41KQ0KDQoNCmBgYA0KDQo8YnI+DQoNCg0KIyMjIyA0LjIuMiBHcsOhZmljbyBkZSBiYXJyYXMgDQoNCkFxdcOtIHBvZGVtb3Mgb2JzZXJ2YXIgbG8gYW50ZXJpb3JtZW50ZSBkZXNjcml0bywgbGFzIHByaW5jaXBhbGVzIGVjb25vbcOtYXMgc3VlbGVuIHNlciBzaWVtcHJlIGxhcyBtaXNtYXMsIHByZXNlbnRhbmRvIHBvciB1bmEgcGFydGUgdG9kYXMgbGEgbWlzbWEgdGVtcG9yYWxpZGFkIChyZWZsZWphZGEgZW4gbGEgZGlzbWludWNpw7NuIGRlbCBudW1lcm8gZGUgdHVyaXN0YXMgZW4gbG9zIG1pc21vcyBtZXNlcykgeSBwb3Igb3RyYSwgbGEgZGlzbWludWNpw7NuIGRlIHR1cmlzdGFzIHBvciBlbCBDT1ZJRC0xOS4gDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQoNCmJhcnJhcyA8LSB0dXJpc21vX2V1cm9wYSAlPiUgDQogIGZpbHRlciggQ291bnRyeSAhPSAiRXVyb3BlYW5fVW5pb24iKQ0KDQpiYXJyYXMgIDwtIGJhcnJhcyAgJT4lIA0KICBncm91cF9ieShkYXRlKSAlPiUgDQogIGFycmFuZ2UoZGF0ZSwgZGVzYyh2YWx1ZSkpICU+JSANCiAgbXV0YXRlKHJhbmtpbmcgPSByb3dfbnVtYmVyKCkpICU+JQ0KICBmaWx0ZXIocmFua2luZyA8PTkpICU+JSANCiAgdW5ncm91cCgpIA0KDQpiYXJyYXMkZGF0ZSA8LSBhcy5jaGFyYWN0ZXIoYmFycmFzJGRhdGUpDQoNCg0KdGFibGFfMSA8LSBnZ3Bsb3QoYmFycmFzLCBhZXMocmFua2luZywgdmFsdWUsIGNvdW50cnkgPSBjb2RlLCBzaXplID0gMTUpKSArDQogIGdlb21fY29sKGFlcyhyYW5raW5nLCB2YWx1ZSwgIGZpbGwgPSAiI2ZmYjc0ZCIpKSArDQogIA0KICBnZW9tX2ZsYWcoYWVzKHJhbmtpbmcsIHZhbHVlLCBjb3VudHJ5ID0gY29kZSksIHNpemUgPSAxMCkgKw0KICBnZW9tX3RleHQoYWVzKHJhbmtpbmcsIHZhbHVlLCBsYWJlbCA9IGFzLmZhY3Rvcih2YWx1ZSksIHNpemUgPSAyMCksIGhqdXN0PSAtMC41KSArDQogIGdlb21fdGV4dChhZXMoeD05LCB5PTMwMDAwMDAwLCBsYWJlbCA9IGFzLmZhY3RvcihkYXRlKSksIHZqdXN0ID0gMC4yLCBhbHBoYSA9IDAuNSwgIGNvbCA9ICJncmF5Iiwgc2l6ZSA9IDEwKSArDQogIA0KICBzY2FsZV94X3JldmVyc2UoKSArDQogIGNvb3JkX2ZsaXAoY2xpcCA9ICJvZmYiLCBleHBhbmQgPSBGQUxTRSkgKw0KICB0aGVtZV9saWdodCgpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gTkEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gTkEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IE5BKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSBOQSkpICtsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCkrDQogIGxhYnModGl0bGUgPSAiRXZvbHVjacOzbiBkZWwgdHVyaXNtbyBlbiBFdXJvcGEiLA0KICAgICAgIHN1YnRpdGxlID0gIlR1cnNpbW8gZGVzZGUgMjAxNyBoYXN0YSAyMDIxLiIsDQogICAgICAgY2FwdGlvbiA9ICJGdWVudGU6IEVsYWJvcmFjacOzbiBwcm9waWEgY29uIGRhdG9zIGRlIEV1cm9lc3RhdCIpICsNCiAgbGltcyh5ID0gYyhOQSwgNDAwMDAwMDApKSArDQogIA0KICB0cmFuc2l0aW9uX3N0YXRlcyhhcy5mYWN0b3IoZGF0ZSksdHJhbnNpdGlvbl9sZW5ndGggPSAxLCBzdGF0ZV9sZW5ndGggPSAwLCB3cmFwID0gRkFMU0UpDQoNCnRhYmxhXzEgPC0gdGFibGFfMSArICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIA0KDQojZ2dhbmltYXRlOjphbmltYXRlKHRhYmxhXzEsIG5mcmFtZXMgPSA0NTAsIGZwcyA9IDI1KSANCg0KYGBgDQoNCjxjZW50ZXI+PGltZyBzcmM9ImltYWdlbmVzL2JhcnJhcy5naWYiIHdpZHRoID0gIjY3NXB4IiAvPjwvY2VudGVyPg0KDQo8YnI+DQoNCg0KIyMgNSBFc3R1ZGlvIGRlbCB0dXJpc21vIGVuICoqRXNwYcOxYSoqIA0KDQpFbCB0dXJpc21vIGVzIHVubyBkZSBsb3MgcHJpbmNpcGFsZXMgbW90b3JlcyBkZSBsYSBlY29ub23DrWEgZXNwYcOxb2xhLCBvdG9yZ2FuZG8gZW1wbGVvIGFwcm94aW1hZGFtbmV0ZSBhIDIgbWlsbG9uZXMgZGUgcGVyc29uYXMsIGNvbiBsb3MgcXVlIHNlIHJlY2liZSBkZSBwcm9tZWRpbyBhIDgwIG1pbGxvbmVzIGRlIHR1cmlzdGFzIGFsIGHDsW8gKGFudGVzIGRlIGxhIHBhbWRlbWlhKSBxdWUgZGVqYW4gYXByb3hpbWFkYW1uZXRlIHVub3MgOTAuMDAwIG1pbGxvbmVzIGRlIGV1cm9zIGVuIGluZ3Jlc29zLiBQb3IgZWxsbywgbm8gZXMgZGUgZXh0cmHDsWFyIGxhIGVsZXZhZGEgaW52ZXJzacOzbiBsbGV2YWRhIGEgY2FibyBwYXJhIG1lam9yYXIgZWwgc2VjdG9yLg0KDQpUb2RhcyBlc3RhcyBpbnZlcnNpb25lcyBoYW4gZGVyaXZhZG8gZW4gcXVlIEVzcGHDsWEgc2UgY29udmllcnRhIGVuIHVubyBkZSBsb3MgcGFpc2VzIG3DoXMgY29tcGV0aXRpdm9zIGVuIGVsIHNlY3RvciB0dXLDrXN0aWNvLCBxdWVkYW5kbyBlc3RvIGRlbW9zdHJhZG8gZW4gZWwgcmFua2luZyBlbGFib3JhZG8gcG9yIGVsIFdvcmwgRWNvbm9taWMgRm9ydW0sIG90b3JnYW5kb2xlIGxhIHByaW1lcmEgcG9zaWNpw7NuIGRlIGVudHJlIDE0MCBlY29ub23DrWFzLg0KDQpFc3RvIGVzIHBvc2libGUgcG9yIGxhIGdyYW4gb2ZlcnRhIHR1cmlzdGljYSBkZSBsYSBxdWUgZGlzcG9uZSBudWVzdHJvIHBhw61zLCBwdWRpZW5kbyBkZWNhbnRhcnNlIHBvciBleHBlcmllbmNpYXMgbcOhcyBlbmZvY2FkYXMgZW4gZWwgc29sIHkgcGxheWEgbyBtw6FzIGN1bHRyYWxlcyB5IG5hdHVyYWxlcywgaG9zcGVkYW5kb3NlIGVuIGxhIGdyYW4gZGVuc2lkYWQgaG90ZWxlcmEgaW5zdGFsYWRhIGVuIG51ZXRzcm8gcGHDrXMuDQoNCjxicj4NCg0KIyMjIDUuMSBFc3R1ZGlvIGRlIGxhIG9mZXJ0YSBob3RlbGVyYQ0KDQojIyMjIDUuMS4yIE7Dum1lcm8gZGUgaG90ZWxlcyBwb3IgQ0NBQQ0KDQpFbiBlc3RlIGdyw6FmaWNvIHBvZGVtb3Mgb2JzZXJ2YXIgZWwgbnVtZXJvIGRlIGVzdGFibGVjaW1pZW50b3MgaG90ZWxlcm9zIHBvciBjb211bmlkYWQgYXV0b25vbWEsIHNpZW5kbyBBbmRhbHVjaWEgbGEgY29tdW5pZGFkIGNvbiBtYXlvciBwcmVzZW5jaWEgZGUgZXN0b3MgY29uIDE1NTcgZXN0YWJsZWNpbWllbnRvcywgc2VndWlkbyBkZSBjb211bmlkYWRlcyBjb21vIENhdGFsdcOxYSwgTWFkcmlkIG8gVmFsZW5jaWEsIHF1ZSBjb21vIHZlcmVtb3MgZW4gZWwgYXBhcnRhZG8gNS4yIHNvbiBsYXMgY29tdW5pZGFkZXMgcXVlIG1heW9yIG7Dum1lcm8gZGUgdHVyaXN0YXMsIHkgcG9yIGVuZGUgaW5ncmVzb3MsIHJlY2liZW4uDQoNCkFsZ28gcXVlIHB1ZWRlIHNvcnByZW5kZXIgZXMgZWwgaGVjaG8gZGVsIG7Dum1lcm8gZGUgaG90ZWxlcyBkZSBsb3MgcXVlIGRpc3BvbmVuIGxhcyBpc2xhcyBiYWxlYXJlcyB5IGNhbmFyaWFzLCBoZWNobyBxdWUgc2UgZXhwbGljYSBwb3Igc3UgcmVkdWNpZGEgZGltZW5zacOzbiwgeSBlbCBoZWNobyBkZSBxdWUgY29tdW5pZGFkZXMgY29tbyBHYWxpY2lhIHkgQ2FzdGlsbGEgeSBMZW9uLCBxdWUgYSBwcmlvcmkgbm8gZXN0w6FuIGNvbnNpZGVyYWRhcyBjb21vIGNvbXVuaWRhZGVzIHF1ZSByZWNpYmFuIHVuIG51bWVybyBjb25zaWRlcmFibGUgZGUgdHVyaXN0YXMsIHBvc2VhbiB1biBtYXlvciBuw7ptZXJvIGRlIGhvdGVsZXMgcXVlIGxhIENvbXVuaXRhdCBWYWxlbmNpYW5hIHkgbGEgQ29tdW5pZGFkIGRlIE1hZHJpZC4NCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFIH0NCg0KbnVtIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9jb2woZGF0YSA9IG5faG90ZWxlcywgYWVzKCB4ID0gcmVvcmRlcihsb2NhdGlvbiwgbl9ob3RlbGVzKSwgeSA9IG5faG90ZWxlcywgZmlsbCA9IG5faG90ZWxlcykpICsNCiAgIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3c9IiNmZmVjYjMiLCBoaWdoPSIjZmY4ZjAwIikgKw0KICANCiAgY29vcmRfZmxpcCgpICsNCiAgDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIikpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIGZpbGwgPSAiSG90ZWxlcyIsDQogICAgY2FwdGlvbiA9ICJGdWVudGU6IEVsYWJvcmFjacOzbiBwcm9waWEgIikgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpudW0gPC0gZ2dwbG90bHkobnVtKQ0KDQpudW0NCg0KYGBgDQoNCjxicj4NCg0KDQojIyMjIDUuMS4yIENhdGVnb3LDrWEgZGUgZGljaG9zIGhvdGVsZXMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMjIyMgR3LDoWZpY28gZGUgRG9uYQ0KDQpEaWNob3MgKipob3RlbGVzKiogZXN0w6FuIGNsYXNpZmljYWRvcyBzZWd1biB1bmEgY2xhc2lmaWNhY2nDs24gZGUgKiplc3RyZWxsYXMgb3JvKiosIGRlIDEgYSA1IGVzdHJlbGxhcywgc2llbmRvIGxhIHF1aW50YSBsYSBkZSBtYXlvciBwcmVzdGlnaW8gKGF1bnF1ZSBlc3RhIHJlZ3VsYWNpw7NuIGNhbWJpYSBkZSBjb211aW5kYWQgZW4gY29tdW5pZGFkIHBvciBsbyBxdWUgbm8gc2Ugc2lndWVuIGxvcyBtaXNtb3MgY3JpdGVyaW9zIHBhcmEgY2FkYSBkZWNpc2nDs24pLg0KDQpDb21vIHBvZGVtb3Mgb2JzZXJ2YXIgZW4gZWwgZ3LDoWZpY28gZGUgRG9uYSwgbG9zIGhvdGVsZXMgZGUgMiwzIHkgNCBlc3RyZWxsYXMgcmVwcmVzbmV0YW4gdW5hIG1heW9yIHByb3BvcmNpb24gZW4gRXNwYcOxYS4gDQoNCkFkZW3DoXMgdGFtYmnDqW4gZGlzcG9uZW1vcyBkZSBsYSBpbmZvcm1hY2nDs24gc29icmUgbG9zICoqaG9zdGFsZXMqKiwgcXVlIGFsIGlndWFsIHF1ZSBsb3MgaG90ZWxlcyBzZSBjbGFzaWZpY2FuIGNvbiBlc3RyZWxsYXMsIHBlcm8gZXN0YSB2ZXogZGUgKipwbGF0YSoqLiBFbiBlc3RlIGNhc28gb2JzZXJ2YW1vcyBjb21vIGxvcyBob3RhbGVzIGRlIHVuYSBlc3RyZWxsYSBzb24gbG9zIHByaW5jaXBhbGVzIGVuIG51ZXN0cm8gcGFpcy4gDQoNClNpIGRlc2VhIGNvbm9jZXIgbG9zIHBvcmNlbnRhamVzIGNvbiBkZXRhbGxlIHB1ZWRlIGFjdWRpciBhIGxhICoqdGFibGEqKg0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjQ3JSJ9DQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQoNCmNhdGVnb3JpYV9ob3RlbCA8LSBjYXRlZ29yaWFzICU+JSBmaWx0ZXIoIGNhdGVnb3JpYSA9PSAiaG90ZWxlcyIpICU+JSANCiAgbXV0YXRlKHRvdGFsID0gc3VtKG51bWVybykpICU+JSANCiAgbXV0YXRlKHBvcmNlbnRhamUgPSAobnVtZXJvIC8gdG90YWwpICogMTAwKSANCg0KbiA8LSBnZ3Bsb3QoY2F0ZWdvcmlhX2hvdGVsICxhZXMoeD0yLHk9cG9yY2VudGFqZSwgZmlsbCA9IGVzdHJlbGxhcykpKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwNCiAgICAgICAgICAgY29sb3I9IndoaXRlIikrDQogIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiIzgxYzc4NCIsIiM3ZTU3YzIiLCIjMjE5NmYzIiwiI2ZmZWU1OCIsICIjZjQ0MzM2IikpICsNCiAgDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSsNCiAgeGxpbSgwLjUsMi41KSAgKw0KICB0aGVtZV92b2lkKCkrDQogIA0KICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIndoaXRlIiksDQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICAgIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCBmaWxsID0gTlVMTCkrbGFicyh0aXRsZSA9ICJDYXRlZ29yaWEgZGUgbG9zIGhvdGVsZXMiLA0KICAgIGNhcHRpb24gPSAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhICIpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIndoaXRlIiksDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIndoaXRlIiksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIikpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTkEpLA0KICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTkEpKQ0KDQojbg0KIA0KICANCg0KYGBgDQoNCjxjZW50ZXI+PGltZyBzcmM9ImltYWdlbmVzL2NhdF9ob3RlbC5wbmciIHdpZHRoID0gIjEwMDBweCIgLz48L2NlbnRlcj4NCg0KDQo6OjoNCg0KOjo6IHsuY29sdW1uIHdpZHRoPSIxJSJ9DQo8IS0tIGFuIGVtcHR5IERpdiAod2l0aCBhIHdoaXRlIHNwYWNlKSBoYWNpZW5kbyBkZSBzZXBhcmFkb3IgLS0+DQo6OjoNCg0KOjo6IHsuY29sdW1uIHdpZHRoPSI0NyUifQ0KDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQoNCmNhdGVnb3JpYV9ob3N0YWwgPC0gY2F0ZWdvcmlhcyAlPiUgZmlsdGVyKCBjYXRlZ29yaWEgPT0gImhvc3RhbGVzIikgJT4lIA0KICBtdXRhdGUodG90YWwgPSBzdW0obnVtZXJvKSkgJT4lIA0KICBtdXRhdGUoIHBvcmNlbnRhamUgPSAobnVtZXJvIC8gdG90YWwpICogMTAwKQ0KDQoNCm0gPC0gZ2dwbG90KGNhdGVnb3JpYV9ob3N0YWwgLGFlcyh4PTIseT1wb3JjZW50YWplLCBmaWxsID0gZXN0cmVsbGFzKSkrDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLA0KICAgICAgICAgICBjb2xvcj0id2hpdGUiKSsNCiAgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjODFjNzg0IiwiIzdlNTdjMiIsIiMyMTk2ZjMiLCIjZmZlZTU4IiwgIiNmNDQzMzYiKSkgKw0KICANCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpKw0KICB4bGltKDAuNSwyLjUpICArDQogIHRoZW1lX3ZvaWQoKSsNCiAgDQogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgZmlsbCA9IE5VTEwpK2xhYnModGl0bGUgPSAiQ2F0ZWdvcmlhIGRlIGxvcyBob3N0YWxlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gIkZ1ZW50ZTogRWxhYm9yYWNpw7NuIHByb3BpYSAiKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJ3aGl0ZSIpKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikgKyANCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5BKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTkEpKQ0KDQoNCiNtDQoNCg0KYGBgDQoNCjxjZW50ZXI+PGltZyBzcmM9ImltYWdlbmVzL2NhdF9ob3N0YWwucG5nIiB3aWR0aCA9ICIxMDAwcHgiIC8+PC9jZW50ZXI+DQoNCg0KOjo6DQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCg0KIyMjIyMgVGFibGFzDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgd2FybmluZz0gRkFMU0V9DQogIA0KZGF0YXRhYmxlKGNhdGVnb3JpYV9ob3RlbCwgY2xhc3MgPSJzdHJpcGUgaG92ZXIgY29tcGFjdCByb3ctYm9yZGVyIiAsIGZpbHRlciA9ICd0b3AnKQ0KDQpgYGANCg0KYGBge3IsIGVjaG8gPSBUUlVFLCB3YXJuaW5nPSBGQUxTRX0NCg0KZGF0YXRhYmxlKGNhdGVnb3JpYV9ob3N0YWwsIGNsYXNzID0ic3RyaXBlIGhvdmVyIGNvbXBhY3Qgcm93LWJvcmRlciIgLCBmaWx0ZXIgPSAndG9wJykNCg0KYGBgDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyMgNS4yIEVzdHVkaW8gZGUgbG9zIGluZ3Jlc29zIHBvciB0dXJpc21vDQoNCiMjIyMgNS4yLjEgRXZvbHVjacOzbiBkZSBsb3MgaW5ncmVzb3MNCg0KRWwgc2VjdG9yIHR1csOtc3RpY28gc3Vwb25lIHVuYSBmdWVudGUgZGUgaW5ncmVzb3MgbXV5IGdyYW5kZSBwYXJhIEVzcGHDsWEsIGRlIHVub3MgOTAuMDAwIG1pbGxvbmVzIGRlIGV1cm9zIGFsIGHDsW8gY29tbyBoZSBjb21lbnRhZG8gYW50ZWlvcm1lbnRlLCBubyBvYnN0YW50ZSBkZXNkZSBsYSBjcmlzaXMgdml2aWRhIGVuIDIwMjAgbG9zIGluZ3Jlc29zIGRlY2F5ZXJvbiBkZSBtYW5lcmEgbXV5IGNvbnNpZGVyYWJsZSwgeSBhIHBlc2FyIGRlIHF1ZSB2aXZpbW9zIGVuIHVuIHBlcmlvZG8gZGUgY2llcnRhIHJlY3VwZXJhY2nDs24sIHRhbnRvIGVjb27Ds21pY2EgY29tbyBkZSBsaWJlcnRhZCBkZSBtb3ZpbWllbnRvLCBsb3MgaW5ncmVzb3MgZGVsIGHDsW8gMjAyMSBkaXN0YW4gbXVjaG8gZGUgc2VyIHNlbWJsYW50ZXMgYSBsb3MgZGUgYcOxb3MgYW50ZXJpb3Jlcy4NCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFIH0NCg0KIyBHcsOhZmljbyBkZSBFc3Bhw7FhDQoNCmdhc3RvX2VzcCA8LSBnYXN0b190dXIgJT4lIGZpbHRlcihsb2NhdGlvbiA9PSAiU3BhaW4iKQ0KDQpnYXN0b19lc3AkZGF0ZSA8LSBhcy5EYXRlKGdhc3RvX2VzcCRkYXRlKQ0KDQpnYXN0b19lc3BfMiA8LSBnYXN0b19lc3AgJT4lIGZpbHRlcihkYXRlID09ICIyMDIwLTAyLTAxIiB8IGRhdGUgPT0gIjIwMjAtMDMtMDEiIHwgZGF0ZSA9PSAiMjAyMC0wNC0wMSIgfCBkYXRlID09ICIyMDIwLTA1LTAxIiB8IGRhdGUgPT0gIjIwMjAtMDYtMDEiKQ0KDQptMSA8LSBnZ3Bsb3QoKSArDQogIGdlb21fbGluZShkYXRhID0gZ2FzdG9fZXNwLCBhZXMoZGF0ZSwgdmFsdWUpLCBjb2xvciA9ICIjNjE2MTYxIiwgc2l6ZSA9IDEuNSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBnYXN0b19lc3AsIGFlcyhkYXRlLCB2YWx1ZSApLCBjb2xvciA9ICIjNjE2MTYxIiwgc2l6ZSA9IDEuNSkgKw0KICANCiAgZ2VvbV9saW5lKGRhdGEgPSBnYXN0b19lc3BfMiwgYWVzKGRhdGUsIHZhbHVlKSwgY29sb3IgPSAiI2Q1MDAwMCIsIHNpemUgPSAxLjUpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZ2FzdG9fZXNwXzIsIGFlcyhkYXRlLCB2YWx1ZSksIGNvbG9yID0gIiNkNTAwMDAiLCBzaXplID0gMS41KSArDQogIA0KICANCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0wLA0KICAgICAgICAgICAgIHNpemUgPSAwLjI1LA0KICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsNCiAgDQogIA0KICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHM9IiVZLSVtIixkYXRlX2JyZWFrcyAgPSIzIG1vbnRocyIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA3MCwgaGp1c3QgPSAxKSkgKw0KICANCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSkgKw0KICANCiAgbGFicyh0aXRsZSA9ICJFdm9sdWNpw7NuIGRlIGxvcyBpbmdyZXNvcyBlbiBFc3Bhw7FhIiwNCiAgICB4ID0gTlVMTCwgeSA9ICJJbmdyZXNvcyIsIHN1YnRpdGxlID0gIkVuIG1pbGxvbmVzIGRlIGV1cm9zIikNCg0KDQojIEdyw6FmaWNvIGRlIGxhcyBjb211bmlkYWRlcyANCg0KZ2FzdG9fY29tdSA8LSBnYXN0b190dXIgJT4lICBmaWx0ZXIobG9jYXRpb24gIT0gIlNwYWluIikgJT4lIA0KICBmaWx0ZXIobG9jYXRpb24gJWluJSBjKCJBbmRhbHVjw61hIiwgIkNhdGFsdcOxYSIsICJDb211bml0YXQgVmFsZW5jaWFuYSIsICJNYWRyaWQsIENvbXVuaWRhZCBkZSIpKQ0KDQptMiA8LSBnZ3Bsb3QoKSArDQogIGdlb21fbGluZShkYXRhID0gZ2FzdG9fY29tdSwgYWVzKGRhdGUsIHZhbHVlLCBjb2xvciA9IGxvY2F0aW9uKSwgc2l6ZSA9IDEuNSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBnYXN0b19jb211LCBhZXMoZGF0ZSwgdmFsdWUsIGNvbG9yID0gbG9jYXRpb24pLCBzaXplID0gMS41KSArDQogIA0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPTAsDQogICAgICAgICAgICBzaXplID0gMC4yNSwNCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsNCiAgDQogIA0KICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHM9IiVZLSVtIixkYXRlX2JyZWFrcyAgPSIyIG1vbnRocyIpICsNCiAgDQogIA0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDcwLCBoanVzdCA9IDEpKSAgKyANCiAgDQogIA0KICBzY2FsZV9jb2xvcl9tYW51YWwoYnJlYWtzID0gYygiQW5kYWx1Y8OtYSIsICJDYXRhbHXDsWEiLCAiQ29tdW5pdGF0IFZhbGVuY2lhbmEiLCAiTWFkcmlkLCBDb211bmlkYWQgZGUiKSwNCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKCIjMDBiMGZmIiwgIiM5MGNhZjkiLCAiI2ZmOTgwMCIsICIjZmZjYzgwIikpICsNCiAgDQogIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSArDQogIA0KICBsYWJzKHRpdGxlID0gIkV2b2x1Y2nDs24gZGUgbG9zIGluZ3Jlc29zIHBvciBDQ0FBIiwNCiAgICB4ID0gTlVMTCwgeSA9ICJJbmdyZXNvcyAiLCBjb2xvdXIgPSBOVUxMLA0KICAgIHN1YnRpdGxlID0gIkVuIG1pbGxvbmVzIGRlIGV1cm9zICIsIGNhcHRpb24gPSAiRnVlbnRlOiBFbGFib3JhY2nDs24gcHJvcGlhIGNvbiBkYXRvcyBkZWwgSU5FIikNCg0KDQojbTIgKyBpbnNldF9lbGVtZW50KG0xLCBsZWZ0ID0gMC42LCByaWdodCA9IDEsIGJvdHRvbSA9IDAuNSwgdG9wID0gMS4wNSkNCiAgDQoNCmBgYA0KDQo8Y2VudGVyPjxpbWcgc3JjPSJpbWFnZW5lcy9qdW50by5wbmciIHdpZHRoID0gIjEwMDBweCIgLz48L2NlbnRlcj4NCg0KDQo8YnI+DQoNCg0KIyMjIDUuMyBQcmluY2lwYWxlcyBDb211bmlkYWRlcyBBdXLDs25vbWFzDQoNCiMjIyMgNS4zLjEgQ29tdW5pZGFkZXMgQXV0w7Nub21hcyBjb24gbcOhcyBpbmdyZXNvcyB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMjIyBNYXBhDQoNCkVuIGVzdGUgYXBhcnRhZG8gcG9kZW1vcyBhcHJlY2lhciBjb21vIGxhcyBDQ0FBIGNvbiBtYXlvciBuaXZlbCBkZSBpbmdyZXNvcyBwb3IgdHVyaXNtbyBzb24gQ2F0YWx1w7FhLCBBbmRhbHVjw61hLCBDb211bml0YXQgVmFsZW5jaWFuYSwgQ29tdW5pZGFkIGRlIE1hZHJpZCwgSWxsZXMgQmFsZWFycyB5IENhbmFyaWFzLg0KDQpTaSBkZXNlYSBjb25vY2VyIGxvcyBpbmdyZXNvcyBlbiBjYWRhIHBlcmlkbyBwdWVkZSBjb25zdWx0YXIgbGEgKip0YWJsYSoqDQoNCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSB9DQoNCnJtKGdhc3RvX2NvbXVuaWRhZGVzX2F1dG9ub21hcywgZ2FzdG9fdHVyaXN0aWNvX2VzcCwgSUdOX25vbWVuY2xhX211bmksIG11bmljaXBpb3NfMjAyMCwgcmlvX2Vicm9fNCwgcmlvc19lc3BhbnlhLCB3b3JsZCkNCg0KQ0NBQV8yIDwtIFByb3ZpbmNpYXMgJT4lIGdyb3VwX2J5KGluZV9jY2FhLCBpbmVfY2NhYS5uKSAlPiUgc3VtbWFyaXplKCkNCg0KQ0NBQV8zIDwtIENDQUFfMiAlPiUgc2Y6OnN0X2Ryb3BfZ2VvbWV0cnkoKQ0KDQoNCiN1bmlyIGFxdWkgbG9zIGRhdG9zIGRlbCBnYXN0byBjb24gc3UgZ2VvbWV0csOtYQ0KDQpjYW5hcmlhcyA8LSBDQ0FBXzIgJT4lIGZpbHRlcihpbmVfY2NhYS5uID09ICJDYW5hcmlhcyIpDQpwZW5pbnN1bGEgPC0gQ0NBQV8yICU+JSBmaWx0ZXIoICEoaW5lX2NjYWEubiA9PSAiQ2FuYXJpYXMiKSkNCg0KbXlfc2hpZnQgPC0gc3RfYmJveChwZW5pbnN1bGEpW2MoMSwyKV0tIChzdF9iYm94KGNhbmFyaWFzKVtjKDEsMildKSArIGMoLTIuNCwgLTEuMSkNCmNhbmFyaWFzJGdlb21ldHJ5IDwtIGNhbmFyaWFzJGdlb21ldHJ5ICsgbXlfc2hpZnQNCnN0X2NycyhjYW5hcmlhcykgIDwtIHN0X2NycyhwZW5pbnN1bGEpDQpwZW5pbnN1bGFfeV9jYW5hcmlhcyA8LSByYmluZChwZW5pbnN1bGEsIGNhbmFyaWFzKQ0KDQpwZW5pbnN1bGFfeV9jYW5hcmlhc18xIDwtcGVuaW5zdWxhX3lfY2FuYXJpYXMgJT4lIHNmOjpzdF9kcm9wX2dlb21ldHJ5KCkNCg0KZ2FzdG9fY2NhYSA8LSBmdWxsX2pvaW4oZ2FzdG9fdHVyLCBwZW5pbnN1bGFfeV9jYW5hcmlhcywgYnkgPSBjKCJsb2NhdGlvbiIgPSAiaW5lX2NjYWEubiIpKQ0KDQpnYXN0b19jY2FhIDwtIGdhc3RvX2NjYWEgJT4lIGZpbHRlcihkYXRlID09ICIyMDIxLTA4LTAxIikNCg0KcDEgPC0gZ2dwbG90KCkgKw0KICAgZ2VvbV9zZihkYXRhID0gcGVuaW5zdWxhX3lfY2FuYXJpYXMpICsNCiAgZ2VvbV9zZihkYXRhID0gZ2FzdG9fY2NhYSwgYWVzKGdlb21ldHJ5ID0gZ2VvbWV0cnksIGZpbGwgPSB2YWx1ZSApKSArDQogIHRoZW1lX3ZvaWQoKSAgKw0KICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJzZXJpZiIsIGZhY2UgPSAiaXRhbGljIiksDQogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNlcmlmIiwgZmFjZSA9ICAiaXRhbGljIikpICsNCiAgbGFicyh0aXRsZSA9ICJHYXN0byB0dXLDrXN0aWNvIiwgZmlsbCA9ICJJbmdyZXNvcyIpICArDQogIHNjYWxlX2ZpbGxfY29udGludW91cyhsb3c9IiNmZmVjYjMiLGhpZ2g9IiNlZjZjMDAiKSArDQogIGxhYnModGl0bGUgPSAiIiwNCiAgICAgICBjYXB0aW9uID0gIkRhdG9zIGV4dHJhaWRvcyBkZSBJTkUiKQ0KDQpwMQ0KDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KPGJyPg0KDQoNCiMjIyMjIFRhYmxhIA0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UgfQ0KDQpnYXN0b190dXJfMiA8LSBnYXN0b190dXIgJT4lIHJlbmFtZShpbmdyZXNvcyA9IHZhbHVlKQ0KDQpkYXRhdGFibGUoZ2FzdG9fdHVyXzIsIGNsYXNzID0ic3RyaXBlIGhvdmVyIGNvbXBhY3Qgcm93LWJvcmRlciIgLCBmaWx0ZXIgPSAndG9wJykNCg0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCg0KIyMjIyA1LjMuMiBDb25zZWN1ZW5jaWFzIGRlbCBDb3ZpZC0xOSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyMjIyBJbXBhY3RvIA0KDQpFbiBlc3RvcyBjdWFkcm9zIHBvZGVtb3Mgb2JzZXJ2YXIgY3VhbGVzIGZ1ZXJvbiBsYXMgY29tdW5pZGFkZXMsIGRlIGxhcyBhbnRlcmlvcm1lbnRlIG1lbmNpb25hZGFzLCBxdWUgc3Vmcmllcm9uIGVuIG1heW9yIHkgbWVub3IgbWVkaWRhIGxhcyBjb25zZWN1ZW5pY2FzIGRlbCBDT1ZJRC0xOS4NCg0KOjo6IHsuY29sdW1uIHdpZHRoPSI0NyUifQ0KDQpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UgfQ0KDQppbXBhY3RvXzIgPC0gZ2FzdG9fdHVyICU+JSBmaWx0ZXIoZGF0ZSA9PSAiMjAxOS0wOC0wMSIgfCBkYXRlID09ICIyMDIwLTA4LTAxIikNCg0KaW1wYWN0b18yIDwtIGltcGFjdG9fMiAlPiUgZmlsdGVyKGxvY2F0aW9uICE9IGMoIlNwYWluIiwgIk90cmFzIENvbXVuaWRhZGVzIEF1dMOzbm9tYXMiKSkgJT4lIA0KICBncm91cF9ieShsb2NhdGlvbikgJT4lIA0KICBtdXRhdGUoY3JlY2ltaWVudG8gPSB2YWx1ZSAtIGxhZyh2YWx1ZSkpICU+JSANCiAgbXV0YXRlKGluY3JlbWVudG8gPSBjcmVjaW1pZW50byAvIGZpcnN0KHZhbHVlKSAqIDEwMCApICU+JSANCiAgdW5ncm91cCgpDQoNCm1heF8yIDwtIGltcGFjdG9fMiAlPiUgc2xpY2VfbWF4KGluY3JlbWVudG8sIG4gPSAxKSAlPiUgDQogIHNlbGVjdChsb2NhdGlvbiwgaW5jcmVtZW50bykNCg0KDQoNCmJhbmRlcmFfdmFsZW5jaWEgPC0gKCJpbWFnZW5lcy9jb211bmlkYWRfdmFsZW5jaWFuYS5wbmciKQ0KDQoNCm1heF9pbmMgPC0gbWF4XzIgJT4lIGdyb3VwX2J5KGxvY2F0aW9uKSAlPiUgDQogIGFkZF9jb2x1bW4oYmFuZGVyYV92YWxlbmNpYSkgJT4lIA0KICB1bmdyb3VwKCkNCg0KDQpUYWJsYV9tYXhfYiA8LSBtYXhfaW5jICU+JSBndCgpDQoNClRhYmxhX21heF9iIDwtIFRhYmxhX21heF9iICU+JQ0KICB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqQ29tdW5pZGFkIG1lbm9zIHBlcmp1ZGljYWRhKioiKSxzdWJ0aXRsZSA9IG1kKCJBIGZlY2hhOiAwMS0wOC0yMDIwIikpDQoNClRhYmxhX21heF9iIDwtIFRhYmxhX21heF9iICU+JQ0KICB0YWJfb3B0aW9ucyhoZWFkaW5nLmJhY2tncm91bmQuY29sb3IgPSAiI2ZmYjc0ZCIpICU+JSANCiAgdGFiX29wdGlvbnMoaGVhZGluZy50aXRsZS5mb250LnNpemUgPSAxNSwgaGVhZGluZy5zdWJ0aXRsZS5mb250LnNpemUgPSAxMywgIGNvbHVtbl9sYWJlbHMuZm9udC53ZWlnaHQgPSAgImJvbGQiKQ0KDQoNClRhYmxhX21heF9iIDwtIFRhYmxhX21heF9iICAlPiUNCiAgZ3Q6OnRleHRfdHJhbnNmb3JtKGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IHZhcnMoYmFuZGVyYV92YWxlbmNpYSkpLCBmbiA9IGZ1bmN0aW9uKHgpIHtndDo6d2ViX2ltYWdlKHgsIGhlaWdodCA9IDUwKX0pICU+JSAgDQogIGNvbHNfYWxpZ24oDQogICAgYWxpZ24gPSAiY2VudGVyIikNCg0KVGFibGFfbWF4X2INCg0KYGBgDQoNCjo6Og0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjElIn0NCjwhLS0gYW4gZW1wdHkgRGl2ICh3aXRoIGEgd2hpdGUgc3BhY2UpIGhhY2llbmRvIGRlIHNlcGFyYWRvciAtLT4NCjo6Og0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjQ3JSJ9DQoNCg0KYGBge3IgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFIH0NCg0KbWluXzIgPC0gaW1wYWN0b18yICU+JSBzbGljZV9taW4oaW5jcmVtZW50bywgbiA9IDEpICU+JSANCiAgc2VsZWN0KGxvY2F0aW9uLCBpbmNyZW1lbnRvKQ0KDQpiYW5kZXJhX21hZHJpZCA8LSAoImltYWdlbmVzL21hZHJpZC5wbmciKQ0KDQoNCm1pbl9pbmMgPC0gbWluXzIgJT4lIGdyb3VwX2J5KGxvY2F0aW9uKSAlPiUgDQogIGFkZF9jb2x1bW4oYmFuZGVyYV9tYWRyaWQpICU+JSB1bmdyb3VwKCkNCg0KDQpUYWJsYV9taXhfYiA8LSBtaW5faW5jICU+JSBndCgpDQoNClRhYmxhX21peF9iIDwtIFRhYmxhX21peF9iICU+JQ0KICB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqQ29tdW5pZGFkIG3DoXMgcGVyanVkaWNhZGEqKiIpLHN1YnRpdGxlID0gbWQoIkEgZmVjaGE6IDAxLTA4LTIwMjAiKSkNCg0KVGFibGFfbWl4X2IgPC0gVGFibGFfbWl4X2IgJT4lDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICIjZmZiNzRkIikgJT4lIHRhYl9vcHRpb25zKGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMTUsIGhlYWRpbmcuc3VidGl0bGUuZm9udC5zaXplID0gMTMsICBjb2x1bW5fbGFiZWxzLmZvbnQud2VpZ2h0ID0gICJib2xkIikNCg0KDQpUYWJsYV9taXhfYiA8LSBUYWJsYV9taXhfYiAgJT4lDQogIGd0Ojp0ZXh0X3RyYW5zZm9ybShsb2NhdGlvbnMgPSBjZWxsc19ib2R5KGNvbHVtbnMgPSB2YXJzKGJhbmRlcmFfbWFkcmlkKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojp3ZWJfaW1hZ2UoeCwgaGVpZ2h0ID0gNTApfSkgJT4lICBjb2xzX2FsaWduKA0KICAgIGFsaWduID0gImNlbnRlciIpDQoNClRhYmxhX21peF9iDQoNCmBgYA0KDQo6OjoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQojIyMjIyBSZWN1cGVyYWNpw7NuDQoNCkFxdcOtIHZlbW9zIGNvbW8gbG9zIHBhcGVsZXMgc2UgaW52aWVydGUsIHkgbGEgY29tdW5pZGFkIHF1ZSBtw6FzIGNhecOzIGVuIDIwMjAgZXMgbGEgcXVlIG1heW9yIHJlY3VwZXJhY2nDs24gcHJlc2VudGEgZW4gMjAyMSB5IHZpY2V2ZXJzYS4gDQoNCjo6OiB7LmNvbHVtbiB3aWR0aD0iNDclIn0NCg0KDQpgYGB7cn0NCg0KcmVjdSA8LSAgZ2FzdG9fdHVyICU+JSBmaWx0ZXIoZGF0ZSA9PSAiMjAyMC0wOC0wMSIgfCBkYXRlID09ICIyMDIxLTA4LTAxIikNCg0KcmVjdSA8LSByZWN1ICU+JSBmaWx0ZXIobG9jYXRpb24gIT0gYygiU3BhaW4iLCAiT3RyYXMgQ29tdW5pZGFkZXMgQXV0w7Nub21hcyIpKSAlPiUgDQogIGdyb3VwX2J5KGxvY2F0aW9uKSAlPiUgDQogIG11dGF0ZShjcmVjaW1pZW50byA9IHZhbHVlIC0gbGFnKHZhbHVlKSkgJT4lIA0KICBtdXRhdGUoaW5jcmVtZW50byA9IGNyZWNpbWllbnRvIC8gZmlyc3QodmFsdWUpICogMTAwICkgJT4lIA0KICB1bmdyb3VwKCkNCg0KcmVjdV9tYXggPC0gcmVjdSAlPiUgc2xpY2VfbWF4KGluY3JlbWVudG8sIG4gPSAxKSAlPiUgDQogIHNlbGVjdChsb2NhdGlvbiwgaW5jcmVtZW50bykNCg0KYmFuZGVyYV9tYWRyaWQgPC0gKCJpbWFnZW5lcy9tYWRyaWQucG5nIikNCg0KcmVjdV8xIDwtIHJlY3VfbWF4ICU+JSBncm91cF9ieShsb2NhdGlvbikgJT4lIA0KICBhZGRfY29sdW1uKGJhbmRlcmFfbWFkcmlkKSAlPiUgdW5ncm91cCgpDQoNCg0KVGFibGFfbWF4X2MgPC0gcmVjdV8xICU+JSBndCgpDQoNClRhYmxhX21heF9jIDwtIFRhYmxhX21heF9jICU+JQ0KICB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqQ29tdW5pZGFkIGNvbiB1bmEgbWF5b3IgcmVjdXBlcmFjacOzbioqIiksc3VidGl0bGUgPSBtZCgiQSBmZWNoYTogMDEtMDgtMjAyMSIpKQ0KDQpUYWJsYV9tYXhfYyA8LSBUYWJsYV9tYXhfYyAlPiUNCiAgdGFiX29wdGlvbnMoaGVhZGluZy5iYWNrZ3JvdW5kLmNvbG9yID0gIiNmZmI3NGQiKSAlPiUgdGFiX29wdGlvbnMoaGVhZGluZy50aXRsZS5mb250LnNpemUgPSAxNSwgaGVhZGluZy5zdWJ0aXRsZS5mb250LnNpemUgPSAxMywgIGNvbHVtbl9sYWJlbHMuZm9udC53ZWlnaHQgPSAgImJvbGQiKQ0KDQoNClRhYmxhX21heF9jIDwtIFRhYmxhX21heF9jICAlPiUNCiAgZ3Q6OnRleHRfdHJhbnNmb3JtKGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IHZhcnMoYmFuZGVyYV9tYWRyaWQpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OndlYl9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgIGNvbHNfYWxpZ24oDQogICAgYWxpZ24gPSAiY2VudGVyIikNCg0KVGFibGFfbWF4X2MNCg0KDQpgYGANCg0KOjo6DQoNCjo6OiB7LmNvbHVtbiB3aWR0aD0iMSUifQ0KPCEtLSBhbiBlbXB0eSBEaXYgKHdpdGggYSB3aGl0ZSBzcGFjZSkgaGFjaWVuZG8gZGUgc2VwYXJhZG9yIC0tPg0KOjo6DQoNCjo6OiB7LmNvbHVtbiB3aWR0aD0iNDclIn0NCg0KDQpgYGB7cn0NCg0KcmVjdV9taW4gPC0gcmVjdSAlPiUgc2xpY2VfbWluKGluY3JlbWVudG8sIG4gPSAxKSAlPiUgDQogIHNlbGVjdChsb2NhdGlvbiwgaW5jcmVtZW50bykNCg0KYmFuZGVyYV92YWxlbmNpYSA8LSAoImltYWdlbmVzL2NvbXVuaWRhZF92YWxlbmNpYW5hLnBuZyIpDQoNCnJlY3VfMiA8LSByZWN1X21pbiAlPiUgZ3JvdXBfYnkobG9jYXRpb24pICU+JSANCiAgYWRkX2NvbHVtbihiYW5kZXJhX3ZhbGVuY2lhICkgJT4lIHVuZ3JvdXAoKQ0KDQoNClRhYmxhX21pbl9jIDwtIHJlY3VfMiAlPiUgZ3QoKQ0KDQpUYWJsYV9taW5fYyA8LSBUYWJsYV9taW5fYyAlPiUNCiAgdGFiX2hlYWRlcih0aXRsZSA9IG1kKCIqKkNvbXVuaWRhZCBjb24gdW5hIG1lbm9yIHJlY3VwZXJhY2nDs24qKiIpLHN1YnRpdGxlID0gbWQoIkEgZmVjaGE6IDAxLTA4LTIwMjEiKSkNCg0KVGFibGFfbWluX2MgPC0gVGFibGFfbWluX2MgJT4lDQogIHRhYl9vcHRpb25zKGhlYWRpbmcuYmFja2dyb3VuZC5jb2xvciA9ICIjZmZiNzRkIikgJT4lIHRhYl9vcHRpb25zKGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gMTUsIGhlYWRpbmcuc3VidGl0bGUuZm9udC5zaXplID0gMTMsICBjb2x1bW5fbGFiZWxzLmZvbnQud2VpZ2h0ID0gICJib2xkIikNCg0KDQpUYWJsYV9taW5fYyA8LSBUYWJsYV9taW5fYyAgJT4lDQogIGd0Ojp0ZXh0X3RyYW5zZm9ybShsb2NhdGlvbnMgPSBjZWxsc19ib2R5KGNvbHVtbnMgPSB2YXJzKGJhbmRlcmFfdmFsZW5jaWEpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OndlYl9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgIGNvbHNfYWxpZ24oDQogICAgYWxpZ24gPSAiY2VudGVyIikNCg0KVGFibGFfbWluX2MNCg0KDQpgYGANCg0KOjo6DQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KDQojIyA2IENvbmNsdXNpb25lcyANCg0KUGFyYSBmaW5hbGl6YXIgZWwgdHJhYmFqbyBkZXN0YWNhciBjb21vIGVsIHR1cmlzbW8gZXMgdW5vIGRlIGxvcyBwcmluY2lwYWxlcyBtb3RvcmVzIGRlIGxhcyBlY29ub23DrWFzIGV1cm9wZWFzLCBzb2JyZSB0b2RvIGRlIGxhIGVzcGHDsW9sYSwgcHJvcG9yY2lvbmFuZG8gZXN0YSB1bmEgZnVlbnRlIGRlIGluZ3Jlc29zIG11eSBpbXBvcnRhbnRlLCBjb24gbG8gcXVlIHRvZG8gZWxsbyBjb25sbGV2YSAoZW1wbGVvLCBiaWVuZXN0YXIsIFBJQi4uLikuIFBvciBlbGxvIGVzIHByZW9jdXBuYXRlIGxhIHNpdHVhY2nDs24gYWN0dWFsIGVuIGxhIHF1ZSB2aXZpbW9zLCB5YSBxdWUgYSBwZXNhciBkZSBxdWUgZW4gbGEgYWN0dWFsaWRhZCBleHBlcmltZW50YW1vcyB1bmEgY2llcnRhIHJlY3VwZXJhY2nDs24gZWNvbsOzbWljYSwgZXN0w6FuIHN1cmdpZW5kbyBudWV2YXMgdmFyaWFudGVzIGRlbCBDT1ZJZC0xOSwgY29tbyBsYSBPbWljcm9uLCBxdWUgZXN0w6FuIHBvbmllbmRvIGVuIGphcXVlIGEgbGFzIGVjb25taWFzIG1lbmNpb25hZGFzIGVuIGVsIHRyYWJham8sIHBvciBsbyBjdWFsIG5vIHNlIGRlc2NhcnRhIGxhIGltcG9zaWNpw7NuIGRlIG51ZXZhcyByZXN0cmljY2lvbmVzIHF1ZSBwdWVkYW4gcmVmcmVuYXIgZGljaGEgcmVjdXBlcmFjacOzbiBhZmVjdGFuZG8gYXPDrSBkZSBmb3JtYSBtdXkgbmVnYXRpdmEgYSBlc3RlIHNlY3RvciBlbiBjb25jcmV0by4NCg0KDQo8YnI+DQoNCg0KUmVzcGVjdG8gYSBsYSBlbGFib3JhY2nDs24gZGVsIHRyYWJham8sIGRlc3RhY2FyIGNvbW8gbGEgZWxhYm9yYWNpw7NuIGRlbCBlbnNheW8gZ3J1cGFsIG1lIGhhIHNlcnZpZG8gZGUgdXRpbGlkYWQgZW4gZWwgbW9tZW50byBkZSB0cmF0YXIgZGUgbWFuZWphciBsb3MgZGF0b3MsIGFzw60gY29tbyBwYXJhIGxhIGVsYWJvcmFjacOzbiBkZSBncsOhZmljYXMgcXVlIGFudGVzIHN1cG9uaWFuIHVuIHBsdXMgZGUgZGlmaWN1bHRhZC4gQWRlbcOhcywgbGEgcmVhbGl6YWNpw7NuIGRlIGVzdGUgbWUgaGEgcGVybWl0aWRvIGFjYWJhciBkZSBhc2VudGFyIGxvcyBjb25vY2ltaW5ldG9zIGFkcXVpcmlkb3MgdGFudG8gZW4gbGEgYXNpZ25hdHVyYSBjb21vIGxvcyBxdWUgYWRxdWlyaW1vcyBqdW50byBhIG1pcyBjb21wYcOxZXJvcyB5IHlvIGFsIHJlYWxpemFyIGVsIG90cm8gdHJhYmFqby4NCg0KDQo8YnI+DQoNCg0KIyMgNy4gUmVmZXJlbmNpYXMNCg0KUGFyYSByZWFsaXphciBsb3MgY29tZW50YXJpb3MgeSBncsOhZmljb3MgcXVlIGhlbW9zIGlkbyBhbmFsaXphbmRvIGEgbG8gbGFyZ28gZGVsIHRyYWJham8gbWUgaGUgYmFzYWRvIGVuIGFydMOtY3Vsb3MgeSBkYXRvcyBxdWUgZXhwb25kcsOpIGEgY29udGludWFjacOzbiAuDQoNClBhcmEgcG9kZXIgcmVhbGl6YXIgZGljaG9zIGNvbWVudGFyaW9zLCBoZSBjb25zdWx0YWRvIGVzdG9zIGFydMOtY3Vsb3M6DQoNCi0gPGEgaHJlZj0iaHR0cHM6Ly9jb25jZXB0b2RlZmluaWNpb24uZGUvdHVyaXNtby8iPmh0dHBzOi8vY29uY2VwdG9kZWZpbmljaW9uLmRlL3R1cmlzbW8vPC9hPg0KDQotIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmludmVzdGluc3BhaW4ub3JnL2VzL3NlY3RvcmVzL3R1cmlzbW8tb2NpbyI+aHR0cHM6Ly93d3cuaW52ZXN0aW5zcGFpbi5vcmcvZXMvc2VjdG9yZXMvdHVyaXNtby1vY2lvPC9hPg0KDQotIDxhIGhyZWY9Imh0dHBzOi8vdGVjbm9ob3RlbG5ld3MuY29tLzIwMTcvMDcvMTcvZWwtc2VjdG9yLXR1cmlzdGljby1wcmluY2lwYWwtbW90b3ItZGUtbGEtZWNvbm9taWEtZXNwYW5vbGEvIj5odHRwczovL3RlY25vaG90ZWxuZXdzLmNvbS8yMDE3LzA3LzE3L2VsLXNlY3Rvci10dXJpc3RpY28tcHJpbmNpcGFsLW1vdG9yLWRlLWxhLWVjb25vbWlhLWVzcGFub2xhLzwvYT4NCg0KLSA8YSBocmVmPSJodHRwczovL2VjLmV1cm9wYS5ldS9yZWdpb25hbF9wb2xpY3kvZXMvcG9saWN5L3RoZW1lcy90b3VyaXNtLyI+aHR0cHM6Ly9lYy5ldXJvcGEuZXUvcmVnaW9uYWxfcG9saWN5L2VzL3BvbGljeS90aGVtZXMvdG91cmlzbS8NCg0KUGFyYSByZWFsaXphciBncsOhZmljb3MgW2FuaW1hZG9zXShodHRwczovL2dnYW5pbWF0ZS5jb20vKSwgaGUgY29uc3VsdGFkbyBsYXMgZXhwbGljYWNpb25lcyBkZSBjb21vIGltcGxlbWVudGFyIGVsIHBhcXVldGUgZ2dhbmltYXRlIGVuIGVsIHByb3llY3RvLg0KDQpQYXJhIHBvZGVyIHJlYWxpemFyIHVuIG1hcGEgZGUgRXNwYcOxYSB5IHN1cyBbQ0NBQV0oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViL3R1dG9yaWFsZXMvdHRfMDlfR0lTLWNvbi1SLmh0bWwjRGF0b3NfZXNwYWNpYWxlcykgbWUgaGUgYmFzYWRvIGVuIGVzdGUgdHV0b3JpYWwgZGUgbGEgYXNpZ25hdHVyYS4gDQoNCkFkZW3DoXMsIHBhcmEgbGEgcG9kZXIgZGV0ZXJtaW5hciBkZSBmb3JtYSBtdXkgdmlzdWFsIGxhIHByb3BvcmNpw7NuIGRlIHR1cmlzdGFzIHBvciBwYWlzIGhlIGVsYWJvcmFkbyB1biB0cmVlbWFwIGJhbnNhZG9tZSBlbiBlc3RhIFtww6FnaW5hXShodHRwczovL3d3dy5yLWdyYXBoLWdhbGxlcnkuY29tL3RyZWVtYXAuaHRtbCIpLg0KDQpUYW1iacOpbiBoZSBjb25zdWxhdGRvIGxhIHDDoWdpbmEgW1ItR3JhcGhdKGh0dHBzOi8vd3d3LnItZ3JhcGgtZ2FsbGVyeS5jb20vKSBjb21vIGluc3BpcmFjacOzbiBwYXJhIGFsZ3Vub3MgZ3LDoWZpY29zLg0KDQpQYXJhIGRldGVybWluYXIgbGEgZXNjYWxhIGRlIGNvbG9yZXMsIHRhbnRvIGRlbCBDU1MgY29tbyBkZSBsb3MgZ3LDoWZpY29zIGhlIGNvbnN1bHRhZG8gZXN0YXMgW3BhbGV0YXNdKGh0dHBzOi8vd3d3Lm1hdGVyaWFscGFsZXR0ZS5jb20vY29sb3JzKQ0KDQpQb3Igw7psdGltbywgZGVzdGFjYXIgcXVlIHRhbWLDrWVuIGhlIGNvbnN1bHRhZG8gbG9zIHRyYWJham9zIHJlYWxpemFkb3MgcG9yIG1pcyBjb21wYcOxZXJvcyBlbiBhw7FvcyBhbnRlcmlvcmVzLiBMb3MgcHVlZGVzIGVuY29udHJhciAgW2FxdWldKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIwLTIxLXdlYi8wNy10cmFiYWpvcy5odG1sKSANCg0KDQotLS0tLS0tLS0tLS0tLS0tDQoNCg0KPGJyPg0KDQoNClBhcmEgY29uY2x1aXIgZXN0ZSBhcGFydGFkbyBpbmNsdWltb3MgbGEgYHNlc3Npb24gaW5mb2A6DQoNCg0KYGBge3J9DQpzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkgJT4lIGRldGFpbHM6OmRldGFpbHMoc3VtbWFyeSA9ICdjdXJyZW50IHNlc3Npb24gaW5mbycpIA0KYGBgDQo=