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 2020-2021. La página web de la asignatura puede verse aquí: https://perezp44.github.io/intro-ds-20-21-web/. Los trabajos de nuestros compañeros de curso pueden verse aquí.



1. Introducción

Este trabajo consiste en un estudio de las diferentes películas y series de netflix. Con este análisis queremos poner en práctica lo estudiado en la asignatura de Programación y manejo de datos en la era del Big Data.

2. ¿Qué es?

Netflix es un servicio de streaming que funciona mediante suscripción y permite a sus usuarios ver series y películas, sin anuncios, a través de cualquier dispositivo conectado a internet.

También se pueden descargar series y películas en cualquier dispositivo iOS, Android, o Windows 10 y verlas sin necesidad de conexión a internet.

Logo

3. Un poco de hisotria

La compañía no tuvo éxito desde un comienzo, pero las buenas acciones de sus desarrolladores la llevaron a obtener las ganancias que tiene hoy en día.

En sus principios, Netflix era una compañía que alquilaba DVD’s, se fundó en 1997, y fue en 1998 donde alquiló su primer DVD. La empresa comenzó alquilando películas por esta modalidad.

  • En 2007, Netflix inicia su servicio de VOD en Estados Unidos para computadoras personales.

  • A partir de 2008 se agregan diferentes opciones para acceder al catálogo por retransmisión en directo.

  • En 2009 su catálogo físico ofrece 100 mil títulos y su clientela supera los 10 millones de suscriptores.

  • En 2011, la empresa inicia operaciones por primera vez fuera del territorio estadounidense y canadiense, ofreciendo su catálogo por retransmisión en directo en la región de América Latina y el Caribe.

  • En 2012 ofrece sus servicios en algunos países de Europa.

  • En 2016 ofrece sus contenidos a todo el mundo con excepción de la región de Crimea, y los territorios de Corea del Norte, China y Siria.

4. Análisis de la oferta audiovisual de Netflix

Oferta de Netflix

4.1 Datos analizados

El contenido de Netflix varía según la región, y puede cambiar con el tiempo. Su oferta incluye una gran variedad de galardonados títulos originales de Netflix, series, películas, documentales y mucho más.

A lo largo de este análisis vamos a utilizar las siguientes rutas de datos.

netflix <- read_excel("./Datos/netflix_titles.xlsx")
netflix <- netflix %>% select(-show_id, -cast, -description, -rating)
suscriptores <- read_excel("./Datos/suscriptores11.xlsx")

La tabla ‘netflix’ nos da los datos de las Movies y TVShows que Netflix tiene en su página. Nos indica el título de cada una de ellas, su director, la ciudad donde fueron producidas, la fecha que se estrenaron y la que se subieron a la plataforma de Netflix, la duración y el género.

Con la función anterior hemos arreglado los datos de netflix_titles y eliminado las columnas ‘show_id’, ‘coast’, ‘description’ y ‘ratiing’.

4.2. Gráfico TVShows Vs Movies en el tiempo

cuatro <- netflix %>% group_by(type, release_year)%>% count()
cuatro1 <- ggplot(cuatro, aes(x = release_year, y = n)) + geom_area(aes(color = type, fill = type),
alpha = 0.5, position=position_dodge(0.8))+ scale_color_manual(values=c("#00AFBB","#E7B800"))+ scale_fill_manual(values=c("#00AFBB","#E7B800"))
cuatro1+labs(title = "TVShows y Movies en el tiempo")

La compañía no tuvo éxito desde un comienzo, pero las buenas acciones de sus desarrolladores la llevaron a obtener las ganancias que tiene hoy en día.

En sus principios, Netflix era una compañía que alquilaba DVD’s, se fundó en 1997, y fue en 1998 donde alquiló su primer DVD. La empresa comenzó alquilando películas por esta modalidad.

4.3 Películas y series ordenadas por años de producción

Lo primero que vamos a hacer es ordenar las películas y series de más antigua a más nueva y después mover la columna “release_year” a la izquierda de todo.

grafico2 <- netflix %>% arrange(release_year)
grafico2.1 <- grafico2 %>% select(release_year, everything())

Cogiendo como referencia la tabla del trabajo de Noelia Sánchez, Ignacio Montava y Andreu Esparza, hemos realizado la siguiene tabla en a que se pueden buscar las distintas Movies y TV Show por diferentes filtros.

Como podemos observar en la tabla anterior, la serie más antigua que existe en la plataforma de Netflix es “Pioneers: First Women Filmmakers”

La película más antigua que se encuentra en la plataforma es, “Prelude to War”, una película estadounidense basada en la Segunda Guerra Mundial y cuyo director es Frank Capra.

4.4 Los diez directores con más películas

En la siguiente tabla se pueden observar los diez directores que más películas han realizado.

grafico4 <- netflix %>% filter(type == "Movie") %>%group_by(director) %>% summarise(Películas=n()) %>% na.omit(datos) %>% slice_max(Películas,n =10)
grafico41 <- grafico4 %>% mutate(director = forcats::as_factor(director))
director Películas
Raúl Campos, Jan Suter 18
Marcus Raboy 14
Jay Karas 13
Jay Chapman 12
Martin Scorsese 9
Steven Spielberg 9
David Dhawan 8
Johnnie To 8
Lance Bangs 8
Cathy Garcia-Molina 7
Hakan Algül 7
Ryan Polito 7
S.S. Rajamouli 7
Shannon Hartman 7

De forma más visual se puede observar lo anteriormente mostrado en el siguiente gráfico. Raúl Campos y Jan Suter son los directores con diferencia que más películas han realizado.


graficodirectores1 <- ggplot (grafico41, aes(x=director, y = Películas), aes(fct_rev(director))) + geom_bar(stat="identity", fill = "red") + coord_flip() + labs(x = "Director", y = "Número de películas")+labs(title = "Diez directores con más películas")
ggplotly(graficodirectores1)

4.5 Los díez países con más películas.

El país con más películas producidas que hay en la plataforma de Netflix es Estados Unidos y el segundo es India.

Sorprende que India sea de los paises que tiene más producción de cine y esto se debe a la industria cinematográfica ubicada en una de sus ciudades más pobladas, Bombay. Esta ha desbancado en el número de producción de películas a Hollywood, y es que en Bollywood se producen cada año más de 1.000 cintas o películas.

grafico4 <- netflix %>% filter(type == "Movie") %>%group_by(country) %>% summarise(Países=n()) %>% na.omit(datos) %>% slice_max(Países,n =10)
grafico41 <- grafico4 %>% mutate(country = forcats::as_factor(country))
d <- ggplot (grafico41,aes(x=country, y = Países), aes(fct_rev(country))) + geom_bar(stat="identity", fill = "black") + coord_flip()
d + labs(title = "Gráfico de los 10 países con más películas producidas",
       caption = "Datos provenientes del netflix_titles dataset",
       x = "País",
       y = "Número de Películas",
       color = "Especie de lirio")

Hemos creado un mapa para mostrar estos diez paises.

world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf") 
world1 <- world %>% filter (admin %in% c("Japan", "Hong Kong", "France", "Mexico", "Turkey", "Spain", "Canada", "United Kingdom", "India", "United States of America"))

world2 <- world %>% filter(!(admin %in% c("Japan", "Hong Kong", "France", "Mexico", "Turkey", "Spain", "Canada", "United Kingdom", "India", "United States")))

world3 <- ggplot () + geom_sf(data = world2) + geom_sf(data = world1, fill = "black") +  labs(title = "Países con más películas en Netflix",  caption = "Elaboracion propia") + theme(panel.grid.major = element_line(color = gray(.8), linetype = "dashed", size = 0.05), panel.background = element_rect(fill = "gray")) + coord_sf(xlim = c(-160, 160), ylim = c(-50, 80), expand = FALSE) + 
annotate(geom = "text", label = "1482", size = 4, x = -72.5, y = 43, color = "RED") +
annotate(geom = "text", label = "80", size = 4, x = -4, y = 42.5, color = "RED") + 
annotate(geom = "text", label = "170", size = 4, x = -1, y = 55, color = "RED")  + 
annotate(geom = "text", label = "50", size = 4, x = 3, y = 50,color = "RED") +
annotate(geom = "text", label = "55", size = 4, x = 35.18, y = 38.84, color = "RED") + 
annotate(geom = "text", label = "724", size = 4, x = 79.89, y = 20.95, color = "RED") + 
annotate(geom = "text", label = "88", size = 4, x = -101.11, y = 55.29, color = "RED") + 
annotate(geom = "text", label = "54", size = 4, x = -99.27, y = 19.67, color = "RED")+
annotate(geom = "text", label = "49", size = 4, x = 114.10, y = 22.39, color = "RED")+ 
annotate(geom = "text", label = "47", size = 4, x = 139.41, y = 36.72, color = "RED")
world3

