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


Resumen: Podríamos decir que, aunque en las últimas décadas muchos deportes han ganado popularidad, el fútbol es el deporte más extendido y seguido por aficionados, al menos a nivel europeo. Además, otros continentes como América o Ásia que no han tenido una cultura histórica futbolera como en Europa, están pasando por un proceso de extensión de dicho deporte en sus territorios. Sin embargo, la opinión popular de los aficionados nos dice que las mejores competiciones se juegan en Europa. Por ello, voy a analizar las 5 principales ligas de fútbol europeo.

Competiciones a analizar: La Liga (liga española), Bundesliga (Liga alemana), Serie A (Liga italiana), Premier League (Liga inglesa) y Ligue 1 (Liga fracesa).



2. Datos

Comentarios

Como se ha comentado a lo largo del curso y, tras mi experiencia trabajando con datos del INE en el Trabajo de Equipo, la principal problemática suele girar entorno al estado en que recibimos los datos. En mi caso, he trabajado con datos obtenidos de la plataforma Kaggle, plataforma dedicada al posteo de data frames. Esto ha hecho que los datos con los que he trabajado estubieran muy arreglados. Simplemente he tenido que renombrar y seleccionar.



Datos

#Importamos al Global Environment el archivo descargado de Kaggle
df_futbol <- rio::import("./datos/Football teams.csv")

#La unica limpieza que hacemos son los nombres, para poner los que tenemos más familiarizados
df_futbol <- df_futbol %>% 
  rename(Equipo = Team, Liga=Tournament, Tiros=Shots, Amarillas=yellow_cards, Rojas=red_cards, Goles=Goals)

Referencias

Como he comentado anteriormente, Kaggle es una plataforma que, entre otras funciones, sirve para postear trabajos relacionados con los datos. Lo curioso es que puedes encontrar datos de todo tipo. Desde precios de activos financieros hasta datos deportivos. En mi caso me he basado en datos de los siguientes usuarios :

varpit94
TANUJLEOMESSI
AHMET ÇALIŞ
RUPESH KR SINGH
RIBACKI

3. Liga más goleadora

Análisis


En este gráfico, se puede apreciar el máximo y el mínimo de goles anotados por un equipo de cada liga, así como el número promedio de goles que se han marcado en esa liga. Por tanto, podemos ver que el equipo que más goles ha anotado juega en la Bundesliga, el equipo que menos tantos ha conseguido juega para la Premier League. Además, por término medio, la Bundesliga es la competición con más goles y La Liga es la que menos tiene.



Código

p1 <- ggplot (data= df_futbol, aes (x=Liga, y=Goles, fill=Liga))+
  geom_boxplot() + 
  labs(title = "Gráfico 1: Goles por Liga",
        fill = "Competición" ) +
  theme_dark()+
  theme(legend.position = "none") +
  theme(text = element_text(face = "bold"))

ggplotly(p1)


4. Equipos más y menos goleadores (Top 10)

Análisi


En este caso se pueden observar el TOP 10 de los equipos con más goles y con menos goles. Nos encontramos con que la Bundesliga tiene 4 equipos dentro del TOP 10 de más anotadores, cosa que concuerda con lo explicado en el Punto 3. Por otra parte, otro hecho destacable es que la Serie A no tiene ningún equipo en el TOP 10 menos goleadores.

Cabe destacar que, aunque es un TOP 10, aparecen + - 10 equipos debido a que hay empate en el número de goles.



Más goleadores



Menos goleadores



Código

df_mas <- df_futbol %>% 
  filter(min_rank(desc(Goles))<10)

df_menos <- df_futbol %>% 
  filter(min_rank(Goles)<10)

pmas <- ggplot(data= df_mas, aes(x=Equipo, y=Goles))+
  geom_bar(stat="identity",aes(fill=Liga),colour="Black")+
  labs(title= "Top10 equipos más goleadores")+
  theme(text = element_text(face = "bold")) + theme_minimal()


ggplotly(pmas)

pmenos <- ggplot(data= df_menos, aes(x=Equipo, y=Goles))+
  geom_bar(stat="identity",aes(fill=Liga),colour="Black")+
  labs(title= "Top10 equipos menos goleadores")+
  theme(text = element_text(face = "bold"))+ theme_minimal()

pmenos <- pmenos + lims(y=c(0,100))

ggplotly(pmenos)

p2 <- pmas + pmenos 

p2


5. Goles por Liga

Análisis


Antes que nada, hay que destacar que he elegido establecer una escala libre en cada competición para poder exagerar las formas y que sea más visual. Por tanto, a la hora de analizar hay que tener en cuenta la escala del eje y. Podemos apreciar que, como se ha demostrado anteriormente, la Serie A, aunque concentra muchos de sus equipos en la parte bja del gráfico: rango de goles 40-60, no tiene ningún equipo que anote menos de 39 goles, a diferencia de lo que ocurre por ejemplo en la Premier League, donde hay un equipo con 19 goles.


Código

p3 <- ggplot(data= df_futbol,  aes(x=Liga, y=Goles, fill=Liga)) +
  geom_violin() +  
  facet_wrap(Liga~., scales = "free")+
  geom_jitter() +
  theme_classic()+
  theme(legend.position = "none")

ggplotly(p3)

6. ¿Qué hacen los que más marcan?

Análisis



En esta ocasión se intenta demostrar si hay una relación entre el % de posesión, la cantidad de tiros por partido y el número de goles anotados. La pregunta que nos podríamos hacer sería: ¿Los que más marcan son los que mas tiros hacen y más mantienen el balón?. Primero que nada se puede observar que la línea de tendencia es creciente, cosa que se traduce en que a medida que el % de posesión y el número de tiros aumentan, tambien lo hace el número de goles. Además, se puede observar que el equipo que más posesión tiene se encuentra en La Liga y hemos visto anteriormente que no es el más goleador. Por tanto, como el más goleador se encuentra en la Bundesliga, para ver quien es el que más goles marcará, influye en mayor medida el número de tiros que se hacen por partido.


código

p4 <- ggballoonplot(data= df_futbol ,x="Possession", y="Tiros", fill="Liga")+
  theme_classic()+
  labs(title = "Grafico 4: Relación Posesión-Tiros-Goles")+
  geom_smooth(color="black")

p4


7. Equipos más amonestados

Análisis


En esta ocasión se pretende mostrar los 10 equipos con más tarjetas, tanto rojas como amarillas. El equipo más “duro” fué el Getafe, de La Liga, el cual también está dentro del TOP3 tarjetas rojas. El equipo con más amonestaciones graves (tarjetas rojas) es el Marseille, de la Ligue 1, con un total de 9 rojas.



Código

df_5 <- df_futbol %>% 
  group_by(Liga) %>% 
  mutate(Total = Amarillas + Rojas) %>% 
  select(Equipo ,Amarillas, Rojas, Total ) %>% 
  top_n(2, Total)


p5 <- ggplot(df_5) +
  aes(x = Equipo, fill = Rojas, weight = Total) +
  geom_bar() +
  scale_fill_distiller(palette = "Reds", direction = 1) +
  labs(x = "Equipo",
       y ="Total Tarjetas",
       title = "Top 10 equipos más amonestados",
       subtitle = "Tarjetas amarillas y rojas",
       fill = "Rojas") +
  ggthemes::theme_base()

ggplotly(p5)


8. Ranking

Análisis


Por último, he querido mostrar la valoración general (Rating) de todos los equipos. Se puede apreciar que el mejor equipo en la temporada 20/21 fué el Manchester City, de la liga inglesa, mientras que el peor fué el Schalke 04, de la liga alemana. Cabe destacar también que los ingleses tienen la mayor parte de sus equipos en el rango de rating 6.6 - 7