4.6 Gráfico porcentaje TvShows Vs Movies

Con este gráfico podemos ver que en la oferta de Netflix predominan las películas frente a las series. El porcentaje de películas es de aproximadamente un 68% frente al 32% de series.

grafico6 <- netflix %>% group_by(type) %>% summarise(NN=n()) %>% mutate(prob = prop.table(NN)*100)
grafico61 <- ggplot(grafico6, aes(x = "", y = prob, fill = prob))+geom_bar(stat="identity", color = "white") + geom_text(aes(label=prob),position=position_stack(vjust=0.5), color="white", size=5) + coord_polar(theta="y") + theme_void()
grafico61+labs(title = "Movies Vs Tv SHows")

4.7 Las diez películas más largas

En este apartado hemos tenido que modificar en primer lugar, la columna donde se mostraba la duración, ya que inicialmente la celda contenía letras y números (ejemplo: 90 min), y crear dos nuevas columnas donde en una pusiera el número y en la otra las letras. De este modo poder trabajar los datos. En segundo lugar, habiendo creado las dos columnas, hemos tenido que modificar el formato de los datos de la columna que contenía los números, ya que estaba en formato letra, y no leía bien los datos. Dicho esto, a continuación podemos observar las diez películas más largas de la plataforma Netflix.

i <-   separate(data = netflix, col = "duration", into = c("duracion", "tipo"), sep = " ") %>% mutate(duracion = as.numeric(duracion)) %>% filter (tipo == "min") %>% top_n(duracion, n = 10) %>% mutate(duracion = forcats::as_factor(duracion)) 
type title director country date_added release_year duracion tipo listed_in
Movie The Gospel of Luke David Batty United States, United Kingdom, Morocco October 19, 2018 2015 205 min Dramas, Faith & Spirituality
Movie Jodhaa Akbar Ashutosh Gowariker India October 1, 2018 2008 214 min Action & Adventure, Dramas, International Movies
Movie The Irishman Martin Scorsese United States November 27, 2019 2019 209 min Dramas
Movie Doctor Zhivago David Lean United States, Italy, United Kingdom, Liechtenstein November 1, 2019 1965 200 min Classic Movies, Dramas, Romantic Movies
Movie The Lord of the Rings: The Return of the King Peter Jackson New Zealand, United States January 1, 2020 2003 201 min Action & Adventure, Sci-Fi & Fantasy
Movie Lagaan Ashutosh Gowariker India December 8, 2017 2001 224 min Dramas, International Movies, Music & Musicals
Movie Sangam Raj Kapoor India December 31, 2019 1964 228 min Classic Movies, Dramas, International Movies
Movie Black Mirror: Bandersnatch NA United States December 28, 2018 2018 312 min Dramas, International Movies, Sci-Fi & Fantasy
Movie Elephants Dream 4 Hour Bassam Kurdali Netherlands August 23, 2018 2006 196 min International Movies, Sci-Fi & Fantasy
Movie What’s Your Raashee? Ashutosh Gowariker India August 15, 2018 2009 203 min Comedies, International Movies, Music & Musicals

4.8 TV Shows lanzados por año de producción

En este apartado hemos aislado los datos de TVShows para poder realizar el gráfico correspondiente.

i2 <-   separate(data = netflix, col = "duration", into = c("duracion", "tipo"), sep = " ") %>% mutate(duracion = as.numeric(duracion)) %>% filter (tipo == "Season") %>% mutate(duracion = forcats::as_factor(duracion)) 

grafico4.8 <- i2 %>% group_by(release_year) %>% summarise(NN=n())
b <- ggplot (grafico4.8, aes(x = release_year, y = NN)) + geom_bar(stat = "identity", fill = "steelblue")
b + labs(title = "Gráfico: TVShows por año",
       subtitle = "(diferenciando por año)",
       caption = "Datos provenientes del netflix_titles dataset",
       x = "Release_year",
       y = "NN",
       color = "Especie de lirio")

5. Evolución de los suscriptores



suscriptores %>%
  ggplot( aes(x=Año, y=Suscriptors, group=Zonas_geográficas, color=Zonas_geográficas)) +
    geom_line() +
    geom_point() + 
      transition_reveal(Año)

Con este gráfico podemos ver la evolución de los nuevos suscriptores analizando los datos del mes de enero de los años 2018, 2019 y 2020.

Podemos observar que Europa es la que ha experimentado un mayor crecimiento de suscriptores desde hace tres años hasta ahora con una diferencia de mas de 40.000 suscriptores en este mes desde 2018 hasta 2020.

EEUU y Canadá ya contaban con un gran número de suscriptores en marzo de 2018 y siguen siendo la zona que mas suscriptores tienen. Al mismo tiempo que la zona de Asia tienen un número mucho menor.

No hemos podido encontrar los datos de este año enteros para poder ver la evolución pero sí se puede afirmar que Netflix ha duplicado el número de suscriptores gracias a la cuarentena por el coronavirus duplicando también sus beneficios y las expectativas para este periodo.

6. Sesión Informativa

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

current session info


- Session info ---------------------------------------------------------------
 setting  value                       
 version  R version 4.0.2 (2020-06-22)
 os       Windows 10 x64              
 system   x86_64, mingw32             
 ui       RTerm                       
 language (EN)                        
 collate  Spanish_Spain.1252          
 ctype    Spanish_Spain.1252          
 tz       Europe/Paris                
 date     2020-12-17                  

- Packages -------------------------------------------------------------------
 package           * version    date       lib source                        
 assertthat          0.2.1      2019-03-21 [1] CRAN (R 4.0.3)                
 backports           1.2.0      2020-11-02 [1] CRAN (R 4.0.3)                
 broom               0.7.2      2020-10-20 [1] CRAN (R 4.0.3)                
 cellranger          1.1.0      2016-07-27 [1] CRAN (R 4.0.3)                
 class               7.3-17     2020-04-26 [2] CRAN (R 4.0.2)                
 classInt            0.4-3      2020-04-07 [1] CRAN (R 4.0.3)                
 cli                 2.2.0      2020-11-20 [1] CRAN (R 4.0.2)                
 clipr               0.7.1      2020-10-08 [1] CRAN (R 4.0.3)                
 colorspace          2.0-0      2020-11-11 [1] CRAN (R 4.0.3)                
 crayon              1.3.4      2017-09-16 [1] CRAN (R 4.0.3)                
 crosstalk           1.1.0.1    2020-03-13 [1] CRAN (R 4.0.3)                
 data.table          1.13.2     2020-10-19 [1] CRAN (R 4.0.3)                
 DBI                 1.1.0      2019-12-15 [1] CRAN (R 4.0.3)                
 dbplyr              2.0.0      2020-11-03 [1] CRAN (R 4.0.3)                
 desc                1.2.0      2018-05-01 [1] CRAN (R 4.0.3)                
 details             0.2.1      2020-01-12 [1] CRAN (R 4.0.3)                
 digest              0.6.27     2020-10-24 [1] CRAN (R 4.0.3)                
 dplyr             * 1.0.2      2020-08-18 [1] CRAN (R 4.0.3)                
 e1071               1.7-4      2020-10-14 [1] CRAN (R 4.0.3)                
 ellipsis            0.3.1      2020-05-15 [1] CRAN (R 4.0.3)                
 evaluate            0.14       2019-05-28 [1] CRAN (R 4.0.3)                
 fansi               0.4.1      2020-01-08 [1] CRAN (R 4.0.3)                
 farver              2.0.3      2020-01-16 [1] CRAN (R 4.0.3)                
 fastmap             1.0.1      2019-10-08 [1] CRAN (R 4.0.3)                
 forcats           * 0.5.0      2020-03-01 [1] CRAN (R 4.0.3)                
 formatR             1.7        2019-06-11 [1] CRAN (R 4.0.3)                
 fs                  1.5.0      2020-07-31 [1] CRAN (R 4.0.3)                
 gapminder         * 0.3.0      2017-10-31 [1] CRAN (R 4.0.3)                
 generics            0.1.0      2020-10-31 [1] CRAN (R 4.0.3)                
 gganimate         * 1.0.7      2020-10-15 [1] CRAN (R 4.0.3)                
 ggplot2           * 3.3.2      2020-06-19 [1] CRAN (R 4.0.3)                
 ggThemeAssist     * 0.1.5      2016-08-13 [1] CRAN (R 4.0.3)                
 gifski              0.8.6      2018-09-28 [1] CRAN (R 4.0.3)                
 glue                1.4.2      2020-08-27 [1] CRAN (R 4.0.3)                
 gt                * 0.2.2      2020-11-16 [1] Github (rstudio/gt@fcd2167)   
 gtable              0.3.0      2019-03-25 [1] CRAN (R 4.0.3)                
 haven               2.3.1      2020-06-01 [1] CRAN (R 4.0.3)                
 here                1.0.0      2020-11-15 [1] CRAN (R 4.0.2)                
 highr               0.8        2019-03-20 [1] CRAN (R 4.0.3)                
 hms                 0.5.3      2020-01-08 [1] CRAN (R 4.0.3)                
 htmltools           0.5.0      2020-06-16 [1] CRAN (R 4.0.3)                
 htmlwidgets         1.5.2      2020-10-03 [1] CRAN (R 4.0.3)                
 httpuv              1.5.4      2020-06-06 [1] CRAN (R 4.0.3)                
 httr                1.4.2      2020-07-20 [1] CRAN (R 4.0.3)                
 jsonlite            1.7.1      2020-09-07 [1] CRAN (R 4.0.3)                
 KernSmooth          2.23-17    2020-04-26 [2] CRAN (R 4.0.2)                
 klippy            * 0.0.0.9500 2020-11-16 [1] Github (rlesur/klippy@378c247)
 knitr             * 1.30       2020-09-22 [1] CRAN (R 4.0.3)                
 labeling            0.4.2      2020-10-20 [1] CRAN (R 4.0.3)                
 later               1.1.0.1    2020-06-05 [1] CRAN (R 4.0.3)                
 lattice             0.20-41    2020-04-02 [2] CRAN (R 4.0.2)                
 lazyeval            0.2.2      2019-03-15 [1] CRAN (R 4.0.3)                
 lifecycle           0.2.0      2020-03-06 [1] CRAN (R 4.0.3)                
 lubridate           1.7.9.2    2020-11-13 [1] CRAN (R 4.0.3)                
 magrittr            2.0.1      2020-11-17 [1] CRAN (R 4.0.3)                
 mime                0.9        2020-02-04 [1] CRAN (R 4.0.3)                
 miniUI              0.1.1.1    2018-05-18 [1] CRAN (R 4.0.3)                
 modelr              0.1.8      2020-05-19 [1] CRAN (R 4.0.3)                
 munsell             0.5.0      2018-06-12 [1] CRAN (R 4.0.3)                
 pillar              1.4.7      2020-11-20 [1] CRAN (R 4.0.2)                
 pkgconfig           2.0.3      2019-09-22 [1] CRAN (R 4.0.3)                
 plotly            * 4.9.2.1    2020-04-04 [1] CRAN (R 4.0.3)                
 plyr                1.8.6      2020-03-03 [1] CRAN (R 4.0.3)                
 png                 0.1-7      2013-12-03 [1] CRAN (R 4.0.3)                
 prettyunits         1.1.1      2020-01-24 [1] CRAN (R 4.0.3)                
 progress            1.2.2      2019-05-16 [1] CRAN (R 4.0.3)                
 promises            1.1.1      2020-06-09 [1] CRAN (R 4.0.3)                
 purrr             * 0.3.4      2020-04-17 [1] CRAN (R 4.0.3)                
 R6                  2.5.0      2020-10-28 [1] CRAN (R 4.0.3)                
 Rcpp                1.0.5      2020-07-06 [1] CRAN (R 4.0.3)                
 reactable         * 0.2.3      2020-10-04 [1] CRAN (R 4.0.3)                
 reactR              0.4.3      2020-07-12 [1] CRAN (R 4.0.3)                
 readr             * 1.4.0      2020-10-05 [1] CRAN (R 4.0.3)                
 readxl            * 1.3.1      2019-03-13 [1] CRAN (R 4.0.3)                
 reprex              0.3.0      2019-05-16 [1] CRAN (R 4.0.3)                
 rgeos               0.5-5      2020-09-07 [1] CRAN (R 4.0.3)                
 rlang               0.4.8      2020-10-08 [1] CRAN (R 4.0.3)                
 rmarkdown           2.5        2020-10-21 [1] CRAN (R 4.0.3)                
 rnaturalearth       0.1.0      2017-03-21 [1] CRAN (R 4.0.3)                
 rnaturalearthdata   0.1.0      2017-02-21 [1] CRAN (R 4.0.3)                
 rprojroot           2.0.2      2020-11-15 [1] CRAN (R 4.0.2)                
 rstudioapi          0.13       2020-11-12 [1] CRAN (R 4.0.3)                
 rvest               0.3.6      2020-07-25 [1] CRAN (R 4.0.3)                
 scales            * 1.1.1      2020-05-11 [1] CRAN (R 4.0.3)                
 sessioninfo         1.1.1      2018-11-05 [1] CRAN (R 4.0.3)                
 sf                  0.9-6      2020-09-13 [1] CRAN (R 4.0.3)                
 shiny               1.5.0      2020-06-23 [1] CRAN (R 4.0.3)                
 sp                  1.4-4      2020-10-07 [1] CRAN (R 4.0.3)                
 stringi             1.5.3      2020-09-09 [1] CRAN (R 4.0.3)                
 stringr           * 1.4.0      2019-02-10 [1] CRAN (R 4.0.3)                
 tibble            * 3.0.4      2020-10-12 [1] CRAN (R 4.0.3)                
 tidyr             * 1.1.2      2020-08-27 [1] CRAN (R 4.0.3)                
 tidyselect          1.1.0      2020-05-11 [1] CRAN (R 4.0.3)                
 tidyverse         * 1.3.0      2019-11-21 [1] CRAN (R 4.0.3)                
 tweenr              1.0.1      2018-12-14 [1] CRAN (R 4.0.3)                
 units               0.6-7      2020-06-13 [1] CRAN (R 4.0.3)                
 vctrs               0.3.5      2020-11-17 [1] CRAN (R 4.0.3)                
 viridisLite         0.3.0      2018-02-01 [1] CRAN (R 4.0.3)                
 withr               2.3.0      2020-09-22 [1] CRAN (R 4.0.3)                
 xfun                0.19       2020-10-30 [1] CRAN (R 4.0.3)                
 xml2                1.3.2      2020-04-23 [1] CRAN (R 4.0.3)                
 xtable              1.8-4      2019-04-21 [1] CRAN (R 4.0.3)                
 yaml                2.2.1      2020-02-01 [1] CRAN (R 4.0.3)                

[1] C:/Users/usuario1/Documents/R/win-library/4.0
[2] C:/Program Files/R/R-4.0.2/library