código

p6 <- ggplot(df_futbol, aes(x=Equipo, y=Rating, fill=Liga))+
  geom_point()+
  facet_grid(cols=vars(Liga))+
  theme(legend.position = "none")+
  labs(title="Rating de los equipos")

ggplotly(p6)


9. Conclusiones

Se han analizado parámetros de las que son consideradas cómo las mejores ligas europeas, pero ¿cual es la mejor liga?. Esto depende del gusto de cada aficionado, pero el consenso general nos dice que esta decisión va variando. Hasta la temporada, aproximadamente, 18/19, La Liga (liga española) era considerada la mejor, con equipos que dieron mucho espectáculo y con mucha calidad de fútbol (ejemplo, el gran % de posesión actual de sus equipos). Hoy por hoy, los ingleses son considerados como los principales creadores de espectáculo futbolístico, entre otras, gracias a su velocidad de juego

10. Bibliografía

Kaggle
rPubs
ggPlot
Tutoriales



Información de mi R-sesión:

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

- Packages -------------------------------------------------------------------
 package       * version    date       lib source                        
 abind           1.4-5      2016-07-21 [1] CRAN (R 4.1.1)                
 assertthat      0.2.1      2019-03-21 [1] CRAN (R 4.1.1)                
 backports       1.2.1      2020-12-09 [1] CRAN (R 4.1.1)                
 broom           0.7.9      2021-07-27 [1] CRAN (R 4.1.1)                
 bslib           0.3.1      2021-10-06 [1] CRAN (R 4.1.1)                
 car             3.0-12     2021-11-06 [1] CRAN (R 4.1.2)                
 carData       * 3.0-4      2020-05-22 [1] CRAN (R 4.1.1)                
 cellranger      1.1.0      2016-07-27 [1] CRAN (R 4.1.1)                
 class           7.3-19     2021-05-03 [2] CRAN (R 4.1.1)                
 classInt        0.4-3      2020-04-07 [1] CRAN (R 4.1.1)                
 cli             3.0.1      2021-07-17 [1] CRAN (R 4.1.1)                
 clipr           0.7.1      2020-10-08 [1] CRAN (R 4.1.1)                
 colorspace      2.0-2      2021-06-24 [1] CRAN (R 4.1.1)                
 crayon          1.4.2      2021-10-29 [1] CRAN (R 4.1.1)                
 crosstalk     * 1.1.1      2021-01-12 [1] CRAN (R 4.1.1)                
 curl            4.3.2      2021-06-23 [1] CRAN (R 4.1.1)                
 data.table      1.14.0     2021-02-21 [1] CRAN (R 4.1.1)                
 DBI             1.1.1      2021-01-15 [1] CRAN (R 4.1.1)                
 dbplyr          2.1.1      2021-04-06 [1] CRAN (R 4.1.1)                
 desc            1.4.0      2021-09-28 [1] CRAN (R 4.1.1)                
 details         0.2.1      2020-01-12 [1] CRAN (R 4.1.1)                
 digest          0.6.28     2021-09-23 [1] CRAN (R 4.1.1)                
 dplyr         * 1.0.7      2021-06-18 [1] CRAN (R 4.1.1)                
 e1071           1.7-8      2021-07-28 [1] CRAN (R 4.1.1)                
 ellipsis        0.3.2      2021-04-29 [1] CRAN (R 4.1.1)                
 evaluate        0.14       2019-05-28 [1] CRAN (R 4.1.1)                
 extrafont       0.17       2014-12-08 [1] CRAN (R 4.1.1)                
 extrafontdb     1.0        2012-06-11 [1] CRAN (R 4.1.1)                
 fansi           0.5.0      2021-05-25 [1] CRAN (R 4.1.1)                
 farver          2.1.0      2021-02-28 [1] CRAN (R 4.1.1)                
 fastmap         1.1.0      2021-01-25 [1] CRAN (R 4.1.1)                
 forcats       * 0.5.1      2021-01-27 [1] CRAN (R 4.1.1)                
 foreign         0.8-81     2020-12-22 [2] CRAN (R 4.1.1)                
 formatR         1.11       2021-06-01 [1] CRAN (R 4.1.1)                
 fs              1.5.0      2020-07-31 [1] CRAN (R 4.1.1)                
 gdtools         0.2.3      2021-01-06 [1] CRAN (R 4.1.1)                
 generics        0.1.1      2021-10-25 [1] CRAN (R 4.1.1)                
 gganimate     * 1.0.7      2020-10-15 [1] CRAN (R 4.1.1)                
 ggplot2       * 3.3.5      2021-06-25 [1] CRAN (R 4.1.1)                
 ggpubr        * 0.4.0      2020-06-27 [1] CRAN (R 4.1.2)                
 ggrepel       * 0.9.1      2021-01-15 [1] CRAN (R 4.1.2)                
 ggsignif        0.6.3      2021-09-09 [1] CRAN (R 4.1.2)                
 ggThemeAssist * 0.1.5      2016-08-13 [1] CRAN (R 4.1.1)                
 ggthemes        4.2.4      2021-01-20 [1] CRAN (R 4.1.1)                
 gifski          1.4.3-1    2021-05-02 [1] CRAN (R 4.1.2)                
 glue            1.5.0      2021-11-07 [1] CRAN (R 4.1.2)                
 gtable          0.3.0      2019-03-25 [1] CRAN (R 4.1.1)                
 haven           2.4.3      2021-08-04 [1] CRAN (R 4.1.1)                
 highr           0.9        2021-04-16 [1] CRAN (R 4.1.1)                
 hms             1.1.0      2021-05-17 [1] CRAN (R 4.1.1)                
 hrbrthemes    * 0.8.0      2020-03-06 [1] CRAN (R 4.1.1)                
 htmltools       0.5.2      2021-08-25 [1] CRAN (R 4.1.1)                
 htmlwidgets     1.5.4      2021-09-08 [1] CRAN (R 4.1.1)                
 httpuv          1.6.3      2021-09-09 [1] CRAN (R 4.1.1)                
 httr            1.4.2      2020-07-20 [1] CRAN (R 4.1.1)                
 jquerylib       0.1.4      2021-04-26 [1] CRAN (R 4.1.1)                
 jsonlite        1.7.2      2020-12-09 [1] CRAN (R 4.1.1)                
 KernSmooth      2.23-20    2021-05-03 [2] CRAN (R 4.1.1)                
 klippy        * 0.0.0.9500 2021-11-30 [1] Github (rlesur/klippy@378c247)
 knitr         * 1.36       2021-09-29 [1] CRAN (R 4.1.1)                
 labeling        0.4.2      2020-10-20 [1] CRAN (R 4.1.1)                
 later           1.3.0      2021-08-18 [1] CRAN (R 4.1.1)                
 lattice         0.20-44    2021-05-02 [2] CRAN (R 4.1.1)                
 lazyeval        0.2.2      2019-03-15 [1] CRAN (R 4.1.1)                
 lifecycle       1.0.1      2021-09-24 [1] CRAN (R 4.1.1)                
 lubridate       1.7.10     2021-02-26 [1] CRAN (R 4.1.1)                
 magrittr        2.0.1      2020-11-17 [1] CRAN (R 4.1.1)                
 Matrix          1.3-4      2021-06-01 [2] CRAN (R 4.1.1)                
 mgcv            1.8-36     2021-06-01 [2] CRAN (R 4.1.1)                
 mime            0.12       2021-09-28 [1] CRAN (R 4.1.1)                
 miniUI          0.1.1.1    2018-05-18 [1] CRAN (R 4.1.1)                
 modelr          0.1.8      2020-05-19 [1] CRAN (R 4.1.1)                
 munsell         0.5.0      2018-06-12 [1] CRAN (R 4.1.1)                
 nlme            3.1-152    2021-02-04 [2] CRAN (R 4.1.1)                
 openxlsx        4.2.4      2021-06-16 [1] CRAN (R 4.1.1)                
 patchwork     * 1.1.1      2020-12-17 [1] CRAN (R 4.1.1)                
 pillar          1.6.4      2021-10-18 [1] CRAN (R 4.1.1)                
 pkgconfig       2.0.3      2019-09-22 [1] CRAN (R 4.1.1)                
 plotly        * 4.9.4.1    2021-06-18 [1] CRAN (R 4.1.1)                
 png             0.1-7      2013-12-03 [1] CRAN (R 4.1.1)                
 prettyunits     1.1.1      2020-01-24 [1] CRAN (R 4.1.1)                
 progress        1.2.2      2019-05-16 [1] CRAN (R 4.1.1)                
 promises        1.2.0.1    2021-02-11 [1] CRAN (R 4.1.1)                
 proxy           0.4-26     2021-06-07 [1] CRAN (R 4.1.1)                
 purrr         * 0.3.4      2020-04-17 [1] CRAN (R 4.1.1)                
 R6              2.5.1      2021-08-19 [1] CRAN (R 4.1.1)                
 RColorBrewer  * 1.1-2      2014-12-07 [1] CRAN (R 4.1.1)                
 Rcpp            1.0.7      2021-07-07 [1] CRAN (R 4.1.1)                
 reactable     * 0.2.3      2020-10-04 [1] CRAN (R 4.1.1)                
 readr         * 2.0.1      2021-08-10 [1] CRAN (R 4.1.1)                
 readxl        * 1.3.1      2019-03-13 [1] CRAN (R 4.1.1)                
 reprex          2.0.1      2021-08-05 [1] CRAN (R 4.1.1)                
 rio           * 0.5.27     2021-06-21 [1] CRAN (R 4.1.1)                
 rlang           0.4.12     2021-10-18 [1] CRAN (R 4.1.1)                
 rmarkdown       2.11       2021-09-14 [1] CRAN (R 4.1.1)                
 rprojroot       2.0.2      2020-11-15 [1] CRAN (R 4.1.1)                
 rstatix         0.7.0      2021-02-13 [1] CRAN (R 4.1.2)                
 rstudioapi      0.13       2020-11-12 [1] CRAN (R 4.1.1)                
 Rttf2pt1        1.3.9      2021-07-22 [1] CRAN (R 4.1.1)                
 rvest           1.0.1      2021-07-26 [1] CRAN (R 4.1.1)                
 sass            0.4.0      2021-05-12 [1] CRAN (R 4.1.1)                
 scales          1.1.1      2020-05-11 [1] CRAN (R 4.1.1)                
 sessioninfo     1.1.1      2018-11-05 [1] CRAN (R 4.1.1)                
 sf            * 1.0-2      2021-07-26 [1] CRAN (R 4.1.1)                
 shiny           1.7.1      2021-10-02 [1] CRAN (R 4.1.1)                
 stringi       * 1.7.5      2021-10-04 [1] CRAN (R 4.1.1)                
 stringr       * 1.4.0      2019-02-10 [1] CRAN (R 4.1.1)                
 systemfonts     1.0.3      2021-10-13 [1] CRAN (R 4.1.1)                
 tibble        * 3.1.5      2021-09-30 [1] CRAN (R 4.1.1)                
 tidyr         * 1.1.3      2021-03-03 [1] CRAN (R 4.1.1)                
 tidyselect      1.1.1      2021-04-30 [1] CRAN (R 4.1.1)                
 tidyverse     * 1.3.1      2021-04-15 [1] CRAN (R 4.1.1)                
 tweenr          1.0.2      2021-03-23 [1] CRAN (R 4.1.1)                
 tzdb            0.1.2      2021-07-20 [1] CRAN (R 4.1.1)                
 units           0.7-2      2021-06-08 [1] CRAN (R 4.1.1)                
 utf8            1.2.2      2021-07-24 [1] CRAN (R 4.1.1)                
 vctrs           0.3.8      2021-04-29 [1] CRAN (R 4.1.1)                
 viridisLite     0.4.0      2021-04-13 [1] CRAN (R 4.1.1)                
 withr           2.4.2      2021-04-18 [1] CRAN (R 4.1.1)                
 xfun            0.28       2021-11-04 [1] CRAN (R 4.1.2)                
 xml2            1.3.2      2020-04-23 [1] CRAN (R 4.1.1)                
 xtable          1.8-4      2019-04-21 [1] CRAN (R 4.1.1)                
 yaml            2.2.1      2020-02-01 [1] CRAN (R 4.1.1)                
 zip             2.2.0      2021-05-31 [1] CRAN (R 4.1.1)                

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