LS0tDQp0aXRsZTogIkFOw4FMSVNJUyBERSBMQSBPRkVSVEEgQVVESU9WSVNVQUwgREUgTkVURkxJWCINCmF1dGhvcjogIk1hcnRhIE9saXZlcihvYmVsbWFyQGFsdW1uaS51di5lcykgXG4gXG4gQ2FybG9zIFJvZHJpZ3VleihjYXJvZ29uNEBhbHVtbmkudXYuZXMpICBcbiBcbiBNYXIgVmFsbGRlY2FicmVzKHZhbGxkZWNhQGFsdW1uaS51di5lcykuIFxuXG4gVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIg0KZGF0ZTogIkRpY2llbWJyZSBkZSAyMDIwIChhY3R1YWxpemFkbyBlbCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLSVtLSVZJylgKSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0aGVtZTogcGFwZXINCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlIA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNSANCiAgICB0b2NfZmxvYXQ6IA0KICAgICAgY29sbGFwc2VkOiB0cnVlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgZGZfcHJpbnQ6IGthYmxlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCmBgYHtyIHBhY2thZ2VzLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa2xpcHB5KSAgIy0gcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInJsZXN1ci9rbGlwcHkiKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ2dUaGVtZUFzc2lzdCkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGdhcG1pbmRlcikNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShyZWFjdGFibGUpDQpsaWJyYXJ5KGd0KQ0KYGBgDQoNCmBgYHtyIGNodW5rLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgI3Jlc3VsdHMgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgY2FjaGUgPSBGQUxTRSwgY2FjaGUucGF0aCA9ICIvY2FjaGVzLyIsIGNvbW1lbnQgPSAiIz4iLA0KICAgICAgICAgICAgICAgICAgICAgICNmaWcud2lkdGggPSA3LCAjZmlnLmhlaWdodD0gNywgICANCiAgICAgICAgICAgICAgICAgICAgICAjb3V0LndpZHRoID0gNywgb3V0LmhlaWdodCA9IDcsDQogICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLCAgZmlnLnNob3cgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDcvOSwgb3V0LndpZHRoID0gIjYwJSIsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGRldiA9ICJwbmciLCBkZXYuYXJncyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkNCmBgYA0KDQpgYGB7ciBvcHRpb25zLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgIy0gcGFyYSBxdWl0YXIgbGEgbm90YWNpw7NuIGNpZW50w61maWNhDQpvcHRpb25zKCJ5YW1sLmV2YWwuZXhwciIgPSBUUlVFKSANCmBgYA0KDQoNCmBgYHtyIGtsaXBweSwgZWNobyA9IEZBTFNFfQ0Ka2xpcHB5OjprbGlwcHkocG9zaXRpb24gPSBjKCJ0b3AiLCAicmlnaHQiKSkgIy0gcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInJsZXN1ci9rbGlwcHkiKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tDQoNClRyYWJham8gIGVsYWJvcmFkbyBwYXJhIGxhIGFzaWduYXR1cmEgIlByb2dyYW1hY2nDs24geSBtYW5lam8gZGUgZGF0b3MgZW4gbGEgZXJhIGRlbCBCaWcgRGF0YSIgZGUgbGEgVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIGR1cmFudGUgZWwgY3Vyc28gMjAyMC0yMDIxLiBMYSBww6FnaW5hIHdlYiBkZSBsYSBhc2lnbmF0dXJhIHB1ZWRlIHZlcnNlIGFxdcOtOiA8aHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjAtMjEtd2ViLz4uIExvcyB0cmFiYWpvcyBkZSBudWVzdHJvcyBjb21wYcOxZXJvcyBkZSBjdXJzbyBwdWVkZW4gdmVyc2UgW2FxdcOtXShodHRwczovL3BlcmV6cDQ0LmdpdGh1Yi5pby9pbnRyby1kcy0yMC0yMS13ZWIvMDctdHJhYmFqb3MuaHRtbCkuDQoNCi0tLS0tLS0tLS0tLS0tLQ0KDQo8YnI+DQoNCiMgMS4gSW50cm9kdWNjacOzbg0KDQpFc3RlIHRyYWJham8gY29uc2lzdGUgZW4gdW4gZXN0dWRpbyBkZSBsYXMgZGlmZXJlbnRlcyBwZWzDrWN1bGFzIHkgc2VyaWVzIGRlIG5ldGZsaXguIENvbiBlc3RlIGFuw6FsaXNpcyBxdWVyZW1vcyBwb25lciBlbiBwcsOhY3RpY2EgbG8gZXN0dWRpYWRvIGVuIGxhIGFzaWduYXR1cmEgZGUgUHJvZ3JhbWFjacOzbiB5IG1hbmVqbyBkZSBkYXRvcyBlbiBsYSBlcmEgZGVsIEJpZyBEYXRhLg0KDQojIDIuIMK/UXXDqSBlcz8NCg0KTmV0ZmxpeCBlcyB1biBzZXJ2aWNpbyBkZSBzdHJlYW1pbmcgcXVlIGZ1bmNpb25hIG1lZGlhbnRlIHN1c2NyaXBjacOzbiB5IHBlcm1pdGUgYSBzdXMgdXN1YXJpb3MgdmVyIHNlcmllcyB5IHBlbMOtY3VsYXMsIHNpbiBhbnVuY2lvcywgYSB0cmF2w6lzIGRlIGN1YWxxdWllciBkaXNwb3NpdGl2byBjb25lY3RhZG8gYSBpbnRlcm5ldC4gICANCg0KVGFtYmnDqW4gc2UgcHVlZGVuIGRlc2NhcmdhciBzZXJpZXMgeSBwZWzDrWN1bGFzIGVuIGN1YWxxdWllciBkaXNwb3NpdGl2byBpT1MsIEFuZHJvaWQsIG8gV2luZG93cyAxMCB5IHZlcmxhcyBzaW4gbmVjZXNpZGFkIGRlIGNvbmV4acOzbiBhIGludGVybmV0Lg0KDQohW0xvZ29dKC4vaW1hZ2VuZXMvRm90bzEuanBnKSANCg0KDQojIDMuIFVuIHBvY28gZGUgaGlzb3RyaWENCg0KTGEgY29tcGHDscOtYSBubyB0dXZvIMOpeGl0byBkZXNkZSB1biBjb21pZW56bywgcGVybyBsYXMgYnVlbmFzIGFjY2lvbmVzIGRlIHN1cyBkZXNhcnJvbGxhZG9yZXMgbGEgbGxldmFyb24gYSBvYnRlbmVyIGxhcyBnYW5hbmNpYXMgcXVlIHRpZW5lIGhveSBlbiBkw61hLg0KDQpFbiBzdXMgcHJpbmNpcGlvcywgTmV0ZmxpeCBlcmEgdW5hIGNvbXBhw7HDrWEgcXVlIGFscXVpbGFiYSBEVkTigJlzLCBzZSBmdW5kw7MgZW4gMTk5NywgeSBmdWUgZW4gMTk5OCBkb25kZSBhbHF1aWzDsyBzdSBwcmltZXIgRFZELiBMYSBlbXByZXNhIGNvbWVuesOzIGFscXVpbGFuZG8gcGVsw61jdWxhcyBwb3IgZXN0YSBtb2RhbGlkYWQuDQoNCg0KLSBFbiAyMDA3LCBOZXRmbGl4IGluaWNpYSBzdSBzZXJ2aWNpbyBkZSBWT0QgZW4gRXN0YWRvcyBVbmlkb3MgcGFyYSBjb21wdXRhZG9yYXMgcGVyc29uYWxlcy4gDQoNCi0gQSBwYXJ0aXIgZGUgMjAwOCBzZSBhZ3JlZ2FuIGRpZmVyZW50ZXMgb3BjaW9uZXMgcGFyYSBhY2NlZGVyIGFsIGNhdMOhbG9nbyBwb3IgcmV0cmFuc21pc2nDs24gZW4gZGlyZWN0by4gDQoNCi0gRW4gMjAwOSBzdSBjYXTDoWxvZ28gZsOtc2ljbyBvZnJlY2UgMTAwIG1pbCB0w610dWxvcyB5IHN1IGNsaWVudGVsYSBzdXBlcmEgbG9zIDEwIG1pbGxvbmVzIGRlIHN1c2NyaXB0b3Jlcy4NCg0KLSBFbiAyMDExLCBsYSBlbXByZXNhIGluaWNpYSBvcGVyYWNpb25lcyBwb3IgcHJpbWVyYSB2ZXogZnVlcmEgZGVsIHRlcnJpdG9yaW8gZXN0YWRvdW5pZGVuc2UgeSBjYW5hZGllbnNlLCBvZnJlY2llbmRvIHN1IGNhdMOhbG9nbyBwb3IgcmV0cmFuc21pc2nDs24gZW4gZGlyZWN0byBlbiBsYSByZWdpw7NuIGRlIEFtw6lyaWNhIExhdGluYSB5IGVsIENhcmliZS4gDQoNCi0gRW4gMjAxMiBvZnJlY2Ugc3VzIHNlcnZpY2lvcyBlbiBhbGd1bm9zIHBhw61zZXMgZGUgRXVyb3BhLiAgDQoNCi0gRW4gMjAxNiBvZnJlY2Ugc3VzIGNvbnRlbmlkb3MgYSB0b2RvIGVsIG11bmRvIGNvbiBleGNlcGNpw7NuIGRlIGxhIHJlZ2nDs24gZGUgQ3JpbWVhLCB5IGxvcyB0ZXJyaXRvcmlvcyBkZSBDb3JlYSBkZWwgTm9ydGUsIENoaW5hIHkgU2lyaWEuDQoNCg0KDQojIDQuIEFuw6FsaXNpcyBkZSBsYSBvZmVydGEgYXVkaW92aXN1YWwgZGUgTmV0ZmxpeA0KDQohW09mZXJ0YSBkZSBOZXRmbGl4XSguL2ltYWdlbmVzL0ZvdG8yLmpwZykNCg0KDQojIyA0LjEgRGF0b3MgYW5hbGl6YWRvcw0KDQpFbCBjb250ZW5pZG8gZGUgTmV0ZmxpeCB2YXLDrWEgc2Vnw7puIGxhIHJlZ2nDs24sIHkgcHVlZGUgY2FtYmlhciBjb24gZWwgdGllbXBvLiBTdSBvZmVydGEgaW5jbHV5ZSB1bmEgZ3JhbiB2YXJpZWRhZCBkZSBnYWxhcmRvbmFkb3MgdMOtdHVsb3Mgb3JpZ2luYWxlcyBkZSBOZXRmbGl4LCBzZXJpZXMsIHBlbMOtY3VsYXMsIGRvY3VtZW50YWxlcyB5IG11Y2hvIG3DoXMuDQoNCkEgbG8gbGFyZ28gZGUgZXN0ZSBhbsOhbGlzaXMgdmFtb3MgYSB1dGlsaXphciBsYXMgc2lndWllbnRlcyBydXRhcyBkZSBkYXRvcy4NCg0KDQpgYGB7ciwgaW5jbHVkZSA9IFRSVUUsIGVjaG89VFJVRX0NCm5ldGZsaXggPC0gcmVhZF9leGNlbCgiLi9EYXRvcy9uZXRmbGl4X3RpdGxlcy54bHN4IikNCm5ldGZsaXggPC0gbmV0ZmxpeCAlPiUgc2VsZWN0KC1zaG93X2lkLCAtY2FzdCwgLWRlc2NyaXB0aW9uLCAtcmF0aW5nKQ0Kc3VzY3JpcHRvcmVzIDwtIHJlYWRfZXhjZWwoIi4vRGF0b3Mvc3VzY3JpcHRvcmVzMTEueGxzeCIpDQpgYGANCg0KTGEgdGFibGEgJ25ldGZsaXgnIG5vcyBkYSBsb3MgZGF0b3MgZGUgbGFzIE1vdmllcyB5IFRWU2hvd3MgcXVlIE5ldGZsaXggdGllbmUgZW4gc3UgcMOhZ2luYS4gTm9zIGluZGljYSBlbCB0w610dWxvIGRlIGNhZGEgdW5hIGRlIGVsbGFzLCBzdSBkaXJlY3RvciwgbGEgY2l1ZGFkIGRvbmRlIGZ1ZXJvbiBwcm9kdWNpZGFzLCBsYSBmZWNoYSBxdWUgc2UgZXN0cmVuYXJvbiB5IGxhIHF1ZSBzZSBzdWJpZXJvbiBhIGxhIHBsYXRhZm9ybWEgZGUgTmV0ZmxpeCwgbGEgZHVyYWNpw7NuIHkgZWwgZ8OpbmVyby4NCg0KQ29uIGxhIGZ1bmNpw7NuIGFudGVyaW9yIGhlbW9zIGFycmVnbGFkbyBsb3MgZGF0b3MgZGUgbmV0ZmxpeF90aXRsZXMgeSBlbGltaW5hZG8gbGFzIGNvbHVtbmFzICdzaG93X2lkJywgJ2NvYXN0JywgJ2Rlc2NyaXB0aW9uJyB5ICdyYXRpaW5nJy4NCg0KDQoNCiMjIDQuMi4gR3LDoWZpY28gVFZTaG93cyBWcyBNb3ZpZXMgZW4gZWwgdGllbXBvIA0KDQpgYGB7ciwgZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFfQ0KY3VhdHJvIDwtIG5ldGZsaXggJT4lIGdyb3VwX2J5KHR5cGUsIHJlbGVhc2VfeWVhciklPiUgY291bnQoKQ0KY3VhdHJvMSA8LSBnZ3Bsb3QoY3VhdHJvLCBhZXMoeCA9IHJlbGVhc2VfeWVhciwgeSA9IG4pKSArIGdlb21fYXJlYShhZXMoY29sb3IgPSB0eXBlLCBmaWxsID0gdHlwZSksDQphbHBoYSA9IDAuNSwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoMC44KSkrIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiIzAwQUZCQiIsIiNFN0I4MDAiKSkrIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMDBBRkJCIiwiI0U3QjgwMCIpKQ0KY3VhdHJvMStsYWJzKHRpdGxlID0gIlRWU2hvd3MgeSBNb3ZpZXMgZW4gZWwgdGllbXBvIikNCg0KYGBgDQoNCkxhIGNvbXBhw7HDrWEgbm8gdHV2byDDqXhpdG8gZGVzZGUgdW4gY29taWVuem8sIHBlcm8gbGFzIGJ1ZW5hcyBhY2Npb25lcyBkZSBzdXMgZGVzYXJyb2xsYWRvcmVzIGxhIGxsZXZhcm9uIGEgb2J0ZW5lciBsYXMgZ2FuYW5jaWFzIHF1ZSB0aWVuZSBob3kgZW4gZMOtYS4NCg0KRW4gc3VzIHByaW5jaXBpb3MsIE5ldGZsaXggZXJhIHVuYSBjb21wYcOxw61hIHF1ZSBhbHF1aWxhYmEgRFZE4oCZcywgc2UgZnVuZMOzIGVuIDE5OTcsIHkgZnVlIGVuIDE5OTggZG9uZGUgYWxxdWlsw7Mgc3UgcHJpbWVyIERWRC4gTGEgZW1wcmVzYSBjb21lbnrDsyBhbHF1aWxhbmRvIHBlbMOtY3VsYXMgcG9yIGVzdGEgbW9kYWxpZGFkLg0KDQoNCiMjIDQuMyBQZWzDrWN1bGFzIHkgc2VyaWVzIG9yZGVuYWRhcyBwb3IgYcOxb3MgZGUgcHJvZHVjY2nDs24NCg0KTG8gcHJpbWVybyBxdWUgdmFtb3MgYSBoYWNlciBlcyBvcmRlbmFyIGxhcyBwZWzDrWN1bGFzIHkgc2VyaWVzIGRlIG3DoXMgYW50aWd1YSBhIG3DoXMgbnVldmEgeSBkZXNwdcOpcyBtb3ZlciBsYSBjb2x1bW5hICJyZWxlYXNlX3llYXIiIGEgbGEgaXpxdWllcmRhIGRlIHRvZG8uDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUV9DQpncmFmaWNvMiA8LSBuZXRmbGl4ICU+JSBhcnJhbmdlKHJlbGVhc2VfeWVhcikNCmdyYWZpY28yLjEgPC0gZ3JhZmljbzIgJT4lIHNlbGVjdChyZWxlYXNlX3llYXIsIGV2ZXJ5dGhpbmcoKSkNCg0KYGBgDQoNCkNvZ2llbmRvIGNvbW8gcmVmZXJlbmNpYSBsYSB0YWJsYSBkZWwgdHJhYmFqbyBkZSBOb2VsaWEgU8OhbmNoZXosIElnbmFjaW8gTW9udGF2YSB5IEFuZHJldSBFc3BhcnphLCBoZW1vcyByZWFsaXphZG8gbGEgc2lndWllbmUgdGFibGEgZW4gYSBxdWUgc2UgcHVlZGVuIGJ1c2NhciBsYXMgZGlzdGludGFzIE1vdmllcyB5IFRWIFNob3cgcG9yIGRpZmVyZW50ZXMgZmlsdHJvcy4NCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KDQpyZWFjdGFibGUoZ3JhZmljbzIuMSwgZGVmYXVsdFBhZ2VTaXplID0gIDEwLCAgcGFnaW5hdGlvblR5cGUgPSAianVtcCIsIHNob3dQYWdlU2l6ZU9wdGlvbnMgPSAgVFJVRSAsIHBhZ2VTaXplT3B0aW9ucyA9ICBjICggMTAgLCA1MCAsIDEwMCApLGRlZmF1bHRDb2xEZWYgPSBjb2xEZWYoDQogICAgYWxpZ24gPSAiY2VudGVyIiwNCiAgICBtaW5XaWR0aCA9IDcwLA0KICAgIGhlYWRlclN0eWxlID0gbGlzdChiYWNrZ3JvdW5kID0gInJlZCIpLA0KICAgIGZpbHRlcmFibGUgPSBUUlVFKSwgIGhpZ2hsaWdodCA9IFRSVUUsIG91dGxpbmVkID0gVFJVRSwNCiAgICBjb2x1bW5zID0gbGlzdCgNCiAgYE1vdmllcyZUVlNob3cvYcOxb2AgPSBjb2xEZWYoc3R5bGUgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIGlmICh2YWx1ZSA+IDApIHsNCiAgICAgIGNvbG9yIDwtICIjZTAwMDAwIn0NCiAgICAgIGVsc2Ugew0KICAgICAgY29sb3IgPC0gIiMwMDgwMDAiDQogICAgfQ0KICAgIGxpc3QoY29sb3IgPSBjb2xvciwgZm9udFdlaWdodCA9ICJib2xkIikNCiAgfSkpKQ0KDQpgYGANCg0KQ29tbyBwb2RlbW9zIG9ic2VydmFyIGVuIGxhIHRhYmxhIGFudGVyaW9yLCBsYSBzZXJpZSBtw6FzIGFudGlndWEgcXVlIGV4aXN0ZSBlbiBsYSBwbGF0YWZvcm1hIGRlIE5ldGZsaXggZXMgIlBpb25lZXJzOiBGaXJzdCBXb21lbiBGaWxtbWFrZXJzIg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRSwgb3V0LndpZHRoID0gIjUwJSIsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1hZ2VuZXMiLCAicHJpbWVyYV9zZXJpZS5qcGciKSApIA0KYGBgDQoNCkxhIHBlbMOtY3VsYSBtw6FzIGFudGlndWEgcXVlIHNlIGVuY3VlbnRyYSBlbiBsYSBwbGF0YWZvcm1hIGVzLCAiUHJlbHVkZSB0byBXYXIiLCB1bmEgcGVsw61jdWxhIGVzdGFkb3VuaWRlbnNlIGJhc2FkYSBlbiBsYSBTZWd1bmRhIEd1ZXJyYSBNdW5kaWFsIHkgY3V5byBkaXJlY3RvciBlcyBGcmFuayBDYXByYS4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUUsIG91dC53aWR0aCA9ICI1MCUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltYWdlbmVzIiwgInByaW1lcmFfcGVsaWN1bGEuanBnIikgKSANCmBgYA0KDQoNCiMjIDQuNCBMb3MgZGlleiBkaXJlY3RvcmVzIGNvbiBtw6FzIHBlbMOtY3VsYXMNCg0KRW4gbGEgc2lndWllbnRlIHRhYmxhIHNlIHB1ZWRlbiBvYnNlcnZhciBsb3MgZGlleiBkaXJlY3RvcmVzIHF1ZSBtw6FzIHBlbMOtY3VsYXMgaGFuIHJlYWxpemFkby4NCg0KYGBge3IsIGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRX0NCmdyYWZpY280IDwtIG5ldGZsaXggJT4lIGZpbHRlcih0eXBlID09ICJNb3ZpZSIpICU+JWdyb3VwX2J5KGRpcmVjdG9yKSAlPiUgc3VtbWFyaXNlKFBlbMOtY3VsYXM9bigpKSAlPiUgbmEub21pdChkYXRvcykgJT4lIHNsaWNlX21heChQZWzDrWN1bGFzLG4gPTEwKQ0KZ3JhZmljbzQxIDwtIGdyYWZpY280ICU+JSBtdXRhdGUoZGlyZWN0b3IgPSBmb3JjYXRzOjphc19mYWN0b3IoZGlyZWN0b3IpKQ0KDQpgYGANCg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQprbml0cjo6a2FibGUoZGlyZWN0b3IgPC0gZ3JhZmljbzQxKQ0KDQpgYGANCg0KRGUgZm9ybWEgbcOhcyB2aXN1YWwgc2UgcHVlZGUgb2JzZXJ2YXIgbG8gYW50ZXJpb3JtZW50ZSBtb3N0cmFkbyBlbiBlbCBzaWd1aWVudGUgZ3LDoWZpY28uIFJhw7psIENhbXBvcyB5IEphbiBTdXRlciBzb24gbG9zIGRpcmVjdG9yZXMgY29uIGRpZmVyZW5jaWEgcXVlIG3DoXMgcGVsw61jdWxhcyBoYW4gcmVhbGl6YWRvLg0KDQpgYGB7ciwgZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFfQ0KDQpncmFmaWNvZGlyZWN0b3JlczEgPC0gZ2dwbG90IChncmFmaWNvNDEsIGFlcyh4PWRpcmVjdG9yLCB5ID0gUGVsw61jdWxhcyksIGFlcyhmY3RfcmV2KGRpcmVjdG9yKSkpICsgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsID0gInJlZCIpICsgY29vcmRfZmxpcCgpICsgbGFicyh4ID0gIkRpcmVjdG9yIiwgeSA9ICJOw7ptZXJvIGRlIHBlbMOtY3VsYXMiKStsYWJzKHRpdGxlID0gIkRpZXogZGlyZWN0b3JlcyBjb24gbcOhcyBwZWzDrWN1bGFzIikNCmdncGxvdGx5KGdyYWZpY29kaXJlY3RvcmVzMSkNCmBgYA0KDQoNCiMjIDQuNSBMb3MgZMOtZXogcGHDrXNlcyBjb24gbcOhcyBwZWzDrWN1bGFzLiANCg0KRWwgcGHDrXMgY29uIG3DoXMgcGVsw61jdWxhcyBwcm9kdWNpZGFzIHF1ZSBoYXkgZW4gbGEgcGxhdGFmb3JtYSBkZSBOZXRmbGl4IGVzIEVzdGFkb3MgVW5pZG9zIHkgZWwgc2VndW5kbyBlcyBJbmRpYS4NCg0KU29ycHJlbmRlIHF1ZSBJbmRpYSBzZWEgZGUgbG9zIHBhaXNlcyBxdWUgdGllbmUgbcOhcyBwcm9kdWNjacOzbiBkZSBjaW5lIHkgZXN0byBzZSBkZWJlIGEgbGEgaW5kdXN0cmlhIGNpbmVtYXRvZ3LDoWZpY2EgdWJpY2FkYSBlbiB1bmEgZGUgc3VzIGNpdWRhZGVzIG3DoXMgcG9ibGFkYXMsIEJvbWJheS4gRXN0YSBoYSBkZXNiYW5jYWRvIGVuIGVsIG7Dum1lcm8gZGUgcHJvZHVjY2nDs24gZGUgcGVsw61jdWxhcyBhIEhvbGx5d29vZCwgeSBlcyBxdWUgZW4gQm9sbHl3b29kIHNlIHByb2R1Y2VuIGNhZGEgYcOxbyBtw6FzIGRlIDEuMDAwIGNpbnRhcyBvIHBlbMOtY3VsYXMuDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUV9DQpncmFmaWNvNCA8LSBuZXRmbGl4ICU+JSBmaWx0ZXIodHlwZSA9PSAiTW92aWUiKSAlPiVncm91cF9ieShjb3VudHJ5KSAlPiUgc3VtbWFyaXNlKFBhw61zZXM9bigpKSAlPiUgbmEub21pdChkYXRvcykgJT4lIHNsaWNlX21heChQYcOtc2VzLG4gPTEwKQ0KZ3JhZmljbzQxIDwtIGdyYWZpY280ICU+JSBtdXRhdGUoY291bnRyeSA9IGZvcmNhdHM6OmFzX2ZhY3Rvcihjb3VudHJ5KSkNCmQgPC0gZ2dwbG90IChncmFmaWNvNDEsYWVzKHg9Y291bnRyeSwgeSA9IFBhw61zZXMpLCBhZXMoZmN0X3Jldihjb3VudHJ5KSkpICsgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBmaWxsID0gImJsYWNrIikgKyBjb29yZF9mbGlwKCkNCmQgKyBsYWJzKHRpdGxlID0gIkdyw6FmaWNvIGRlIGxvcyAxMCBwYcOtc2VzIGNvbiBtw6FzIHBlbMOtY3VsYXMgcHJvZHVjaWRhcyIsDQogICAgICAgY2FwdGlvbiA9ICJEYXRvcyBwcm92ZW5pZW50ZXMgZGVsIG5ldGZsaXhfdGl0bGVzIGRhdGFzZXQiLA0KICAgICAgIHggPSAiUGHDrXMiLA0KICAgICAgIHkgPSAiTsO6bWVybyBkZSBQZWzDrWN1bGFzIiwNCiAgICAgICBjb2xvciA9ICJFc3BlY2llIGRlIGxpcmlvIikNCmBgYA0KDQpIZW1vcyBjcmVhZG8gdW4gbWFwYSBwYXJhIG1vc3RyYXIgZXN0b3MgZGlleiBwYWlzZXMuDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUV9DQp3b3JsZCA8LSBybmF0dXJhbGVhcnRoOjpuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKSANCndvcmxkMSA8LSB3b3JsZCAlPiUgZmlsdGVyIChhZG1pbiAlaW4lIGMoIkphcGFuIiwgIkhvbmcgS29uZyIsICJGcmFuY2UiLCAiTWV4aWNvIiwgIlR1cmtleSIsICJTcGFpbiIsICJDYW5hZGEiLCAiVW5pdGVkIEtpbmdkb20iLCAiSW5kaWEiLCAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIikpDQoNCndvcmxkMiA8LSB3b3JsZCAlPiUgZmlsdGVyKCEoYWRtaW4gJWluJSBjKCJKYXBhbiIsICJIb25nIEtvbmciLCAiRnJhbmNlIiwgIk1leGljbyIsICJUdXJrZXkiLCAiU3BhaW4iLCAiQ2FuYWRhIiwgIlVuaXRlZCBLaW5nZG9tIiwgIkluZGlhIiwgIlVuaXRlZCBTdGF0ZXMiKSkpDQoNCndvcmxkMyA8LSBnZ3Bsb3QgKCkgKyBnZW9tX3NmKGRhdGEgPSB3b3JsZDIpICsgZ2VvbV9zZihkYXRhID0gd29ybGQxLCBmaWxsID0gImJsYWNrIikgKyAgbGFicyh0aXRsZSA9ICJQYcOtc2VzIGNvbiBtw6FzIHBlbMOtY3VsYXMgZW4gTmV0ZmxpeCIsICBjYXB0aW9uID0gIkVsYWJvcmFjaW9uIHByb3BpYSIpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9IGdyYXkoLjgpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC4wNSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5IikpICsgY29vcmRfc2YoeGxpbSA9IGMoLTE2MCwgMTYwKSwgeWxpbSA9IGMoLTUwLCA4MCksIGV4cGFuZCA9IEZBTFNFKSArIA0KYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSAiMTQ4MiIsIHNpemUgPSA0LCB4ID0gLTcyLjUsIHkgPSA0MywgY29sb3IgPSAiUkVEIikgKw0KYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSAiODAiLCBzaXplID0gNCwgeCA9IC00LCB5ID0gNDIuNSwgY29sb3IgPSAiUkVEIikgKyANCmFubm90YXRlKGdlb20gPSAidGV4dCIsIGxhYmVsID0gIjE3MCIsIHNpemUgPSA0LCB4ID0gLTEsIHkgPSA1NSwgY29sb3IgPSAiUkVEIikgICsgDQphbm5vdGF0ZShnZW9tID0gInRleHQiLCBsYWJlbCA9ICI1MCIsIHNpemUgPSA0LCB4ID0gMywgeSA9IDUwLGNvbG9yID0gIlJFRCIpICsNCmFubm90YXRlKGdlb20gPSAidGV4dCIsIGxhYmVsID0gIjU1Iiwgc2l6ZSA9IDQsIHggPSAzNS4xOCwgeSA9IDM4Ljg0LCBjb2xvciA9ICJSRUQiKSArIA0KYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSAiNzI0Iiwgc2l6ZSA9IDQsIHggPSA3OS44OSwgeSA9IDIwLjk1LCBjb2xvciA9ICJSRUQiKSArIA0KYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSAiODgiLCBzaXplID0gNCwgeCA9IC0xMDEuMTEsIHkgPSA1NS4yOSwgY29sb3IgPSAiUkVEIikgKyANCmFubm90YXRlKGdlb20gPSAidGV4dCIsIGxhYmVsID0gIjU0Iiwgc2l6ZSA9IDQsIHggPSAtOTkuMjcsIHkgPSAxOS42NywgY29sb3IgPSAiUkVEIikrDQphbm5vdGF0ZShnZW9tID0gInRleHQiLCBsYWJlbCA9ICI0OSIsIHNpemUgPSA0LCB4ID0gMTE0LjEwLCB5ID0gMjIuMzksIGNvbG9yID0gIlJFRCIpKyANCmFubm90YXRlKGdlb20gPSAidGV4dCIsIGxhYmVsID0gIjQ3Iiwgc2l6ZSA9IDQsIHggPSAxMzkuNDEsIHkgPSAzNi43MiwgY29sb3IgPSAiUkVEIikNCndvcmxkMw0KYGBgDQoNCiMjIDQuNiBHcsOhZmljbyBwb3JjZW50YWplIFR2U2hvd3MgVnMgTW92aWVzDQoNCkNvbiBlc3RlIGdyw6FmaWNvIHBvZGVtb3MgdmVyIHF1ZSBlbiBsYSBvZmVydGEgZGUgTmV0ZmxpeCBwcmVkb21pbmFuIGxhcyBwZWzDrWN1bGFzIGZyZW50ZSBhIGxhcyBzZXJpZXMuIEVsIHBvcmNlbnRhamUgZGUgcGVsw61jdWxhcyBlcyBkZSBhcHJveGltYWRhbWVudGUgdW4gNjglIGZyZW50ZSBhbCAzMiUgZGUgc2VyaWVzLg0KDQpgYGB7ciwgZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFfQ0KZ3JhZmljbzYgPC0gbmV0ZmxpeCAlPiUgZ3JvdXBfYnkodHlwZSkgJT4lIHN1bW1hcmlzZShOTj1uKCkpICU+JSBtdXRhdGUocHJvYiA9IHByb3AudGFibGUoTk4pKjEwMCkNCmdyYWZpY282MSA8LSBnZ3Bsb3QoZ3JhZmljbzYsIGFlcyh4ID0gIiIsIHkgPSBwcm9iLCBmaWxsID0gcHJvYikpK2dlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgY29sb3IgPSAid2hpdGUiKSArIGdlb21fdGV4dChhZXMobGFiZWw9cHJvYikscG9zaXRpb249cG9zaXRpb25fc3RhY2sodmp1c3Q9MC41KSwgY29sb3I9IndoaXRlIiwgc2l6ZT01KSArIGNvb3JkX3BvbGFyKHRoZXRhPSJ5IikgKyB0aGVtZV92b2lkKCkNCmdyYWZpY282MStsYWJzKHRpdGxlID0gIk1vdmllcyBWcyBUdiBTSG93cyIpDQoNCmBgYA0KDQoNCiMjIDQuNyBMYXMgZGlleiBwZWzDrWN1bGFzIG3DoXMgbGFyZ2FzDQoNCkVuIGVzdGUgYXBhcnRhZG8gaGVtb3MgdGVuaWRvIHF1ZSBtb2RpZmljYXIgZW4gcHJpbWVyIGx1Z2FyLCBsYSBjb2x1bW5hIGRvbmRlIHNlIG1vc3RyYWJhIGxhIGR1cmFjacOzbiwgeWEgcXVlIGluaWNpYWxtZW50ZSBsYSBjZWxkYSBjb250ZW7DrWEgbGV0cmFzIHkgbsO6bWVyb3MgKGVqZW1wbG86IDkwIG1pbiksIHkgY3JlYXIgZG9zIG51ZXZhcyBjb2x1bW5hcyBkb25kZSBlbiB1bmEgcHVzaWVyYSBlbCBuw7ptZXJvIHkgZW4gbGEgb3RyYSBsYXMgbGV0cmFzLiBEZSBlc3RlIG1vZG8gcG9kZXIgdHJhYmFqYXIgbG9zIGRhdG9zLiBFbiBzZWd1bmRvIGx1Z2FyLCBoYWJpZW5kbyBjcmVhZG8gbGFzIGRvcyBjb2x1bW5hcywgaGVtb3MgdGVuaWRvIHF1ZSBtb2RpZmljYXIgZWwgZm9ybWF0byBkZSBsb3MgZGF0b3MgZGUgbGEgY29sdW1uYSBxdWUgY29udGVuw61hIGxvcyBuw7ptZXJvcywgeWEgcXVlIGVzdGFiYSBlbiBmb3JtYXRvIGxldHJhLCB5IG5vIGxlw61hIGJpZW4gbG9zIGRhdG9zLiANCkRpY2hvIGVzdG8sIGEgY29udGludWFjacOzbiBwb2RlbW9zIG9ic2VydmFyIGxhcyBkaWV6IHBlbMOtY3VsYXMgbcOhcyBsYXJnYXMgZGUgbGEgcGxhdGFmb3JtYSBOZXRmbGl4LiANCg0KDQpgYGB7ciwgZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFfQ0KaSA8LSAgIHNlcGFyYXRlKGRhdGEgPSBuZXRmbGl4LCBjb2wgPSAiZHVyYXRpb24iLCBpbnRvID0gYygiZHVyYWNpb24iLCAidGlwbyIpLCBzZXAgPSAiICIpICU+JSBtdXRhdGUoZHVyYWNpb24gPSBhcy5udW1lcmljKGR1cmFjaW9uKSkgJT4lIGZpbHRlciAodGlwbyA9PSAibWluIikgJT4lIHRvcF9uKGR1cmFjaW9uLCBuID0gMTApICU+JSBtdXRhdGUoZHVyYWNpb24gPSBmb3JjYXRzOjphc19mYWN0b3IoZHVyYWNpb24pKSANCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQprbml0cjo6a2FibGUoTW92aWVzIDwtIGkpDQoNCmBgYA0KDQoNCiMjIDQuOCBUViBTaG93cyBsYW56YWRvcyBwb3IgYcOxbyBkZSBwcm9kdWNjacOzbg0KDQpFbiBlc3RlIGFwYXJ0YWRvIGhlbW9zIGFpc2xhZG8gbG9zIGRhdG9zIGRlIFRWU2hvd3MgcGFyYSBwb2RlciByZWFsaXphciBlbCBncsOhZmljbyBjb3JyZXNwb25kaWVudGUuDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUV9DQppMiA8LSAgIHNlcGFyYXRlKGRhdGEgPSBuZXRmbGl4LCBjb2wgPSAiZHVyYXRpb24iLCBpbnRvID0gYygiZHVyYWNpb24iLCAidGlwbyIpLCBzZXAgPSAiICIpICU+JSBtdXRhdGUoZHVyYWNpb24gPSBhcy5udW1lcmljKGR1cmFjaW9uKSkgJT4lIGZpbHRlciAodGlwbyA9PSAiU2Vhc29uIikgJT4lIG11dGF0ZShkdXJhY2lvbiA9IGZvcmNhdHM6OmFzX2ZhY3RvcihkdXJhY2lvbikpIA0KYGBgDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUV9DQoNCmdyYWZpY280LjggPC0gaTIgJT4lIGdyb3VwX2J5KHJlbGVhc2VfeWVhcikgJT4lIHN1bW1hcmlzZShOTj1uKCkpDQpiIDwtIGdncGxvdCAoZ3JhZmljbzQuOCwgYWVzKHggPSByZWxlYXNlX3llYXIsIHkgPSBOTikpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic3RlZWxibHVlIikNCmIgKyBsYWJzKHRpdGxlID0gIkdyw6FmaWNvOiBUVlNob3dzIHBvciBhw7FvIiwNCiAgICAgICBzdWJ0aXRsZSA9ICIoZGlmZXJlbmNpYW5kbyBwb3IgYcOxbykiLA0KICAgICAgIGNhcHRpb24gPSAiRGF0b3MgcHJvdmVuaWVudGVzIGRlbCBuZXRmbGl4X3RpdGxlcyBkYXRhc2V0IiwNCiAgICAgICB4ID0gIlJlbGVhc2VfeWVhciIsDQogICAgICAgeSA9ICJOTiIsDQogICAgICAgY29sb3IgPSAiRXNwZWNpZSBkZSBsaXJpbyIpDQpgYGANCg0KIyA1LiBFdm9sdWNpw7NuIGRlIGxvcyBzdXNjcmlwdG9yZXMNCg0KYGBge3IsIGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRX0NCg0KDQpzdXNjcmlwdG9yZXMgJT4lDQogIGdncGxvdCggYWVzKHg9QcOxbywgeT1TdXNjcmlwdG9ycywgZ3JvdXA9Wm9uYXNfZ2VvZ3LDoWZpY2FzLCBjb2xvcj1ab25hc19nZW9ncsOhZmljYXMpKSArDQogICAgZ2VvbV9saW5lKCkgKw0KICAgIGdlb21fcG9pbnQoKSArIA0KICAgICAgdHJhbnNpdGlvbl9yZXZlYWwoQcOxbykNCg0KYGBgDQoNCiAgICAgIA0KICAgICAgDQpDb24gZXN0ZSBncsOhZmljbyBwb2RlbW9zIHZlciBsYSBldm9sdWNpw7NuIGRlIGxvcyAgbnVldm9zIHN1c2NyaXB0b3JlcyBhbmFsaXphbmRvIGxvcyBkYXRvcyBkZWwgbWVzIGRlIGVuZXJvIGRlIGxvcyBhw7FvcyAyMDE4LCAyMDE5IHkgMjAyMC4NCg0KUG9kZW1vcyBvYnNlcnZhciBxdWUgRXVyb3BhIGVzIGxhIHF1ZSBoYSBleHBlcmltZW50YWRvIHVuIG1heW9yIGNyZWNpbWllbnRvIGRlIHN1c2NyaXB0b3JlcyBkZXNkZSBoYWNlIHRyZXMgYcOxb3MgaGFzdGEgYWhvcmEgY29uIHVuYSBkaWZlcmVuY2lhIGRlIG1hcyBkZSA0MC4wMDAgc3VzY3JpcHRvcmVzIGVuIGVzdGUgbWVzIGRlc2RlIDIwMTggaGFzdGEgMjAyMC4NCg0KRUVVVSB5IENhbmFkw6EgeWEgY29udGFiYW4gY29uIHVuIGdyYW4gbsO6bWVybyBkZSBzdXNjcmlwdG9yZXMgZW4gbWFyem8gZGUgMjAxOCB5IHNpZ3VlbiBzaWVuZG8gbGEgem9uYSBxdWUgbWFzIHN1c2NyaXB0b3JlcyB0aWVuZW4uIEFsIG1pc21vIHRpZW1wbyBxdWUgbGEgem9uYSBkZSBBc2lhIHRpZW5lbiB1biBuw7ptZXJvIG11Y2hvIG1lbm9yLg0KDQpObyBoZW1vcyBwb2RpZG8gZW5jb250cmFyIGxvcyBkYXRvcyBkZSBlc3RlIGHDsW8gZW50ZXJvcyBwYXJhIHBvZGVyIHZlciBsYSBldm9sdWNpw7NuIHBlcm8gc8OtIHNlIHB1ZWRlIGFmaXJtYXIgcXVlIE5ldGZsaXggaGEgZHVwbGljYWRvIGVsIG7Dum1lcm8gZGUgc3VzY3JpcHRvcmVzIGdyYWNpYXMgYSBsYSBjdWFyZW50ZW5hIHBvciBlbCBjb3JvbmF2aXJ1cyBkdXBsaWNhbmRvIHRhbWJpw6luIHN1cyBiZW5lZmljaW9zIHkgbGFzIGV4cGVjdGF0aXZhcyBwYXJhIGVzdGUgcGVyaW9kby4NCg0KIyA1LiBCaWJsaW9ncmFmw61hDQoNCi0gW2VubGFjZSBhIGxhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmFdKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIwLTIxLXdlYi8wNC10dXRvcmlhbGVzLmh0bWwpDQotIFtlbmxhY2UgZ2FsZXJpYSBkZSBncsOhZmljb3MgZGUgZ2dwbG90Ml0oaHR0cHM6Ly93d3cuci1ncmFwaC1nYWxsZXJ5LmNvbS8pDQotIFtyZXBvc2l0b3JpbyBkZSBsb3MgZGF0b3MgZGVsIHRyYWJham9dKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vc2hpdmFtYi9uZXRmbGl4LXNob3dzKQ0KDQojIDYuIFNlc2nDs24gSW5mb3JtYXRpdmENCg0KYGBge3J9DQogICAgc2Vzc2lvbmluZm86OnNlc3Npb25faW5mbygpICU+JSBkZXRhaWxzOjpkZXRhaWxzKHN1bW1hcnkgPSAnY3VycmVudCBzZXNzaW9uIGluZm8nKQ0KYGBgDQoNCg0KDQo=