LS0tDQp0aXRsZTogIk1FSk9SRVMgTElHQVMgRVVST1BFQVMgREUgRsOaVEJPTCINCnN1YnRpdGxlOiAiUnViw6luIENhbXBvcyBDYW1wb3MgKHJ1Y2FtY2FtQGFsdW1uaS51di5lcykiICMtIHBvbmdvIHTDuiBub21icmUgYWjDrSBwYXJhIHEgYXBhcmV6Y2EgbcOhcyBncmFuZGUgcSBlbCBkZSBsYSBVVg0KYXV0aG9yOiAiVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIg0KZGF0ZTogIkRpY2llbWJyZSBkZSAyMDIxIChhY3R1YWxpemFkbyBlbCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLSVtLSVZJylgKSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICAjY3NzOiAiLi9hc3NldHMvbXlfY3NzX2ZpbGUuY3NzIg0KICAgIHRoZW1lOiBwYXBlcg0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUgDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzIA0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBkZl9wcmludDoga2FibGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlDQotLS0NCg0KYGBge3IgcGFja2FnZXMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShrbGlwcHkpICAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHJlYWN0YWJsZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoc3RyaW5naSkNCmxpYnJhcnkoZ2dUaGVtZUFzc2lzdCkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShwYXRjaHdvcmspDQpsaWJyYXJ5KGdncmVwZWwpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShjcm9zc3RhbGspDQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCmxpYnJhcnkoaHJicnRoZW1lcykNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkocmlvKQ0KbGlicmFyeShnZ2FuaW1hdGUpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZ2dwdWJyKSAjaW5zdGFsbC5wYWNrYWdlcygiZ2dwdWJyIikNCmxpYnJhcnkoY2FyRGF0YSkgI2luc3RhbGwucGFja2FnZXMoImNhckRhdGEiKQ0KYGBgDQoNCmBgYHtyIGNodW5rLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgI3Jlc3VsdHMgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgY2FjaGUgPSBGQUxTRSwgY2FjaGUucGF0aCA9ICIvY2FjaGVzLyIsIGNvbW1lbnQgPSAiIz4iLA0KICAgICAgICAgICAgICAgICAgICAgICNmaWcud2lkdGggPSA3LCAjZmlnLmhlaWdodD0gNywgICANCiAgICAgICAgICAgICAgICAgICAgICAjb3V0LndpZHRoID0gNywgb3V0LmhlaWdodCA9IDcsDQogICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLCAgZmlnLnNob3cgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDAuNjI4LCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLmFsaWduID0gImNlbnRlciIpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZGV2ID0gInBuZyIsIGRldi5hcmdzID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKQ0KYGBgDQoNCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KDQpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmBgYA0KDQo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBqdXN0aWZ5Ij48ZGl2Lz4NCg0KPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+DQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gY2FzaSBpZ3VhbCwgc29sbyBIQVMgZGUgU1VTVElUVUlSICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+DQpUcmFiYWpvIGVsYWJvcmFkbyBwYXJhIGxhIGFzaWduYXR1cmEgIlByb2dyYW1hY2nDs24geSBtYW5lam8gZGUgZGF0b3MgZW4gbGEgZXJhIGRlbCBCaWcgRGF0YSIgZGUgbGEgVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIGR1cmFudGUgZWwgY3Vyc28gMjAyMS0yMDIyLiBFbCByZXBvIGRlbCB0cmFiYWpvIGVzdMOhIFthcXXDrV0oaHR0cHM6Ly9naXRodWIuY29tL1J1Y2FtY2FtL3RyYWJham9fQmlnRGF0YSl7dGFyZ2V0PSJfYmxhbmsifS4gDQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gZXhhY3RhbWVudGUgaWd1YWwsIE5PIEhBUyBERSBDQU1CSUFSIE5BREEtLT4NCg0KTGEgcMOhZ2luYSB3ZWIgZGUgbGEgYXNpZ25hdHVyYSB5IGxvcyB0cmFiYWpvcyBkZSBtaXMgY29tcGHDsWVyb3MgcHVlZGVuIHZlcnNlIFthcXXDrV0oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLzA3LXRyYWJham9zLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uDQoNCg0KPGhyIGNsYXNzPSJsaW5lYS1yZWQiPg0KDQojIDEuIEludHJvZHVjY2nDs24NCjxicj4NCioqUmVzdW1lbjoqKiBQb2Ryw61hbW9zIGRlY2lyIHF1ZSwgYXVucXVlIGVuIGxhcyDDumx0aW1hcyBkw6ljYWRhcyBtdWNob3MgZGVwb3J0ZXMgaGFuIGdhbmFkbyBwb3B1bGFyaWRhZCwgZWwgZsO6dGJvbCBlcyBlbCBkZXBvcnRlIG3DoXMgZXh0ZW5kaWRvIHkgc2VndWlkbyBwb3IgYWZpY2lvbmFkb3MsIGFsIG1lbm9zIGEgbml2ZWwgZXVyb3Blby4gQWRlbcOhcywgb3Ryb3MgY29udGluZW50ZXMgY29tbyBBbcOpcmljYSBvIMOBc2lhIHF1ZSBubyBoYW4gdGVuaWRvIHVuYSBjdWx0dXJhIGhpc3TDs3JpY2EgZnV0Ym9sZXJhIGNvbW8gZW4gRXVyb3BhLCBlc3TDoW4gcGFzYW5kbyBwb3IgdW4gcHJvY2VzbyBkZSBleHRlbnNpw7NuIGRlIGRpY2hvIGRlcG9ydGUgZW4gc3VzIHRlcnJpdG9yaW9zLiBTaW4gZW1iYXJnbywgbGEgb3BpbmnDs24gcG9wdWxhciBkZSBsb3MgYWZpY2lvbmFkb3Mgbm9zIGRpY2UgcXVlIGxhcyBtZWpvcmVzIGNvbXBldGljaW9uZXMgc2UganVlZ2FuIGVuIEV1cm9wYS4gUG9yIGVsbG8sIHZveSBhIGFuYWxpemFyIGxhcyA1IHByaW5jaXBhbGVzIGxpZ2FzIGRlIGbDunRib2wgZXVyb3Blby4NCjxicj4NCjxicj4NCioqQ29tcGV0aWNpb25lcyBhIGFuYWxpemFyOioqIExhIExpZ2EgKGxpZ2EgZXNwYcOxb2xhKSwgQnVuZGVzbGlnYSAoTGlnYSBhbGVtYW5hKSwgU2VyaWUgQSAoTGlnYSBpdGFsaWFuYSksIFByZW1pZXIgTGVhZ3VlIChMaWdhIGluZ2xlc2EpIHkgTGlndWUgMSAoTGlnYSBmcmFjZXNhKS4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KPGJyPg0KDQoNCiMgMi4gRGF0b3Mgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMgQ29tZW50YXJpb3MNCg0KQ29tbyBzZSBoYSBjb21lbnRhZG8gYSBsbyBsYXJnbyBkZWwgY3Vyc28geSwgdHJhcyBtaSBleHBlcmllbmNpYSB0cmFiYWphbmRvIGNvbiBkYXRvcyBkZWwgSU5FIGVuIGVsIFtUcmFiYWpvIGRlIEVxdWlwb10oaHR0cHM6Ly9naXRodWIuY29tL3BhdXBpZXJhMjMvdHJhYmFqb19CaWdEYXRhX2VxdWlwbyksIGxhIHByaW5jaXBhbCBwcm9ibGVtw6F0aWNhIHN1ZWxlIGdpcmFyIGVudG9ybm8gYWwgZXN0YWRvIGVuIHF1ZSByZWNpYmltb3MgbG9zIGRhdG9zLiBFbiBtaSBjYXNvLCBoZSB0cmFiYWphZG8gY29uIGRhdG9zIG9idGVuaWRvcyBkZSBsYSBwbGF0YWZvcm1hICoqS2FnZ2xlKiosIHBsYXRhZm9ybWEgZGVkaWNhZGEgYWwgcG9zdGVvIGRlIGRhdGEgZnJhbWVzLiBFc3RvIGhhIGhlY2hvIHF1ZSBsb3MgZGF0b3MgY29uIGxvcyBxdWUgaGUgdHJhYmFqYWRvIGVzdHViaWVyYW4gbXV5IGFycmVnbGFkb3MuIFNpbXBsZW1lbnRlIGhlIHRlbmlkbyBxdWUgcmVub21icmFyIHkgc2VsZWNjaW9uYXIuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCjxicj4NCg0KIyMgRGF0b3MNCg0KYGBge3IsIGV2YWwgPSBUUlVFfQ0KI0ltcG9ydGFtb3MgYWwgR2xvYmFsIEVudmlyb25tZW50IGVsIGFyY2hpdm8gZGVzY2FyZ2FkbyBkZSBLYWdnbGUNCmRmX2Z1dGJvbCA8LSByaW86OmltcG9ydCgiLi9kYXRvcy9Gb290YmFsbCB0ZWFtcy5jc3YiKQ0KDQojTGEgdW5pY2EgbGltcGllemEgcXVlIGhhY2Vtb3Mgc29uIGxvcyBub21icmVzLCBwYXJhIHBvbmVyIGxvcyBxdWUgdGVuZW1vcyBtw6FzIGZhbWlsaWFyaXphZG9zDQpkZl9mdXRib2wgPC0gZGZfZnV0Ym9sICU+JSANCiAgcmVuYW1lKEVxdWlwbyA9IFRlYW0sIExpZ2E9VG91cm5hbWVudCwgVGlyb3M9U2hvdHMsIEFtYXJpbGxhcz15ZWxsb3dfY2FyZHMsIFJvamFzPXJlZF9jYXJkcywgR29sZXM9R29hbHMpDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgUmVmZXJlbmNpYXMgDQoNCkNvbW8gaGUgY29tZW50YWRvIGFudGVyaW9ybWVudGUsIEthZ2dsZSBlcyB1bmEgcGxhdGFmb3JtYSBxdWUsIGVudHJlIG90cmFzIGZ1bmNpb25lcywgc2lydmUgcGFyYSBwb3N0ZWFyIHRyYWJham9zIHJlbGFjaW9uYWRvcyBjb24gbG9zIGRhdG9zLiBMbyBjdXJpb3NvIGVzIHF1ZSBwdWVkZXMgZW5jb250cmFyIGRhdG9zIGRlIHRvZG8gdGlwby4gRGVzZGUgcHJlY2lvcyBkZSBhY3Rpdm9zIGZpbmFuY2llcm9zIGhhc3RhIGRhdG9zIGRlcG9ydGl2b3MuIEVuIG1pIGNhc28gbWUgaGUgYmFzYWRvIGVuIGRhdG9zIGRlIGxvcyBzaWd1aWVudGVzIHVzdWFyaW9zIDoNCg0KPiB2YXJwaXQ5NA0KPGJyPg0KPiBUQU5VSkxFT01FU1NJDQo8YnI+DQo+IEFITUVUIMOHQUxJxZ4NCjxicj4NCj4gUlVQRVNIIEtSIFNJTkdIDQo8YnI+DQo+IFJJQkFDS0kNCjxicj4NCg0KDQoNCiMgMy4gTGlnYSBtw6FzIGdvbGVhZG9yYSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyBBbsOhbGlzaXMNCjxicj4NCg0KRW4gZXN0ZSBncsOhZmljbywgc2UgcHVlZGUgYXByZWNpYXIgZWwgbcOheGltbyB5IGVsIG3DrW5pbW8gZGUgZ29sZXMgYW5vdGFkb3MgcG9yIHVuIGVxdWlwbyBkZSBjYWRhIGxpZ2EsIGFzw60gY29tbyBlbCBuw7ptZXJvIHByb21lZGlvIGRlIGdvbGVzIHF1ZSBzZSBoYW4gbWFyY2FkbyBlbiBlc2EgbGlnYS4gUG9yIHRhbnRvLCBwb2RlbW9zIHZlciBxdWUgZWwgZXF1aXBvIHF1ZSBtw6FzIGdvbGVzIGhhIGFub3RhZG8ganVlZ2EgZW4gbGEgKipCdW5kZXNsaWdhKiosIGVsIGVxdWlwbyBxdWUgbWVub3MgdGFudG9zIGhhIGNvbnNlZ3VpZG8ganVlZ2EgcGFyYSBsYSAqKlByZW1pZXIgTGVhZ3VlKiouIEFkZW3DoXMsIHBvciB0w6lybWlubyBtZWRpbywgbGEgQnVuZGVzbGlnYSBlcyBsYSBjb21wZXRpY2nDs24gY29uIG3DoXMgZ29sZXMgeSBMYSBMaWdhIGVzIGxhIHF1ZSBtZW5vcyB0aWVuZS4NCjxicj4NCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFfQ0KcDEgPC0gZ2dwbG90IChkYXRhPSBkZl9mdXRib2wsIGFlcyAoeD1MaWdhLCB5PUdvbGVzLCBmaWxsPUxpZ2EpKSsNCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgbGFicyh0aXRsZSA9ICJHcsOhZmljbyAxOiBHb2xlcyBwb3IgTGlnYSIsDQogICAgICAgIGZpbGwgPSAiQ29tcGV0aWNpw7NuIiApICsNCiAgdGhlbWVfZGFyaygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkNCg0KZ2dwbG90bHkocDEpDQpgYGANCjxicj4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgQ8OzZGlnbw0KYGBge3IsIGV2YWwgPSBGQUxTRSwgZWNobyA9IFRSVUUsIHdhcm5pbmc9IEZBTFNFfQ0KcDEgPC0gZ2dwbG90IChkYXRhPSBkZl9mdXRib2wsIGFlcyAoeD1MaWdhLCB5PUdvbGVzLCBmaWxsPUxpZ2EpKSsNCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgbGFicyh0aXRsZSA9ICJHcsOhZmljbyAxOiBHb2xlcyBwb3IgTGlnYSIsDQogICAgICAgIGZpbGwgPSAiQ29tcGV0aWNpw7NuIiApICsNCiAgdGhlbWVfZGFyaygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkNCg0KZ2dwbG90bHkocDEpDQpgYGANCjxicj4NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgNC4gRXF1aXBvcyBtw6FzIHkgbWVub3MgZ29sZWFkb3JlcyAoVG9wIDEwKSB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyBBbsOhbGlzaQ0KDQo8YnI+DQoNCkVuIGVzdGUgY2FzbyBzZSBwdWVkZW4gb2JzZXJ2YXIgZWwgVE9QIDEwIGRlIGxvcyBlcXVpcG9zIGNvbiBtw6FzIGdvbGVzIHkgY29uIG1lbm9zIGdvbGVzLiBOb3MgZW5jb250cmFtb3MgY29uIHF1ZSBsYSBCdW5kZXNsaWdhIHRpZW5lIDQgZXF1aXBvcyBkZW50cm8gZGVsIFRPUCAxMCBkZSBtw6FzIGFub3RhZG9yZXMsIGNvc2EgcXVlIGNvbmN1ZXJkYSBjb24gbG8gZXhwbGljYWRvIGVuIGVsIFB1bnRvIDMuIFBvciBvdHJhIHBhcnRlLCBvdHJvIGhlY2hvIGRlc3RhY2FibGUgZXMgcXVlIGxhIFNlcmllIEEgbm8gdGllbmUgbmluZ8O6biBlcXVpcG8gZW4gZWwgVE9QIDEwIG1lbm9zIGdvbGVhZG9yZXMuDQoNCkNhYmUgZGVzdGFjYXIgcXVlLCBhdW5xdWUgZXMgdW4gVE9QIDEwLCBhcGFyZWNlbiArIC0gMTAgZXF1aXBvcyBkZWJpZG8gYSBxdWUgaGF5IGVtcGF0ZSBlbiBlbCBuw7ptZXJvIGRlIGdvbGVzLg0KDQo8YnI+DQpgYGB7ciwgZXZhbD1UUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFfQ0KZGZfbWFzIDwtIGRmX2Z1dGJvbCAlPiUgDQogIGZpbHRlcihtaW5fcmFuayhkZXNjKEdvbGVzKSk8MTApDQoNCmRmX21lbm9zIDwtIGRmX2Z1dGJvbCAlPiUgDQogIGZpbHRlcihtaW5fcmFuayhHb2xlcyk8MTApDQoNCnBtYXMgPC0gZ2dwbG90KGRhdGE9IGRmX21hcywgYWVzKHg9RXF1aXBvLCB5PUdvbGVzKSkrDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixhZXMoZmlsbD1MaWdhKSxjb2xvdXI9IkJsYWNrIikrDQogIGxhYnModGl0bGU9ICJUb3AxMCBlcXVpcG9zIG3DoXMgZ29sZWFkb3JlcyIpKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSArIHRoZW1lX21pbmltYWwoKQ0KDQpwbWVub3MgPC0gZ2dwbG90KGRhdGE9IGRmX21lbm9zLCBhZXMoeD1FcXVpcG8sIHk9R29sZXMpKSsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLGFlcyhmaWxsPUxpZ2EpLGNvbG91cj0iQmxhY2siKSsNCiAgbGFicyh0aXRsZT0gIlRvcDEwIGVxdWlwb3MgbWVub3MgZ29sZWFkb3JlcyIpKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSsgdGhlbWVfbWluaW1hbCgpDQoNCnBtZW5vcyA8LSBwbWVub3MgKyBsaW1zKHk9YygwLDEwMCkpDQoNCnAyIDwtIHBtYXMgKyBwbWVub3MgDQoNCnAyDQpgYGANCjxicj4NCg0KDQojIyBNw6FzIGdvbGVhZG9yZXMNCjxicj4NCg0KYGBge3IsIGV2YWw9VFJVRSwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPSBGQUxTRX0NCmRmX21hcyA8LSBkZl9mdXRib2wgJT4lIA0KICBmaWx0ZXIobWluX3JhbmsoZGVzYyhHb2xlcykpPDEwKQ0KDQpkZl9tZW5vcyA8LSBkZl9mdXRib2wgJT4lIA0KICBmaWx0ZXIobWluX3JhbmsoR29sZXMpPDEwKQ0KDQpwbWFzIDwtIGdncGxvdChkYXRhPSBkZl9tYXMsIGFlcyh4PUVxdWlwbywgeT1Hb2xlcykpKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsYWVzKGZpbGw9TGlnYSksY29sb3VyPSJCbGFjayIpKw0KICBsYWJzKHRpdGxlPSAiVG9wMTAgZXF1aXBvcyBtw6FzIGdvbGVhZG9yZXMiKSsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkgKyB0aGVtZV9taW5pbWFsKCkNCg0KDQpnZ3Bsb3RseShwbWFzKQ0KYGBgDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBNZW5vcyBnb2xlYWRvcmVzDQo8YnI+DQoNCmBgYHtyLCBldmFsPVRSVUUsIGVjaG8gPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9DQpkZl9tZW5vcyA8LSBkZl9mdXRib2wgJT4lIA0KICBmaWx0ZXIobWluX3JhbmsoR29sZXMpPDEwKQ0KDQpwbWVub3MgPC0gZ2dwbG90KGRhdGE9IGRmX21lbm9zLCBhZXMoeD1FcXVpcG8sIHk9R29sZXMpKSsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLGFlcyhmaWxsPUxpZ2EpLGNvbG91cj0iQmxhY2siKSsNCiAgbGFicyh0aXRsZT0gIlRvcDEwIGVxdWlwb3MgbWVub3MgZ29sZWFkb3JlcyIpKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSsgdGhlbWVfbWluaW1hbCgpDQoNCnBtZW5vcyA8LSBwbWVub3MgKyBsaW1zKHk9YygwLDEwMCkpDQoNCmdncGxvdGx5KHBtZW5vcykNCmBgYA0KPGJyPg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgQ8OzZGlnbw0KDQpgYGB7ciwgZXZhbD1GQUxTRSwgZWNobyA9IFRSVUUsIHdhcm5pbmc9IEZBTFNFfQ0KZGZfbWFzIDwtIGRmX2Z1dGJvbCAlPiUgDQogIGZpbHRlcihtaW5fcmFuayhkZXNjKEdvbGVzKSk8MTApDQoNCmRmX21lbm9zIDwtIGRmX2Z1dGJvbCAlPiUgDQogIGZpbHRlcihtaW5fcmFuayhHb2xlcyk8MTApDQoNCnBtYXMgPC0gZ2dwbG90KGRhdGE9IGRmX21hcywgYWVzKHg9RXF1aXBvLCB5PUdvbGVzKSkrDQogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixhZXMoZmlsbD1MaWdhKSxjb2xvdXI9IkJsYWNrIikrDQogIGxhYnModGl0bGU9ICJUb3AxMCBlcXVpcG9zIG3DoXMgZ29sZWFkb3JlcyIpKw0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSArIHRoZW1lX21pbmltYWwoKQ0KDQoNCmdncGxvdGx5KHBtYXMpDQoNCnBtZW5vcyA8LSBnZ3Bsb3QoZGF0YT0gZGZfbWVub3MsIGFlcyh4PUVxdWlwbywgeT1Hb2xlcykpKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsYWVzKGZpbGw9TGlnYSksY29sb3VyPSJCbGFjayIpKw0KICBsYWJzKHRpdGxlPSAiVG9wMTAgZXF1aXBvcyBtZW5vcyBnb2xlYWRvcmVzIikrDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpKyB0aGVtZV9taW5pbWFsKCkNCg0KcG1lbm9zIDwtIHBtZW5vcyArIGxpbXMoeT1jKDAsMTAwKSkNCg0KZ2dwbG90bHkocG1lbm9zKQ0KDQpwMiA8LSBwbWFzICsgcG1lbm9zIA0KDQpwMg0KYGBgDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDUuIEdvbGVzIHBvciBMaWdhIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIEFuw6FsaXNpcw0KPGJyPg0KQW50ZXMgcXVlIG5hZGEsIGhheSBxdWUgZGVzdGFjYXIgcXVlIGhlIGVsZWdpZG8gZXN0YWJsZWNlciB1bmEgZXNjYWxhIGxpYnJlIGVuIGNhZGEgY29tcGV0aWNpw7NuIHBhcmEgcG9kZXIgZXhhZ2VyYXIgbGFzIGZvcm1hcyB5IHF1ZSBzZWEgbcOhcyB2aXN1YWwuIFBvciB0YW50bywgYSBsYSBob3JhIGRlIGFuYWxpemFyIGhheSBxdWUgdGVuZXIgZW4gY3VlbnRhIGxhIGVzY2FsYSBkZWwgZWplIHkuDQpQb2RlbW9zIGFwcmVjaWFyIHF1ZSwgY29tbyBzZSBoYSBkZW1vc3RyYWRvIGFudGVyaW9ybWVudGUsIGxhIFNlcmllIEEsIGF1bnF1ZSBjb25jZW50cmEgbXVjaG9zIGRlIHN1cyBlcXVpcG9zIGVuIGxhIHBhcnRlIGJqYSBkZWwgZ3LDoWZpY286IHJhbmdvIGRlIGdvbGVzIDQwLTYwLCBubyB0aWVuZSBuaW5nw7puIGVxdWlwbyBxdWUgYW5vdGUgbWVub3MgZGUgMzkgZ29sZXMsIGEgZGlmZXJlbmNpYSBkZSBsbyBxdWUgb2N1cnJlIHBvciBlamVtcGxvIGVuIGxhIFByZW1pZXIgTGVhZ3VlLCBkb25kZSBoYXkgdW4gZXF1aXBvIGNvbiAxOSBnb2xlcy4NCg0KYGBge3IsIGV2YWw9VFJVRSwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPSBGQUxTRX0NCnAzIDwtIGdncGxvdChkYXRhPSBkZl9mdXRib2wsICBhZXMoeD1MaWdhLCB5PUdvbGVzLCBmaWxsPUxpZ2EpKSArDQogIGdlb21fdmlvbGluKCkgKyAgDQogIGZhY2V0X3dyYXAoTGlnYX4uLCBzY2FsZXMgPSAiZnJlZSIpKw0KICBnZW9tX2ppdHRlcigpICsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCmdncGxvdGx5KHAzKQ0KDQpgYGANCjxicj4NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMjIEPDs2RpZ28NCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvID0gVFJVRSwgd2FybmluZz0gRkFMU0V9DQpwMyA8LSBnZ3Bsb3QoZGF0YT0gZGZfZnV0Ym9sLCAgYWVzKHg9TGlnYSwgeT1Hb2xlcywgZmlsbD1MaWdhKSkgKw0KICBnZW9tX3Zpb2xpbigpICsgIA0KICBmYWNldF93cmFwKExpZ2F+Liwgc2NhbGVzID0gImZyZWUiKSsNCiAgZ2VvbV9qaXR0ZXIoKSArDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpnZ3Bsb3RseShwMykNCg0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgNi4gwr9RdcOpIGhhY2VuIGxvcyBxdWUgbcOhcyBtYXJjYW4/IHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCiMjIEFuw6FsaXNpcw0KPGJyPg0KYGBge3IsIGV2YWw9VFJVRSAsZWNobyA9IEZBTFNFLCB3YXJuaW5nPSBGQUxTRX0NCnA0IDwtIGdnYmFsbG9vbnBsb3QoZGF0YT0gZGZfZnV0Ym9sICx4PSJQb3NzZXNzaW9uIiwgeT0iVGlyb3MiLCBmaWxsPSJMaWdhIikrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgbGFicyh0aXRsZSA9ICJHcmFmaWNvIDQ6IFJlbGFjacOzbiBQb3Nlc2nDs24tVGlyb3MtR29sZXMiKSsNCiAgZ2VvbV9zbW9vdGgoY29sb3I9ImJsYWNrIikNCg0KcDQNCmBgYA0KDQo8YnI+DQoNCkVuIGVzdGEgb2Nhc2nDs24gc2UgaW50ZW50YSBkZW1vc3RyYXIgc2kgaGF5IHVuYSByZWxhY2nDs24gZW50cmUgZWwgJSBkZSBwb3Nlc2nDs24sIGxhIGNhbnRpZGFkIGRlIHRpcm9zIHBvciBwYXJ0aWRvIHkgZWwgbsO6bWVybyBkZSBnb2xlcyBhbm90YWRvcy4gTGEgcHJlZ3VudGEgcXVlIG5vcyBwb2Ryw61hbW9zIGhhY2VyIHNlcsOtYTogwr9Mb3MgcXVlIG3DoXMgbWFyY2FuIHNvbiBsb3MgcXVlIG1hcyB0aXJvcyBoYWNlbiB5IG3DoXMgbWFudGllbmVuIGVsIGJhbMOzbj8uIFByaW1lcm8gcXVlIG5hZGEgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGxhIGzDrW5lYSBkZSB0ZW5kZW5jaWEgZXMgY3JlY2llbnRlLCBjb3NhIHF1ZSBzZSB0cmFkdWNlIGVuIHF1ZSBhIG1lZGlkYSBxdWUgZWwgJSBkZSBwb3Nlc2nDs24geSBlbCBuw7ptZXJvIGRlIHRpcm9zIGF1bWVudGFuLCB0YW1iaWVuIGxvIGhhY2UgZWwgbsO6bWVybyBkZSBnb2xlcy4gQWRlbcOhcywgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGVsIGVxdWlwbyBxdWUgbcOhcyBwb3Nlc2nDs24gdGllbmUgc2UgZW5jdWVudHJhIGVuIExhIExpZ2EgeSBoZW1vcyB2aXN0byBhbnRlcmlvcm1lbnRlIHF1ZSBubyBlcyBlbCBtw6FzIGdvbGVhZG9yLiBQb3IgdGFudG8sIGNvbW8gZWwgbcOhcyBnb2xlYWRvciBzZSBlbmN1ZW50cmEgZW4gbGEgQnVuZGVzbGlnYSwgcGFyYSB2ZXIgcXVpZW4gZXMgZWwgcXVlIG3DoXMgZ29sZXMgbWFyY2Fyw6EsIGluZmx1eWUgZW4gbWF5b3IgbWVkaWRhIGVsIG7Dum1lcm8gZGUgdGlyb3MgcXVlIHNlIGhhY2VuIHBvciBwYXJ0aWRvLg0KDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBjw7NkaWdvDQpgYGB7ciwgZXZhbD1GQUxTRSwgZWNobyA9IFRSVUUsIHdhcm5pbmc9IEZBTFNFfQ0KcDQgPC0gZ2diYWxsb29ucGxvdChkYXRhPSBkZl9mdXRib2wgLHg9IlBvc3Nlc3Npb24iLCB5PSJUaXJvcyIsIGZpbGw9IkxpZ2EiKSsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICBsYWJzKHRpdGxlID0gIkdyYWZpY28gNDogUmVsYWNpw7NuIFBvc2VzacOzbi1UaXJvcy1Hb2xlcyIpKw0KICBnZW9tX3Ntb290aChjb2xvcj0iYmxhY2siKQ0KDQpwNA0KYGBgDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDcuIEVxdWlwb3MgbcOhcyBhbW9uZXN0YWRvcyB7LnRhYnNldCAudGFic2V0LXBpbGxzfQ0KDQojIyBBbsOhbGlzaXMNCjxicj4NCkVuIGVzdGEgb2Nhc2nDs24gc2UgcHJldGVuZGUgbW9zdHJhciBsb3MgMTAgZXF1aXBvcyBjb24gbcOhcyB0YXJqZXRhcywgdGFudG8gcm9qYXMgY29tbyBhbWFyaWxsYXMuIEVsIGVxdWlwbyBtw6FzICJkdXJvIiBmdcOpIGVsIEdldGFmZSwgZGUgTGEgTGlnYSwgZWwgY3VhbCB0YW1iacOpbiBlc3TDoSBkZW50cm8gZGVsIFRPUDMgdGFyamV0YXMgcm9qYXMuIEVsIGVxdWlwbyBjb24gbcOhcyBhbW9uZXN0YWNpb25lcyBncmF2ZXMgKHRhcmpldGFzIHJvamFzKSBlcyBlbCBNYXJzZWlsbGUsIGRlIGxhIExpZ3VlIDEsIGNvbiB1biB0b3RhbCBkZSA5IHJvamFzLg0KDQo8YnI+DQpgYGB7ciwgIGV2YWw9VFJVRSwgZWNobyA9IEZBTFNFLCB3YXJuaW5nPSBGQUxTRX0NCmRmXzUgPC0gZGZfZnV0Ym9sICU+JSANCiAgZ3JvdXBfYnkoTGlnYSkgJT4lIA0KICBtdXRhdGUoVG90YWwgPSBBbWFyaWxsYXMgKyBSb2phcykgJT4lIA0KICBzZWxlY3QoRXF1aXBvICxBbWFyaWxsYXMsIFJvamFzLCBUb3RhbCApICU+JSANCiAgdG9wX24oMiwgVG90YWwpDQoNCg0KcDUgPC0gZ2dwbG90KGRmXzUpICsNCiAgYWVzKHggPSBFcXVpcG8sIGZpbGwgPSBSb2phcywgd2VpZ2h0ID0gVG90YWwpICsNCiAgZ2VvbV9iYXIoKSArDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAiUmVkcyIsIGRpcmVjdGlvbiA9IDEpICsNCiAgbGFicyh4ID0gIkVxdWlwbyIsDQogICAgICAgeSA9IlRvdGFsIFRhcmpldGFzIiwNCiAgICAgICB0aXRsZSA9ICJUb3AgMTAgZXF1aXBvcyBtw6FzIGFtb25lc3RhZG9zIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJUYXJqZXRhcyBhbWFyaWxsYXMgeSByb2phcyIsDQogICAgICAgZmlsbCA9ICJSb2phcyIpICsNCiAgZ2d0aGVtZXM6OnRoZW1lX2Jhc2UoKQ0KDQpnZ3Bsb3RseShwNSkNCmBgYA0KDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBDw7NkaWdvDQpgYGB7ciwgIGV2YWw9RkFMU0UsIGVjaG8gPSBUUlVFLCB3YXJuaW5nPSBGQUxTRX0NCmRmXzUgPC0gZGZfZnV0Ym9sICU+JSANCiAgZ3JvdXBfYnkoTGlnYSkgJT4lIA0KICBtdXRhdGUoVG90YWwgPSBBbWFyaWxsYXMgKyBSb2phcykgJT4lIA0KICBzZWxlY3QoRXF1aXBvICxBbWFyaWxsYXMsIFJvamFzLCBUb3RhbCApICU+JSANCiAgdG9wX24oMiwgVG90YWwpDQoNCg0KcDUgPC0gZ2dwbG90KGRmXzUpICsNCiAgYWVzKHggPSBFcXVpcG8sIGZpbGwgPSBSb2phcywgd2VpZ2h0ID0gVG90YWwpICsNCiAgZ2VvbV9iYXIoKSArDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAiUmVkcyIsIGRpcmVjdGlvbiA9IDEpICsNCiAgbGFicyh4ID0gIkVxdWlwbyIsDQogICAgICAgeSA9IlRvdGFsIFRhcmpldGFzIiwNCiAgICAgICB0aXRsZSA9ICJUb3AgMTAgZXF1aXBvcyBtw6FzIGFtb25lc3RhZG9zIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJUYXJqZXRhcyBhbWFyaWxsYXMgeSByb2phcyIsDQogICAgICAgZmlsbCA9ICJSb2phcyIpICsNCiAgZ2d0aGVtZXM6OnRoZW1lX2Jhc2UoKQ0KDQpnZ3Bsb3RseShwNSkNCmBgYA0KDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDguIFJhbmtpbmcgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KIyMgQW7DoWxpc2lzDQo8YnI+DQpQb3Igw7psdGltbywgaGUgcXVlcmlkbyBtb3N0cmFyIGxhIHZhbG9yYWNpw7NuIGdlbmVyYWwgKFJhdGluZykgZGUgdG9kb3MgbG9zIGVxdWlwb3MuIFNlIHB1ZWRlIGFwcmVjaWFyIHF1ZSBlbCBtZWpvciBlcXVpcG8gZW4gbGEgdGVtcG9yYWRhIDIwLzIxIGZ1w6kgZWwgTWFuY2hlc3RlciBDaXR5LCBkZSBsYSBsaWdhIGluZ2xlc2EsIG1pZW50cmFzIHF1ZSBlbCBwZW9yIGZ1w6kgZWwgU2NoYWxrZSAwNCwgZGUgbGEgbGlnYSBhbGVtYW5hLiBDYWJlIGRlc3RhY2FyIHRhbWJpw6luIHF1ZSBsb3MgaW5nbGVzZXMgdGllbmVuIGxhIG1heW9yIHBhcnRlIGRlIHN1cyBlcXVpcG9zIGVuIGVsIHJhbmdvIGRlIHJhdGluZyA2LjYgLSA3DQoNCmBgYHtyLCAgZXZhbD1UUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFfQ0KcDYgPC0gZ2dwbG90KGRmX2Z1dGJvbCwgYWVzKHg9RXF1aXBvLCB5PVJhdGluZywgZmlsbD1MaWdhKSkrDQogIGdlb21fcG9pbnQoKSsNCiAgZmFjZXRfZ3JpZChjb2xzPXZhcnMoTGlnYSkpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKw0KICBsYWJzKHRpdGxlPSJSYXRpbmcgZGUgbG9zIGVxdWlwb3MiKQ0KDQpnZ3Bsb3RseShwNikNCmBgYA0KDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBjw7NkaWdvDQoNCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvID0gVFJVRSwgd2FybmluZz0gRkFMU0V9DQpwNiA8LSBnZ3Bsb3QoZGZfZnV0Ym9sLCBhZXMoeD1FcXVpcG8sIHk9UmF0aW5nLCBmaWxsPUxpZ2EpKSsNCiAgZ2VvbV9wb2ludCgpKw0KICBmYWNldF9ncmlkKGNvbHM9dmFycyhMaWdhKSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrDQogIGxhYnModGl0bGU9IlJhdGluZyBkZSBsb3MgZXF1aXBvcyIpDQoNCmdncGxvdGx5KHA2KQ0KYGBgDQo8YnI+DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDkuIENvbmNsdXNpb25lcw0KDQpTZSBoYW4gYW5hbGl6YWRvIHBhcsOhbWV0cm9zIGRlIGxhcyBxdWUgc29uIGNvbnNpZGVyYWRhcyBjw7NtbyBsYXMgbWVqb3JlcyBsaWdhcyBldXJvcGVhcywgcGVybyDCv2N1YWwgZXMgbGEgbWVqb3IgbGlnYT8uIEVzdG8gZGVwZW5kZSBkZWwgZ3VzdG8gZGUgY2FkYSBhZmljaW9uYWRvLCBwZXJvIGVsIGNvbnNlbnNvIGdlbmVyYWwgbm9zIGRpY2UgcXVlIGVzdGEgZGVjaXNpw7NuIHZhIHZhcmlhbmRvLiBIYXN0YSBsYSB0ZW1wb3JhZGEsIGFwcm94aW1hZGFtZW50ZSwgMTgvMTksIExhIExpZ2EgKGxpZ2EgZXNwYcOxb2xhKSBlcmEgY29uc2lkZXJhZGEgbGEgbWVqb3IsIGNvbiBlcXVpcG9zIHF1ZSBkaWVyb24gbXVjaG8gZXNwZWN0w6FjdWxvIHkgY29uIG11Y2hhIGNhbGlkYWQgZGUgZsO6dGJvbCAoZWplbXBsbywgZWwgZ3JhbiAlIGRlIHBvc2VzacOzbiBhY3R1YWwgZGUgc3VzIGVxdWlwb3MpLiBIb3kgcG9yIGhveSwgbG9zIGluZ2xlc2VzIHNvbiBjb25zaWRlcmFkb3MgY29tbyBsb3MgcHJpbmNpcGFsZXMgY3JlYWRvcmVzIGRlIGVzcGVjdMOhY3VsbyBmdXRib2zDrXN0aWNvLCBlbnRyZSBvdHJhcywgZ3JhY2lhcyBhIHN1IHZlbG9jaWRhZCBkZSBqdWVnbw0KPGJyPg0KPGJyPg0KDQojIDEwLiBCaWJsaW9ncmFmw61hDQoNCltLYWdnbGVdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vKQ0KPGJyPg0KW3JQdWJzXShodHRwczovL3JwdWJzLmNvbS9kYW5pYmFsbGFyaS9nZ3Bsb3QpDQo8YnI+DQpbZ2dQbG90XShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pDQo8YnI+DQpbVHV0b3JpYWxlc10oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLzA0LXR1dG9yaWFsZXMuaHRtbCkNCjxicj48YnI+DQoNCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Kc2Vzc2lvbmluZm86OnNlc3Npb25faW5mbygpICU+JSBkZXRhaWxzOjpkZXRhaWxzKHN1bW1hcnkgPSAnSW5mb3JtYWNpw7NuIGRlIG1pIFItc2VzacOzbjonKSANCmBgYA0KDQoNCjxicj48YnI+DQoNCjxkaXYgY2xhc3M9InRvY2lmeS1leHRlbmQtcGFnZSIgZGF0YS11bmlxdWU9InRvY2lmeS1leHRlbmQtcGFnZSIgc3R5bGU9ImhlaWdodDogMDsiPjwvZGl2Pg0KPGJyPjxicj4NCg0KPGRpdiBjbGFzcz0idG9jaWZ5LWV4dGVuZC1wYWdlIiBkYXRhLXVuaXF1ZT0idG9jaWZ5LWV4dGVuZC1wYWdlIiBzdHlsZT0iaGVpZ2h0OiAwOyI+PC9kaXY+DQo=