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. El repo del trabajo está aquí. La página web de la asignatura y los trabajos de mis compañeros pueden verse aquí.
1. Introducción
En este trabajo enseñare los resultados del campeonato mundial de la Formula 1 en el año 2019, donde se podra mostrar un claro dominio por parte de la escudería Mercedes integrado por los pilots Lewis Hamilton y Valterri Bottas, con respecto al resto de escuderías que no le pudieron hacer frente a estos veloces coches. También resaltaremos diferentes datos interesantes respecto al tema como la ubicación de los circuitos de carrera, el rendimiento de los pilotos de forma individual y de las escuderías.
2. Posiciones de los Pilotos
En la siguiente tabla se destacara a los 9 pilotos que tuvieron una mayor cantidad de puntos comparado a los 20 que compiten a lo largo de la serie mundial. Como se puede apreciar hay nombres de talla mundial como los de Lewis Hamilton y el de su eterno rival Sebastian Vettel que conduce el famoso coche rojo de Ferrari, pero que durante esta temporada no pudo destacar como lo hace habitualmente y termino obtniendo un 5to lugar en la claisifación mundial. Por otro lado se puede apreciar como su compañero de equipo un rookie llamado Charles Leclerc siendo el segundo piloto más joven que ha pertenecido a la escudería de Ferrari haya logrado vencer en su debut al 4 veces campeón mundial de la formula 1.
Posiciones
1. |
Lewis Hamilton |
413 |
18 |
25 |
25 |
18 |
26 |
25 |
25 |
25 |
10 |
26 |
2 |
25 |
18 |
16 |
12 |
26 |
16 |
25 |
18 |
6 |
26 |
2. |
Valtteri Bottas |
326 |
26 |
18 |
18 |
25 |
18 |
15 |
13 |
18 |
15 |
18 |
- |
4 |
15 |
18 |
10 |
18 |
25 |
15 |
25 |
- |
12 |
3. |
Max Verstappen |
278 |
15 |
12 |
12 |
12 |
15 |
12 |
10 |
12 |
26 |
10 |
26 |
19 |
- |
4 |
15 |
12 |
- |
8 |
15 |
25 |
18 |
4. |
Charles Leclerc |
264 |
10 |
16 |
10 |
11 |
10 |
- |
15 |
15 |
18 |
15 |
- |
12 |
25 |
25 |
18 |
15 |
8 |
13 |
13 |
- |
15 |
5. |
Sebastian Vettel |
240 |
12 |
10 |
15 |
15 |
12 |
18 |
18 |
11 |
12 |
- |
18 |
15 |
13 |
- |
25 |
- |
18 |
18 |
- |
- |
10 |
6. |
Carlos Sainz |
96 |
- |
- |
- |
6 |
4 |
8 |
- |
8 |
4 |
8 |
10 |
10 |
- |
- |
- |
8 |
10 |
- |
4 |
15 |
1 |
7. |
Pierre Gasly |
95 |
- |
4 |
9 |
- |
8 |
11 |
4 |
1 |
6 |
12 |
- |
8 |
2 |
- |
4 |
- |
6 |
2 |
- |
18 |
- |
8. |
Alexander Albon |
92 |
- |
2 |
1 |
- |
- |
4 |
- |
- |
- |
- |
8 |
1 |
10 |
8 |
8 |
10 |
12 |
10 |
10 |
- |
8 |
9. |
Daniel Ricciardo |
54 |
- |
- |
6 |
- |
- |
2 |
8 |
- |
- |
6 |
- |
- |
- |
12 |
- |
- |
- |
4 |
8 |
8 |
- |
Posiciones de cada Carrera
1 |
Lewis Hamilton |
R01 |
18 |
2 |
Valtteri Bottas |
R01 |
26 |
3 |
Max Verstappen |
R01 |
15 |
4 |
Charles Leclerc |
R01 |
10 |
5 |
Sebastian Vettel |
R01 |
12 |
6 |
Carlos Sainz |
R01 |
0 |
7 |
Pierre Gasly |
R01 |
0 |
8 |
Alexander Albon |
R01 |
0 |
9 |
Daniel Ricciardo |
R01 |
0 |
1 |
Lewis Hamilton |
R02 |
25 |
2 |
Valtteri Bottas |
R02 |
18 |
3 |
Max Verstappen |
R02 |
12 |
4 |
Charles Leclerc |
R02 |
16 |
5 |
Sebastian Vettel |
R02 |
10 |
6 |
Carlos Sainz |
R02 |
0 |
7 |
Pierre Gasly |
R02 |
4 |
8 |
Alexander Albon |
R02 |
2 |
9 |
Daniel Ricciardo |
R02 |
0 |
1 |
Lewis Hamilton |
R03 |
25 |
2 |
Valtteri Bottas |
R03 |
18 |
3 |
Max Verstappen |
R03 |
12 |
4 |
Charles Leclerc |
R03 |
10 |
5 |
Sebastian Vettel |
R03 |
15 |
6 |
Carlos Sainz |
R03 |
0 |
7 |
Pierre Gasly |
R03 |
9 |
8 |
Alexander Albon |
R03 |
1 |
9 |
Daniel Ricciardo |
R03 |
6 |
1 |
Lewis Hamilton |
R04 |
18 |
2 |
Valtteri Bottas |
R04 |
25 |
3 |
Max Verstappen |
R04 |
12 |
4 |
Charles Leclerc |
R04 |
11 |
5 |
Sebastian Vettel |
R04 |
15 |
6 |
Carlos Sainz |
R04 |
6 |
7 |
Pierre Gasly |
R04 |
0 |
8 |
Alexander Albon |
R04 |
0 |
9 |
Daniel Ricciardo |
R04 |
0 |
1 |
Lewis Hamilton |
R05 |
26 |
2 |
Valtteri Bottas |
R05 |
18 |
3 |
Max Verstappen |
R05 |
15 |
4 |
Charles Leclerc |
R05 |
10 |
5 |
Sebastian Vettel |
R05 |
12 |
6 |
Carlos Sainz |
R05 |
4 |
7 |
Pierre Gasly |
R05 |
8 |
8 |
Alexander Albon |
R05 |
0 |
9 |
Daniel Ricciardo |
R05 |
0 |
1 |
Lewis Hamilton |
R06 |
25 |
2 |
Valtteri Bottas |
R06 |
15 |
3 |
Max Verstappen |
R06 |
12 |
4 |
Charles Leclerc |
R06 |
0 |
5 |
Sebastian Vettel |
R06 |
18 |
6 |
Carlos Sainz |
R06 |
8 |
7 |
Pierre Gasly |
R06 |
11 |
8 |
Alexander Albon |
R06 |
4 |
9 |
Daniel Ricciardo |
R06 |
2 |
1 |
Lewis Hamilton |
R07 |
25 |
2 |
Valtteri Bottas |
R07 |
13 |
3 |
Max Verstappen |
R07 |
10 |
4 |
Charles Leclerc |
R07 |
15 |
5 |
Sebastian Vettel |
R07 |
18 |
6 |
Carlos Sainz |
R07 |
0 |
7 |
Pierre Gasly |
R07 |
4 |
8 |
Alexander Albon |
R07 |
0 |
9 |
Daniel Ricciardo |
R07 |
8 |
1 |
Lewis Hamilton |
R08 |
25 |
2 |
Valtteri Bottas |
R08 |
18 |
3 |
Max Verstappen |
R08 |
12 |
4 |
Charles Leclerc |
R08 |
15 |
5 |
Sebastian Vettel |
R08 |
11 |
6 |
Carlos Sainz |
R08 |
8 |
7 |
Pierre Gasly |
R08 |
1 |
8 |
Alexander Albon |
R08 |
0 |
9 |
Daniel Ricciardo |
R08 |
0 |
1 |
Lewis Hamilton |
R09 |
10 |
2 |
Valtteri Bottas |
R09 |
15 |
3 |
Max Verstappen |
R09 |
26 |
4 |
Charles Leclerc |
R09 |
18 |
5 |
Sebastian Vettel |
R09 |
12 |
6 |
Carlos Sainz |
R09 |
4 |
7 |
Pierre Gasly |
R09 |
6 |
8 |
Alexander Albon |
R09 |
0 |
9 |
Daniel Ricciardo |
R09 |
0 |
1 |
Lewis Hamilton |
R10 |
26 |
2 |
Valtteri Bottas |
R10 |
18 |
3 |
Max Verstappen |
R10 |
10 |
4 |
Charles Leclerc |
R10 |
15 |
5 |
Sebastian Vettel |
R10 |
0 |
6 |
Carlos Sainz |
R10 |
8 |
7 |
Pierre Gasly |
R10 |
12 |
8 |
Alexander Albon |
R10 |
0 |
9 |
Daniel Ricciardo |
R10 |
6 |
1 |
Lewis Hamilton |
R11 |
2 |
2 |
Valtteri Bottas |
R11 |
0 |
3 |
Max Verstappen |
R11 |
26 |
4 |
Charles Leclerc |
R11 |
0 |
5 |
Sebastian Vettel |
R11 |
18 |
6 |
Carlos Sainz |
R11 |
10 |
7 |
Pierre Gasly |
R11 |
0 |
8 |
Alexander Albon |
R11 |
8 |
9 |
Daniel Ricciardo |
R11 |
0 |
1 |
Lewis Hamilton |
R12 |
25 |
2 |
Valtteri Bottas |
R12 |
4 |
3 |
Max Verstappen |
R12 |
19 |
4 |
Charles Leclerc |
R12 |
12 |
5 |
Sebastian Vettel |
R12 |
15 |
6 |
Carlos Sainz |
R12 |
10 |
7 |
Pierre Gasly |
R12 |
8 |
8 |
Alexander Albon |
R12 |
1 |
9 |
Daniel Ricciardo |
R12 |
0 |
1 |
Lewis Hamilton |
R13 |
18 |
2 |
Valtteri Bottas |
R13 |
15 |
3 |
Max Verstappen |
R13 |
0 |
4 |
Charles Leclerc |
R13 |
25 |
5 |
Sebastian Vettel |
R13 |
13 |
6 |
Carlos Sainz |
R13 |
0 |
7 |
Pierre Gasly |
R13 |
2 |
8 |
Alexander Albon |
R13 |
10 |
9 |
Daniel Ricciardo |
R13 |
0 |
1 |
Lewis Hamilton |
R14 |
16 |
2 |
Valtteri Bottas |
R14 |
18 |
3 |
Max Verstappen |
R14 |
4 |
4 |
Charles Leclerc |
R14 |
25 |
5 |
Sebastian Vettel |
R14 |
0 |
6 |
Carlos Sainz |
R14 |
0 |
7 |
Pierre Gasly |
R14 |
0 |
8 |
Alexander Albon |
R14 |
8 |
9 |
Daniel Ricciardo |
R14 |
12 |
1 |
Lewis Hamilton |
R15 |
12 |
2 |
Valtteri Bottas |
R15 |
10 |
3 |
Max Verstappen |
R15 |
15 |
4 |
Charles Leclerc |
R15 |
18 |
5 |
Sebastian Vettel |
R15 |
25 |
6 |
Carlos Sainz |
R15 |
0 |
7 |
Pierre Gasly |
R15 |
4 |
8 |
Alexander Albon |
R15 |
8 |
9 |
Daniel Ricciardo |
R15 |
0 |
1 |
Lewis Hamilton |
R16 |
26 |
2 |
Valtteri Bottas |
R16 |
18 |
3 |
Max Verstappen |
R16 |
12 |
4 |
Charles Leclerc |
R16 |
15 |
5 |
Sebastian Vettel |
R16 |
0 |
6 |
Carlos Sainz |
R16 |
8 |
7 |
Pierre Gasly |
R16 |
0 |
8 |
Alexander Albon |
R16 |
10 |
9 |
Daniel Ricciardo |
R16 |
0 |
1 |
Lewis Hamilton |
R17 |
16 |
2 |
Valtteri Bottas |
R17 |
25 |
3 |
Max Verstappen |
R17 |
0 |
4 |
Charles Leclerc |
R17 |
8 |
5 |
Sebastian Vettel |
R17 |
18 |
6 |
Carlos Sainz |
R17 |
10 |
7 |
Pierre Gasly |
R17 |
6 |
8 |
Alexander Albon |
R17 |
12 |
9 |
Daniel Ricciardo |
R17 |
0 |
1 |
Lewis Hamilton |
R18 |
25 |
2 |
Valtteri Bottas |
R18 |
15 |
3 |
Max Verstappen |
R18 |
8 |
4 |
Charles Leclerc |
R18 |
13 |
5 |
Sebastian Vettel |
R18 |
18 |
6 |
Carlos Sainz |
R18 |
0 |
7 |
Pierre Gasly |
R18 |
2 |
8 |
Alexander Albon |
R18 |
10 |
9 |
Daniel Ricciardo |
R18 |
4 |
1 |
Lewis Hamilton |
R19 |
18 |
2 |
Valtteri Bottas |
R19 |
25 |
3 |
Max Verstappen |
R19 |
15 |
4 |
Charles Leclerc |
R19 |
13 |
5 |
Sebastian Vettel |
R19 |
0 |
6 |
Carlos Sainz |
R19 |
4 |
7 |
Pierre Gasly |
R19 |
0 |
8 |
Alexander Albon |
R19 |
10 |
9 |
Daniel Ricciardo |
R19 |
8 |
1 |
Lewis Hamilton |
R20 |
6 |
2 |
Valtteri Bottas |
R20 |
0 |
3 |
Max Verstappen |
R20 |
25 |
4 |
Charles Leclerc |
R20 |
0 |
5 |
Sebastian Vettel |
R20 |
0 |
6 |
Carlos Sainz |
R20 |
15 |
7 |
Pierre Gasly |
R20 |
18 |
8 |
Alexander Albon |
R20 |
0 |
9 |
Daniel Ricciardo |
R20 |
8 |
1 |
Lewis Hamilton |
R21 |
26 |
2 |
Valtteri Bottas |
R21 |
12 |
3 |
Max Verstappen |
R21 |
18 |
4 |
Charles Leclerc |
R21 |
15 |
5 |
Sebastian Vettel |
R21 |
10 |
6 |
Carlos Sainz |
R21 |
1 |
7 |
Pierre Gasly |
R21 |
0 |
8 |
Alexander Albon |
R21 |
8 |
9 |
Daniel Ricciardo |
R21 |
0 |
3. Evolución de las Posiciones de los Pilotos
Aquí podemos observar a los 9 corredores que hicieron más puntos a lo largo de la temporada. Observando los altos y bajos que han obtenido a lo largo de las 21 carreras realizadas. Se podrá destacar 2 gráficas donde en la primera se observara el rendimientos de los pilotos en relación de los puntos obtenidos con respecto a cada carrera del campeonato mundial, mientras que en la segunda gráfica se detallara el rednimiento de forma individual de cada piloto.
4. Posiciones de las Escuerías
En este apartado del trabajo dejaremos al lado a los pilotos y nos enfocaremos en las escuderías. En el siguiente gráfico se podrá observar de forma ordenada las posiciones que obtuvieron los equipos de la formula 1, con un claro dominio de Mercedes al resto de escuderías obteniendo más de 200 puntos con respecto al segundo lugar. Otro dato interesante que se podría obtener a partir de esta información es que no es coincidencia que la ventaja de los primeros 3 equipos sea tan supeior al resto de las escuderías, ya que el presupuesto que poseen sea mayor al resto. De forma más detallada el equipo de Mercedes tuvo una inversión durante este año de 700 millones, Ferrari de 500 millones, Red Bull de 300 millones y el resto de los 7 participantes su presupuesto no llega ni siquiera a los 150 millones. Por esta razón, la FIA la organización encargada de regular las competiciones de automovilismo deicidió implantar para el 2022 un límite al presupuesto de las escuderías que sería igual a 150 millones, para buscar que exista más competitividad y no de que siempre domine una escudería a lo largo del tiempo, sino para que también los pilotos demuestren su habilidad de conducción al tener coches más similares.
Tabla de las Escuderías
1 |
Mercedes |
739 |
44 |
43 |
43 |
43 |
44 |
40 |
38 |
43 |
25 |
44 |
2 |
29 |
33 |
34 |
22 |
44 |
41 |
40 |
43 |
6 |
38 |
NA |
2 |
Ferrari |
504 |
22 |
26 |
25 |
26 |
22 |
18 |
33 |
26 |
30 |
15 |
18 |
27 |
38 |
25 |
43 |
15 |
26 |
31 |
13 |
- |
25 |
NA |
3 |
Red Bull Racing |
417 |
15 |
16 |
21 |
12 |
23 |
23 |
14 |
13 |
32 |
22 |
26 |
27 |
10 |
12 |
23 |
22 |
12 |
18 |
25 |
25 |
26 |
NA |
4 |
McLaren F1 |
145 |
- |
8 |
- |
10 |
4 |
8 |
- |
10 |
12 |
8 |
10 |
12 |
- |
1 |
6 |
12 |
10 |
- |
10 |
19 |
5 |
NA |
5 |
Renault F1 Team |
91 |
6 |
- |
6 |
- |
- |
2 |
14 |
4 |
- |
7 |
- |
- |
4 |
22 |
2 |
1 |
- |
5 |
10 |
8 |
- |
NA |
6 |
Scuderia Toro Rosso |
85 |
1 |
2 |
1 |
- |
2 |
10 |
1 |
- |
- |
2 |
23 |
1 |
8 |
- |
4 |
- |
7 |
2 |
- |
19 |
2 |
NA |
7 |
Racing Point |
73 |
2 |
1 |
4 |
10 |
- |
- |
2 |
- |
- |
- |
12 |
- |
9 |
6 |
- |
6 |
6 |
6 |
1 |
2 |
6 |
NA |
8 |
Alfa Romeo |
57 |
4 |
6 |
2 |
1 |
- |
- |
- |
6 |
3 |
4 |
- |
6 |
- |
2 |
1 |
- |
- |
- |
- |
22 |
- |
NA |
9 |
Haas F1 Team |
28 |
8 |
- |
- |
- |
7 |
1 |
- |
- |
- |
- |
10 |
- |
- |
- |
- |
2 |
- |
- |
- |
- |
- |
NA |
10 |
Williams |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
NA |
Gráfico de las Escuderías
#> [1] " Williams" " Haas F1 Team" " Alfa Romeo"
#> [4] " Racing Point" " Scuderia Toro Rosso" " Renault F1 Team"
#> [7] " McLaren F1" " Red Bull Racing" " Ferrari"
#> [10] " Mercedes"
5. Mapa de los Circuitos de la F1
Aquí se puede observar un mapa de los 21 circuitos que pertenecen al mundial de la Formula 1. Como se puede ver en el mapa de la formula 1, los grandes premios se realizan en diferentes partes del mundo para que los aficionados no tengan que trasladarse a un único país para observar estas carreras, sino que ofrecen esta oportunidad para que las diferentes culturas del mundo se unan a este deporte y lo puedan apreciar. Lo normal de esto grandes premios es que se celebre una carrera por país por las razones mencionadas anteriormente. Por otro lado se puede destacar, como los circuitos se encuentran ubicados en diferentes continentes como América del Norte y del Sur, Europa, Asia, Oceanía, pero en el único continente que no incluye en sus competiciones es África, por lo cual es fuertemente críticado.
6.Datos Interesantes
Entre los datos interesantes se podran destacar una serie de variables importantes que obtuvieron los pilotos a lo largo de este año. Entre entas variables encontraremos el número de vicotrias que obtuvieron al igual que los podios que siginifica cuando terminas entre los 3 primeros, también destacaremos las poles que es cuando en la ronda de clasificación para obtener el orden de salida en una carrera, el piloto que se clasifica de primero se gana lo que se llama una “pole position” y por último destacaremos lo que sería las vueltas rápidas que es cuando a lo largo de la carrera el piloto que haga la vuelta más rápida se gana 1 punto más para el mundial.
Con respecto a la relación entre vicotrias y podios se puede apreciar como Lewis Hamilton fue el gran dominante con respecto a estas 2 variables obteniendo un total de 11 victorias y 17 podios. Dos casos especiales serían el Charles Leclerc y Max Verstappen, el primero obtuvo un total 10 podios siendo supeior a su rival Verstappen, pero este obtuvo una vicotria más que Leclerc provocando que en la clasificatoria mundial Verstappen quedar una posición arriba que Leclerc.
Con la otra gráfica relación entre Victorias y Poles, es bastante inusual que Lewis Hamilton no haya logrado dominar en las 2 variables como sucedió en la anterior gráfica, sino que el piloto que obtuvo más poles fue Charles Leclerc lo cual es bastante inusual de ver en la segunda temporada de un piloto de formula 1, pero esto no le basto para poder obtener una mayor cantidad de victorias durante este año.
Tabla
1 |
Lewis Hamilton |
21 |
11 |
17 |
5 |
6 |
413 |
2 |
Valtteri Bottas |
21 |
4 |
15 |
5 |
2 |
326 |
3 |
Max Verstappen |
21 |
3 |
9 |
2 |
4 |
278 |
4 |
Charles Leclerc |
21 |
2 |
10 |
7 |
4 |
264 |
5 |
Sebastian Vettel |
21 |
1 |
9 |
2 |
2 |
240 |
6 |
Carlos Sainz Jr. |
21 |
NA |
1 |
NA |
NA |
96 |
7 |
Pierre Gasly |
21 |
NA |
1 |
NA |
2 |
95 |
8 |
Alexander Albon |
21 |
NA |
NA |
NA |
NA |
92 |
9 |
Daniel Ricciardo |
21 |
NA |
NA |
NA |
NA |
54 |
Relación entre Victorias y Podios
Relación entre Vicotiras y Poles
7. Imagen
En está imagen podemos apreciar la fuerte competitivdiad que había entre las escudería de Ferrari y Mercedes que estaban pelando para ganar el campeonato mundial. De forma más detallada, se puede observar como en el Gran Premio de Rusia, Charles Leclerc esta compitiendo contra Lewis Hamilton para poder ganar este apreciado Premio.
8. Conclusión
Dentro del trabajo realizado, al final se puede observar como Lewis Hamilton logro conquistar por sexta vez el título mundial de la Formula 1. Además, se pudo observar como logro superar a su compañero de equipo Valtteri Bottas por más de 100 puntos que obtuvo el segundo lugar en la clasificación general. También se puede destacar que este año hay muchos pilotos jóvenes que tienen un gran futuro por delante en esta gran competeción como lo ha demostrado Max Verstappen, Charles Leclerc o Pierre Gasly, con sus incríbles cantidad de puntos y de los cuales los dos primeros lograron vencer a sus compañeros de equipos.
LS0tDQp0aXRsZTogPGNlbnRlcj48Rk9OVCBDT0xPUj0iUkVEIj5Gw5NSTVVSTEEgMSBURU1QT1JBREEgMjAxOTwvRk9OVD48L2NlbnRlcj4NCnN1YnRpdGxlOiAiQmVybmFyZG8gQ2FydHVzY2llbGxvKGNhcnR1c2NpQGFsdW1uaS51di5lcykiIA0KYXV0aG9yOiAiVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIg0KZGF0ZTogIkRpY2llbWJyZSBkZSAyMDIwIChhY3R1YWxpemFkbyBlbCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLSVtLSVZJylgKSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICAjY3NzOiAiLi9hc3NldHMvbXlfY3NzX2ZpbGUuY3NzIg0KICAgIHRoZW1lOiBkYXJrbHkNCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlIA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMyANCiAgICB0b2NfZmxvYXQ6IA0KICAgICAgY29sbGFwc2VkOiB0cnVlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgZGZfcHJpbnQ6IGthYmxlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCmBgYHtyIHBhY2thZ2VzLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa2xpcHB5KSAgIy0gcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInJsZXN1ci9rbGlwcHkiKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocnZlc3QpICAgICMgRm9yIHNjcmFwaW5nIHRoZSB3ZWINCmxpYnJhcnkodGlkeXIpICAgICMgRnVuY3Rpb25zIHRvIHRpZHkgb3VyIGRhdGENCmxpYnJhcnkoZHBseXIpICAgICMgUGlwZSBvcGVyYXRvciwgdGliYmxlIGhhbmRsaW5nDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShnZ3RoZW1lcykNCmxpYnJhcnkobGVhZmxldCkNCmBgYA0KDQpgYGB7ciBjaHVuay1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgICNyZXN1bHRzID0gImhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgIGNhY2hlID0gRkFMU0UsIGNhY2hlLnBhdGggPSAiL2NhY2hlcy8iLCBjb21tZW50ID0gIiM+IiwNCiAgICAgICAgICAgICAgICAgICAgICAjZmlnLndpZHRoID0gNywgI2ZpZy5oZWlnaHQ9IDcsICAgDQogICAgICAgICAgICAgICAgICAgICAgI291dC53aWR0aCA9IDcsIG91dC5oZWlnaHQgPSA3LA0KICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gVFJVRSwgIGZpZy5zaG93ID0gImhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hc3AgPSA3LzksIG91dC53aWR0aCA9ICI2MCUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIikNCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpDQpgYGANCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KDQpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmBgYA0KDQo8aHIgY2xhc3M9ImxpbmVhLWJsYWNrIj4NCg0KVHJhYmFqbyBlbGFib3JhZG8gcGFyYSBsYSBhc2lnbmF0dXJhICJQcm9ncmFtYWNpw7NuIHkgbWFuZWpvIGRlIGRhdG9zIGVuIGxhIGVyYSBkZWwgQmlnIERhdGEiIGRlIGxhIFVuaXZlcnNpdGF0IGRlIFZhbMOobmNpYSBkdXJhbnRlIGVsIGN1cnNvIDIwMjAtMjAyMS4gRWwgcmVwbyBkZWwgdHJhYmFqbyBlc3TDoSBbYXF1w61dKGh0dHBzOi8vZ2l0aHViLmNvbS9iZXJuaWNhcnR1c2NpZWxsby90cmFiYWpvX0JpZ0RhdGEpe3RhcmdldD0iX2JsYW5rIn0uIExhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmEgeSBsb3MgdHJhYmFqb3MgZGUgbWlzIGNvbXBhw7Flcm9zIHB1ZWRlbiB2ZXJzZSBbYXF1w61dKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIwLTIxLXdlYi8wNy10cmFiYWpvcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8IS0tIEVsIHDDoXJyYWZvIGRlIGFycmliYSBoYXMgZGUgZGVqYXJsbyBjYXNpIGlndWFsLCANCiAgICAgICAgc29sbyBIQVMgZGUgU1VTVElUVUlSIGxhcyAyIHZlY2VzIHF1ZSBhcGFyZWNlICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+DQoNCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCg0KIyMgICA8Rk9OVCBDT0xPUj0icmVkIj4xLiBJbnRyb2R1Y2Npw7NuPC9GT05UPg0KDQpFbiBlc3RlIHRyYWJham8gZW5zZcOxYXJlIGxvcyByZXN1bHRhZG9zIGRlbCBjYW1wZW9uYXRvIG11bmRpYWwgZGUgbGEgRm9ybXVsYSAxIGVuIGVsIGHDsW8gMjAxOSwgZG9uZGUgc2UgcG9kcmEgbW9zdHJhciB1biBjbGFybyBkb21pbmlvIHBvciBwYXJ0ZSBkZSBsYSBlc2N1ZGVyw61hICBNZXJjZWRlcyBpbnRlZ3JhZG8gcG9yIGxvcyBwaWxvdHMgTGV3aXMgSGFtaWx0b24geSBWYWx0ZXJyaSBCb3R0YXMsIGNvbiByZXNwZWN0byBhbCByZXN0byBkZSBlc2N1ZGVyw61hcyBxdWUgbm8gbGUgcHVkaWVyb24gaGFjZXIgZnJlbnRlIGEgZXN0b3MgdmVsb2NlcyBjb2NoZXMuIFRhbWJpw6luIHJlc2FsdGFyZW1vcyBkaWZlcmVudGVzIGRhdG9zIGludGVyZXNhbnRlcyByZXNwZWN0byBhbCB0ZW1hIGNvbW8gbGEgdWJpY2FjacOzbiBkZSBsb3MgY2lyY3VpdG9zIGRlIGNhcnJlcmEsIGVsIHJlbmRpbWllbnRvIGRlIGxvcyBwaWxvdG9zIGRlIGZvcm1hIGluZGl2aWR1YWwgeSBkZSBsYXMgZXNjdWRlcsOtYXMuDQoNCg0KYGBge3IsIGVjaG89RkFMU0UsZXZhbD1UUlVFLCAgb3V0LndpZHRoPSI4MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MgKGhlcmU6OmhlcmUoICIvaW1hZ2VuIiwiY29taWVuem9kZWNhcnJlcmEuanBnIikpDQpgYGANCg0KDQojIyAgIDxGT05UIENPTE9SPSJyZWQiPjIuIFBvc2ljaW9uZXMgZGUgbG9zIFBpbG90b3MgPC9GT05UPiB7LnRhYnNldH0NCg0KDQpFbiBsYSBzaWd1aWVudGUgdGFibGEgc2UgZGVzdGFjYXJhIGEgbG9zIDkgcGlsb3RvcyBxdWUgdHV2aWVyb24gdW5hIG1heW9yIGNhbnRpZGFkIGRlIHB1bnRvcyBjb21wYXJhZG8gYSBsb3MgMjAgcXVlIGNvbXBpdGVuIGEgbG8gbGFyZ28gZGUgbGEgc2VyaWUgbXVuZGlhbC4gQ29tbyBzZSBwdWVkZSBhcHJlY2lhciBoYXkgbm9tYnJlcyBkZSB0YWxsYSBtdW5kaWFsIGNvbW8gbG9zIGRlIExld2lzIEhhbWlsdG9uIHkgZWwgZGUgc3UgZXRlcm5vIHJpdmFsIFNlYmFzdGlhbiBWZXR0ZWwgcXVlIGNvbmR1Y2UgZWwgZmFtb3NvIGNvY2hlIHJvam8gZGUgRmVycmFyaSwgcGVybyBxdWUgZHVyYW50ZSBlc3RhIHRlbXBvcmFkYSBubyBwdWRvIGRlc3RhY2FyIGNvbW8gbG8gaGFjZSBoYWJpdHVhbG1lbnRlIHkgdGVybWlubyBvYnRuaWVuZG8gdW4gNXRvIGx1Z2FyIGVuIGxhIGNsYWlzaWZhY2nDs24gbXVuZGlhbC4gUG9yIG90cm8gbGFkbyBzZSBwdWVkZSBhcHJlY2lhciBjb21vIHN1IGNvbXBhw7Flcm8gZGUgZXF1aXBvIHVuIHJvb2tpZSBsbGFtYWRvIENoYXJsZXMgTGVjbGVyYyBzaWVuZG8gZWwgc2VndW5kbyBwaWxvdG8gbcOhcyBqb3ZlbiBxdWUgaGEgcGVydGVuZWNpZG8gYSBsYSBlc2N1ZGVyw61hIGRlIEZlcnJhcmkgaGF5YSBsb2dyYWRvIHZlbmNlciBlbiBzdSBkZWJ1dCBhbCA0IHZlY2VzIGNhbXBlw7NuIG11bmRpYWwgZGUgbGEgZm9ybXVsYSAxLg0KDQojIyMgPEZPTlQgQ09MT1I9InJlZCI+KipQb3NpY2lvbmVzKio8L0ZPTlQ+DQpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1UUlVFfQ0KDQpmb3JtdWxhXzEgPC0gcmVhZF9leGNlbCgiLi9kYXRvcy9mb3JtdWxhMS54bHN4Iiwgc2hlZXQgPSAxKQ0KDQpmb3JtdWxhXzEgPC0gYXNfdGliYmxlKGZvcm11bGFfMSkgJT4lIA0KICBmaWx0ZXIoYXMuaW50ZWdlcihQb3NpY2lvbikgPD0gOSkNCiMgTWFrZSBEcml2ZXIgYSBmYWN0b3JpYWwgdmFyaWFibGUsIHJlcGxhY2UgYWxsICctJyB3aXRoIHplcm9zLCBjb252ZXJ0IHRvIGxvbmcgZm9ybWF0DQoNCg0Ka25pdHI6OmthYmxlKGZvcm11bGFfMSkNCg0KDQoNCmBgYA0KDQoNCiMjIyA8Rk9OVCBDT0xPUj0icmVkIj4qKlBvc2ljaW9uZXMgZGUgY2FkYSBDYXJyZXJhKio8L0ZPTlQ+DQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPVRSVUV9DQpmb3JtdWxhXzEkUGlsb3RvIDwtIGFzLmZhY3Rvcihmb3JtdWxhXzEkUGlsb3RvKQ0KZm9ybXVsYV8xWywgLTJdIDwtIGFwcGx5KGZvcm11bGFfMVssIC0yXSwgMiwgZnVuY3Rpb24oeCkgYXMuaW50ZWdlcihnc3ViKCctJywgJzAnLCBhcy5jaGFyYWN0ZXIoeCkpKSkNCg0KZjFfbG9uZyA8LSBnYXRoZXIoZm9ybXVsYV8xLCBSYWNlLCBQdW50b3MsIFIwMTpSMjEpDQoNCmtuaXRyOjprYWJsZShmMV9sb25nKQ0KDQoNCmBgYA0KDQojIyAgIDxGT05UIENPTE9SPSJyZWQiPjMuIEV2b2x1Y2nDs24gZGUgbGFzIFBvc2ljaW9uZXMgZGUgbG9zIFBpbG90b3M8L0ZPTlQ+IHsudGFic2V0fQ0KQXF1w60gcG9kZW1vcyBvYnNlcnZhciBhIGxvcyA5IGNvcnJlZG9yZXMgcXVlIGhpY2llcm9uIG3DoXMgcHVudG9zIGEgbG8gbGFyZ28gZGUgbGEgdGVtcG9yYWRhLiBPYnNlcnZhbmRvIGxvcyBhbHRvcyB5IGJham9zIHF1ZSBoYW4gb2J0ZW5pZG8gYSBsbyBsYXJnbyBkZSBsYXMgMjEgY2FycmVyYXMgcmVhbGl6YWRhcy4gU2UgcG9kcsOhIGRlc3RhY2FyIDIgZ3LDoWZpY2FzIGRvbmRlIGVuIGxhIHByaW1lcmEgc2Ugb2JzZXJ2YXJhIGVsIHJlbmRpbWllbnRvcyBkZSBsb3MgcGlsb3RvcyBlbiByZWxhY2nDs24gZGUgbG9zIHB1bnRvcyBvYnRlbmlkb3MgY29uIHJlc3BlY3RvIGEgY2FkYSBjYXJyZXJhIGRlbCBjYW1wZW9uYXRvIG11bmRpYWwsIG1pZW50cmFzIHF1ZSBlbiBsYSBzZWd1bmRhIGdyw6FmaWNhIHNlIGRldGFsbGFyYSBlbCByZWRuaW1pZW50byBkZSBmb3JtYSBpbmRpdmlkdWFsIGRlIGNhZGEgcGlsb3RvLiANCg0KIyMjIDxGT05UIENPTE9SPSJyZWQiPioqR3LDoWZpY2EqKjwvRk9OVD4NCmBgYHtyIHByZXNzdXJlLCBlY2hvPUZBTFNFLCBldmFsPVRSVUUsICBvdXQud2lkdGg9IjgwJSJ9DQpmMV9sb25nIDwtIGdhdGhlcihmb3JtdWxhXzEsIFJhY2UsIFB1bnRvcywgUjAxOlIyMSkNCg0KDQoNCmcgPC0gZ2dwbG90KGYxX2xvbmcsIGFlcyh4ID0gUmFjZSwgeSA9IFB1bnRvcywgZ3JvdXAgPSBQaWxvdG8sIGNvbG91ciA9IFBpbG90bykpICsgDQogIGdlb21fbGluZSgpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShicmVha3M9YygnUjAxJywgJ1IwNicsICdSMTEnLCAnUjE2JywgJ1IyMScpKSArDQogIGxhYnModGl0bGUgPSAnRjEgcmVzdWx0YWRvcyAyMDE5LCB0b3AgOSBkcml2ZXJzJykgKyBnZW9tX3BvaW50KCkNCg0KZ2dwbG90bHkoZykNCg0KYGBgDQoNCg0KDQojIyMgPEZPTlQgQ09MT1I9InJlZCI+KipHcsOhZmljYSBwb3IgUGlsb3RvKio8L0ZPTlQ+DQpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1UUlVFLCAgb3V0LndpZHRoPSI4MCUifQ0KZjFfbG9uZyA8LSBnYXRoZXIoZm9ybXVsYV8xLCBSYWNlLCBQdW50b3MsIFIwMTpSMjEpDQoNCg0KICAgICAgICAgIA0KZiA8LSBnZ3Bsb3QoZjFfbG9uZywgYWVzKHggPSBSYWNlLCB5ID0gUHVudG9zLCBncm91cCA9IFBpbG90bywgY29sb3VyID0gUGlsb3RvKSkgKyANCiAgZ2VvbV9saW5lKHNob3cubGVnZW5kID0gRkFMU0UpICsgZmFjZXRfd3JhcCh+IFBpbG90bykgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGJyZWFrcz1jKCdSMDEnLCAnUjA2JywgJ1IxMScsICdSMTYnLCAnUjIxJykpICsNCiAgbGFicyh0aXRsZSA9ICdGMSByZXN1bHRhZG9zIDIwMTksIHRvcCA5IGRyaXZlcnMnKSArIGdlb21fcG9pbnQoKSANCg0KZ2dwbG90bHkoZikNCg0KYGBgDQoNCg0KDQojIyAgIDxGT05UIENPTE9SPSJyZWQiPjQuIFBvc2ljaW9uZXMgZGUgbGFzIEVzY3VlcsOtYXMgPC9GT05UPiB7LnRhYnNldH0NCg0KRW4gZXN0ZSBhcGFydGFkbyBkZWwgdHJhYmFqbyBkZWphcmVtb3MgYWwgbGFkbyBhIGxvcyBwaWxvdG9zIHkgbm9zIGVuZm9jYXJlbW9zIGVuIGxhcyBlc2N1ZGVyw61hcy4gRW4gZWwgc2lndWllbnRlIGdyw6FmaWNvIHNlIHBvZHLDoSBvYnNlcnZhciBkZSBmb3JtYSBvcmRlbmFkYSBsYXMgcG9zaWNpb25lcyBxdWUgb2J0dXZpZXJvbiBsb3MgZXF1aXBvcyBkZSBsYSBmb3JtdWxhIDEsIGNvbiB1biBjbGFybyBkb21pbmlvIGRlIE1lcmNlZGVzIGFsIHJlc3RvIGRlIGVzY3VkZXLDrWFzIG9idGVuaWVuZG8gbcOhcyBkZSAyMDAgcHVudG9zIGNvbiByZXNwZWN0byBhbCBzZWd1bmRvIGx1Z2FyLiBPdHJvIGRhdG8gaW50ZXJlc2FudGUgcXVlIHNlIHBvZHLDrWEgb2J0ZW5lciBhIHBhcnRpciBkZSBlc3RhIGluZm9ybWFjacOzbiBlcyBxdWUgbm8gZXMgY29pbmNpZGVuY2lhIHF1ZSBsYSB2ZW50YWphIGRlIGxvcyBwcmltZXJvcyAzIGVxdWlwb3Mgc2VhIHRhbiBzdXBlaW9yIGFsIHJlc3RvIGRlIGxhcyBlc2N1ZGVyw61hcywgeWEgcXVlIGVsIHByZXN1cHVlc3RvIHF1ZSBwb3NlZW4gc2VhIG1heW9yIGFsIHJlc3RvLiBEZSBmb3JtYSBtw6FzIGRldGFsbGFkYSBlbCBlcXVpcG8gZGUgTWVyY2VkZXMgdHV2byB1bmEgaW52ZXJzacOzbiBkdXJhbnRlIGVzdGUgYcOxbyBkZSA3MDAgbWlsbG9uZXMsIEZlcnJhcmkgZGUgNTAwIG1pbGxvbmVzLCBSZWQgQnVsbCBkZSAzMDAgbWlsbG9uZXMgeSBlbCByZXN0byBkZSBsb3MgNyBwYXJ0aWNpcGFudGVzIHN1IHByZXN1cHVlc3RvIG5vIGxsZWdhIG5pIHNpcXVpZXJhIGEgbG9zIDE1MCBtaWxsb25lcy4gUG9yIGVzdGEgcmF6w7NuLCBsYSBGSUEgbGEgb3JnYW5pemFjacOzbiBlbmNhcmdhZGEgZGUgcmVndWxhciBsYXMgY29tcGV0aWNpb25lcyBkZSBhdXRvbW92aWxpc21vIGRlaWNpZGnDsyBpbXBsYW50YXIgcGFyYSBlbCAyMDIyIHVuIGzDrW1pdGUgYWwgcHJlc3VwdWVzdG8gZGUgbGFzIGVzY3VkZXLDrWFzIHF1ZSBzZXLDrWEgaWd1YWwgYSAxNTAgbWlsbG9uZXMsIHBhcmEgYnVzY2FyIHF1ZSBleGlzdGEgbcOhcyBjb21wZXRpdGl2aWRhZCB5IG5vIGRlIHF1ZSBzaWVtcHJlIGRvbWluZSB1bmEgZXNjdWRlcsOtYSBhIGxvIGxhcmdvIGRlbCB0aWVtcG8sIHNpbm8gcGFyYSBxdWUgdGFtYmnDqW4gbG9zIHBpbG90b3MgZGVtdWVzdHJlbiBzdSBoYWJpbGlkYWQgZGUgY29uZHVjY2nDs24gYWwgdGVuZXIgY29jaGVzIG3DoXMgc2ltaWxhcmVzLg0KDQojIyMgPEZPTlQgQ09MT1I9InJlZCI+KipUYWJsYSBkZSBsYXMgRXNjdWRlcsOtYXMqKjwvRk9OVD4NCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPVRSVUV9DQoNCmVzY3VkZXJpYSA8LSByZWFkX2V4Y2VsKCIuL2RhdG9zL2Zvcm11bGExLnhsc3giLCBzaGVldCA9IDIpDQoNCmtuaXRyOjprYWJsZShlc2N1ZGVyaWEpDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9RkFMU0V9DQpzdHIoZXNjdWRlcmlhKSAgIy0gbGEgdi4gcmVnaW9uIGVzIGRlIHRpcG8gY2hhcmFjdGVyDQoNCmVzY3VkZXJpYSA8LSBlc2N1ZGVyaWEgJT4lIG11dGF0ZShFc2N1ZGVyw61hID0gZm9yY2F0czo6YXNfZmFjdG9yKEVzY3VkZXLDrWEpKSAgICMtIGNvbnZlcnRpbW9zIGxhIHYuIHJlZ2lvbiBlbiBmYWN0b3IgY29uIGxhIGYuIGFzX2ZhY3RvcigpDQoNCnN0cihlc2N1ZGVyaWEpICAjLSBsYSB2LiByZWdpb24gYWhvcmEgZXMgdW4gZmFjdG9yDQpsZXZlbHMoZXNjdWRlcmlhJEVzY3VkZXLDrWEpICMtIGxvcyBsZXZlbHMgZGVsICBlc3TDoW4gb3JkZW5hZG9yIGFsZmFiw6l0aWNhbWVudGUNCg0KZXNjdWRlcmlhIDwtIGVzY3VkZXJpYSAlPiUgbXV0YXRlKEVzY3VkZXLDrWEgPSBmb3JjYXRzOjpmY3RfcmVvcmRlcihFc2N1ZGVyw61hLCBQdW50b3MpKSAjLSByZW9yZGVuYW1vcyBsb3Mgbml2ZWxlcyBkZWwgZmFjdG9yIGVuIGYuIGRlIFBvYl9yZWdpb24NCg0KbGV2ZWxzKGVzY3VkZXJpYSRFc2N1ZGVyw61hKSAjLSBhaG9yYSBsb3MgbGV2ZWxzIGRlbCBmYWN0b3IgZXN0YW4gb3JkZW5hZG9yIGVuIGZ1bmNpb24gZGUgbGEgcG9ibGFjacOzbg0KDQoNCg0KDQoNCmBgYA0KDQojIyMgPEZPTlQgQ09MT1I9InJlZCI+KipHcsOhZmljbyBkZSBsYXMgRXNjdWRlcsOtYXMqKjwvRk9OVD4NCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPVRSVUUsICBvdXQud2lkdGg9IjgwJSJ9DQplc2N1ZGVyaWEgPC0gZXNjdWRlcmlhICU+JSBtdXRhdGUoRXNjdWRlcsOtYSA9IGZvcmNhdHM6OmZjdF9yZW9yZGVyKEVzY3VkZXLDrWEsIFB1bnRvcykpDQoNCmxldmVscyhlc2N1ZGVyaWEkRXNjdWRlcsOtYSkNCg0KZ2dwbG90KGVzY3VkZXJpYSwgYWVzKHggPSBQdW50b3MsIHkgPSBFc2N1ZGVyw61hKSkgKyBnZW9tX2NvbChmaWxsID0gYygiY3lhbiIsICJyZWQiLCJkYXJrYmx1ZSIsIm9yYW5nZSIsICJ5ZWxsb3ciLCAic3RlZWxibHVlIiwgInBpbmsiLCAiYnJvd24xIiwgImNob2NvbGF0ZTQiLCAiZGFya2dyYXkiKSkgKyBnZW9tX3RleHQoYWVzKGxhYmVsID0gUHVudG9zKSwgbnVkZ2VfeCA9IDI1KSANCg0KYGBgDQoNCg0KDQoNCiMjICAgPEZPTlQgQ09MT1I9IlJFRCI+NS4gTWFwYSBkZSBsb3MgQ2lyY3VpdG9zIGRlIGxhIEYxIDwvRk9OVD4NCg0KQXF1w60gc2UgcHVlZGUgb2JzZXJ2YXIgdW4gbWFwYSBkZSBsb3MgMjEgY2lyY3VpdG9zIHF1ZSBwZXJ0ZW5lY2VuIGFsIG11bmRpYWwgZGUgbGEgRm9ybXVsYSAxLiBDb21vIHNlIHB1ZWRlIHZlciBlbiBlbCBtYXBhIGRlIGxhIGZvcm11bGEgMSwgbG9zIGdyYW5kZXMgcHJlbWlvcyBzZSByZWFsaXphbiBlbiBkaWZlcmVudGVzIHBhcnRlcyBkZWwgbXVuZG8gcGFyYSBxdWUgbG9zIGFmaWNpb25hZG9zIG5vIHRlbmdhbiBxdWUgdHJhc2xhZGFyc2UgYSB1biDDum5pY28gcGHDrXMgcGFyYSBvYnNlcnZhciBlc3RhcyBjYXJyZXJhcywgc2lubyBxdWUgb2ZyZWNlbiBlc3RhIG9wb3J0dW5pZGFkIHBhcmEgcXVlIGxhcyBkaWZlcmVudGVzIGN1bHR1cmFzIGRlbCBtdW5kbyBzZSB1bmFuIGEgZXN0ZSBkZXBvcnRlIHkgbG8gcHVlZGFuIGFwcmVjaWFyLiBMbyBub3JtYWwgZGUgZXN0byBncmFuZGVzIHByZW1pb3MgZXMgcXVlIHNlIGNlbGVicmUgdW5hIGNhcnJlcmEgcG9yIHBhw61zIHBvciBsYXMgcmF6b25lcyBtZW5jaW9uYWRhcyBhbnRlcmlvcm1lbnRlLiBQb3Igb3RybyBsYWRvIHNlIHB1ZWRlIGRlc3RhY2FyLCBjb21vIGxvcyBjaXJjdWl0b3Mgc2UgZW5jdWVudHJhbiB1YmljYWRvcyBlbiBkaWZlcmVudGVzIGNvbnRpbmVudGVzIGNvbW8gQW3DqXJpY2EgZGVsIE5vcnRlIHkgZGVsIFN1ciwgRXVyb3BhLCBBc2lhLCBPY2VhbsOtYSwgcGVybyBlbiBlbCDDum5pY28gY29udGluZW50ZSBxdWUgbm8gaW5jbHV5ZSBlbiBzdXMgY29tcGV0aWNpb25lcyBlcyDDgWZyaWNhLCBwb3IgbG8gY3VhbCBlcyBmdWVydGVtZW50ZSBjcsOtdGljYWRvLg0KYGBge3IgZXZhbCA9IFRSVUUsIGVjaG8gPSBGQUxTRSwgIG91dC53aWR0aD0iODAlIn0NCg0KcCA8LSBsZWFmbGV0KCkgJT4lDQogIGFkZFRpbGVzKCkgJT4lIA0KICBzZXRWaWV3KGxuZyA9IC0yLjQzNTk3MywgbGF0ID0gNTIuMzc4MDUxLCB6b29tID0gMSkgJT4lIA0KICBhZGRNYXJrZXJzKGxuZyA9IDUwLjUxNDUyMSwgbGF0ID0gMjYuMDMxNjk5LCBwb3B1cCA9ICJHUCBCQUhSRUlOIikgJT4lIA0KICBhZGRNYXJrZXJzKGxuZyA9IDE0NC45NjMyNiwgbGF0ID0gLTM3Ljg0NDc2LCBwb3B1cCA9ICJHUCBBVVNUUkFMSUEiKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAxMjEuMjE5NzIsIGxhdCA9IDMxLjMzODg5LCBwb3B1cCA9ICJHUCBDSElOQSIpICU+JQ0KICBhZGRNYXJrZXJzKGxuZyA9IDQ5Ljg5MjAxLCBsYXQgPSA0MC4zNzc2NywgcG9wdXAgPSAiR1AgQVpFUkJBSVnDgU4iKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAyLjI1ODA2MywgbGF0ID0gNDEuNTY5NDY5LCBwb3B1cCA9ICJHUCBFU1BBw5FBIikgJT4lDQogIGFkZE1hcmtlcnMobG5nID0gNy40MjczMiwgbGF0ID0gNDMuNzM5NzYgLCBwb3B1cCA9ICJHUCBNT05BQ08iKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAtNzMuNTI0MTcsIGxhdCA9IDQ1LjUwODM4LCBwb3B1cCA9ICJHUCBDQU5BREEiKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAgNS43OTE3NywgbGF0ID0gNDMuMjUzNjQsIHBvcHVwID0gIkdQIEZSQU5DSUEiKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAxNC43NjQzMTYsIGxhdCA9IDQ3LjIyMjEzMSwgcG9wdXAgPSAiR1AgQVVTVFJJQSIpICU+JQ0KICBhZGRNYXJrZXJzKGxuZyA9IC0xLjAxNDI5OSwgbGF0ID0gNTIuMDcxODEyLCBwb3B1cCA9ICJHUCBJTkdMQVRFUlJBIikgJT4lDQogIGFkZE1hcmtlcnMobG5nID0gIDguNTY2NzUxLCBsYXQgPSA0OS4zMjczMTcsIHBvcHVwID0gIkdQIEFMRU1BTklBIikgJT4lDQogIGFkZE1hcmtlcnMobG5nID0gMTkuMTUwMSwgbGF0ID0gNDcuMzQ1MCwgcG9wdXAgPSAiR1AgSFVOR1JJQSIpICU+JQ0KICBhZGRNYXJrZXJzKGxuZyA9IDUuOTY4MzcsIGxhdCA9IDUwLjQ0NDc0LCBwb3B1cCA9ICJHUCBCRUxHSUNBIikgJT4lDQogIGFkZE1hcmtlcnMobG5nID0gOS4yODI2NDEsIGxhdCA9IDQ1LjYxOTEwNiwgcG9wdXAgPSAiR1AgSVRBTElBIikgJT4lDQogIGFkZE1hcmtlcnMobG5nID0gMTAzLjg2Mzk1LCBsYXQgPSAxLjI5MTU2LCBwb3B1cCA9ICJHUCBTSU5HQVBVUiIpICU+JQ0KICBhZGRNYXJrZXJzKGxuZyA9IDM5LjcyNTY5LCBsYXQgPSA0My41OTkxNywgcG9wdXAgPSAiR1AgUlVTSUEiKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAgMTM2LjU0MTgzOSwgbGF0ID0gIDM0Ljg0NTIwNyAsIHBvcHVwID0gIkdQIEpBUE9OIikgJT4lDQogIGFkZE1hcmtlcnMobG5nID0gLTk5LjA5MjIzOCwgbGF0ID0gMTkuNDAzMzcsIHBvcHVwID0gIkdQIE1FWElDTyIpICU+JQ0KICBhZGRNYXJrZXJzKGxuZyA9IC05Ny42MzY0MDksIGxhdCA9IDMwLjEzNDQxNCwgcG9wdXAgPSAiR1AgRVNUQURPUyBVTklET1MiKSAlPiUNCiAgYWRkTWFya2VycyhsbmcgPSAtNDYuNjk3MTcsIGxhdCA9IC0yMy43MDA1MjIsIHBvcHVwID0gIkdQIEJSQVNJTCIpDQoNCnANCg0KYGBgDQoNCiMjICAgPEZPTlQgQ09MT1I9InJlZCI+Ni5EYXRvcyBJbnRlcmVzYW50ZXMgPC9GT05UPiAgey50YWJzZXR9DQoNCkVudHJlIGxvcyBkYXRvcyBpbnRlcmVzYW50ZXMgc2UgcG9kcmFuIGRlc3RhY2FyIHVuYSBzZXJpZSBkZSB2YXJpYWJsZXMgaW1wb3J0YW50ZXMgcXVlIG9idHV2aWVyb24gbG9zIHBpbG90b3MgYSBsbyBsYXJnbyBkZSBlc3RlIGHDsW8uIEVudHJlIGVudGFzIHZhcmlhYmxlcyBlbmNvbnRyYXJlbW9zIGVsIG7Dum1lcm8gZGUgdmljb3RyaWFzIHF1ZSBvYnR1dmllcm9uIGFsIGlndWFsIHF1ZSBsb3MgcG9kaW9zIHF1ZSBzaWdpbmlmaWNhIGN1YW5kbyB0ZXJtaW5hcyBlbnRyZSBsb3MgMyBwcmltZXJvcywgdGFtYmnDqW4gZGVzdGFjYXJlbW9zIGxhcyBwb2xlcyBxdWUgZXMgY3VhbmRvIGVuIGxhIHJvbmRhIGRlIGNsYXNpZmljYWNpw7NuIHBhcmEgb2J0ZW5lciBlbCBvcmRlbiBkZSBzYWxpZGEgZW4gdW5hIGNhcnJlcmEsIGVsIHBpbG90byBxdWUgc2UgY2xhc2lmaWNhIGRlIHByaW1lcm8gc2UgZ2FuYSBsbyBxdWUgc2UgbGxhbWEgdW5hICJwb2xlIHBvc2l0aW9uIiB5IHBvciDDumx0aW1vIGRlc3RhY2FyZW1vcyBsbyBxdWUgc2Vyw61hIGxhcyB2dWVsdGFzIHLDoXBpZGFzIHF1ZSBlcyBjdWFuZG8gYSBsbyBsYXJnbyBkZSBsYSBjYXJyZXJhIGVsIHBpbG90byBxdWUgaGFnYSBsYSB2dWVsdGEgbcOhcyByw6FwaWRhIHNlIGdhbmEgMSBwdW50byBtw6FzIHBhcmEgZWwgbXVuZGlhbC4NCg0KQ29uIHJlc3BlY3RvIGEgbGEgcmVsYWNpw7NuIGVudHJlIHZpY290cmlhcyB5IHBvZGlvcyBzZSBwdWVkZSBhcHJlY2lhciBjb21vIExld2lzIEhhbWlsdG9uIGZ1ZSBlbCBncmFuIGRvbWluYW50ZSBjb24gcmVzcGVjdG8gYSBlc3RhcyAyIHZhcmlhYmxlcyBvYnRlbmllbmRvIHVuIHRvdGFsIGRlIDExIHZpY3RvcmlhcyB5IDE3IHBvZGlvcy4gRG9zIGNhc29zIGVzcGVjaWFsZXMgc2Vyw61hbiBlbCBDaGFybGVzIExlY2xlcmMgeSBNYXggVmVyc3RhcHBlbiwgZWwgcHJpbWVybyBvYnR1dm8gdW4gdG90YWwgMTAgcG9kaW9zIHNpZW5kbyBzdXBlaW9yIGEgc3Ugcml2YWwgVmVyc3RhcHBlbiwgcGVybyBlc3RlIG9idHV2byB1bmEgdmljb3RyaWEgbcOhcyBxdWUgTGVjbGVyYyBwcm92b2NhbmRvIHF1ZSBlbiBsYSBjbGFzaWZpY2F0b3JpYSBtdW5kaWFsIFZlcnN0YXBwZW4gcXVlZGFyIHVuYSBwb3NpY2nDs24gYXJyaWJhIHF1ZSBMZWNsZXJjLg0KDQpDb24gbGEgb3RyYSBncsOhZmljYSByZWxhY2nDs24gZW50cmUgVmljdG9yaWFzIHkgUG9sZXMsIGVzIGJhc3RhbnRlIGludXN1YWwgcXVlIExld2lzIEhhbWlsdG9uIG5vIGhheWEgbG9ncmFkbyBkb21pbmFyIGVuIGxhcyAyIHZhcmlhYmxlcyBjb21vIHN1Y2VkacOzIGVuIGxhIGFudGVyaW9yIGdyw6FmaWNhLCBzaW5vIHF1ZSBlbCBwaWxvdG8gcXVlIG9idHV2byBtw6FzIHBvbGVzIGZ1ZSBDaGFybGVzIExlY2xlcmMgbG8gY3VhbCBlcyBiYXN0YW50ZSBpbnVzdWFsIGRlIHZlciBlbiBsYSBzZWd1bmRhIHRlbXBvcmFkYSBkZSB1biBwaWxvdG8gZGUgZm9ybXVsYSAxLCBwZXJvIGVzdG8gbm8gbGUgYmFzdG8gcGFyYSBwb2RlciBvYnRlbmVyIHVuYSBtYXlvciBjYW50aWRhZCBkZSB2aWN0b3JpYXMgZHVyYW50ZSBlc3RlIGHDsW8uIA0KDQojIyMgPEZPTlQgQ09MT1I9InJlZCI+KipUYWJsYSoqPC9GT05UPg0KYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9VFJVRX0NCg0KZGF0b3NfaW50ZXJlc2FudGVzIDwtIHJlYWRfZXhjZWwoIi4vZGF0b3MvZm9ybXVsYTEueGxzeCIsIHNoZWV0ID0gMykNCg0Ka25pdHI6OmthYmxlKGRhdG9zX2ludGVyZXNhbnRlcykNCmBgYA0KDQoNCiMjIyA8Rk9OVCBDT0xPUj0icmVkIj4qKlJlbGFjacOzbiBlbnRyZSBWaWN0b3JpYXMgeSBQb2Rpb3MqKjwvRk9OVD4NCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPVRSVUUsICBvdXQud2lkdGg9IjgwJSJ9DQoNCmdncGxvdChkYXRvc19pbnRlcmVzYW50ZXMsIGFlcyh4ID0gVmljdG9yaWFzLCB5ID0gUG9kaW9zLCBjb2xvciA9IFBpbG90bykpICsgZ2VvbV9wb2ludCgpICsNCnNjYWxlX3hfY29udGludW91cyh0cmFucz0nbG9nMTAnLCBsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQpnZ3JlcGVsOjpnZW9tX2xhYmVsX3JlcGVsKGdncGxvdDI6OmFlcyhsYWJlbCA9IFBpbG90bykpICsgbGFicyh0aXRsZSA9ICJSRUxBQ0nDk04gRU5UUkUgTEFTIFZJQ1RPUklBUyBZIFBPRElPUyBERSBMT1MgUElMT1RPUyBERSBGMSIgLCB5ID0gIlBvZGlvcyIsIHggPSAiVmljdG9yaWFzIikgKw0KdGhlbWVfYncoKSArICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCmBgYA0KDQojIyMgPEZPTlQgQ09MT1I9InJlZCI+KipSZWxhY2nDs24gZW50cmUgVmljb3RpcmFzIHkgUG9sZXMqKjwvRk9OVD4NCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPVRSVUUsICBvdXQud2lkdGg9IjgwJSJ9DQoNCnAgPC0gZ2dwbG90KGRhdG9zX2ludGVyZXNhbnRlcywgYWVzKHggPSBWaWN0b3JpYXMsIHkgPSBQb2xlcywgY29sb3IgPSBQaWxvdG8pKSArIGdlb21fcG9pbnQoKSArDQpzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJywgbGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KZ2dyZXBlbDo6Z2VvbV9sYWJlbF9yZXBlbChnZ3Bsb3QyOjphZXMobGFiZWwgPSBQaWxvdG8pKSArIGxhYnModGl0bGUgPSAiUkVMQUNJw5NOIEVOVFJFIExBUyBWSUNUT1JJQVMgWSBQT0xFUyBERSBMT1MgUElMT1RPUyBERSBGMSIgLCB5ID0gIlBvbGVzIiwgeCA9ICJWaWN0b3JpYXMiKSArDQp0aGVtZV9idygpICsgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KDQoNCg0KYGBgDQoNCg0KYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9VFJVRSwgIG91dC53aWR0aD0iODAlIn0NCg0KZ2dwbG90bHkocCkNCg0KYGBgDQoNCiMjICAgPEZPTlQgQ09MT1I9InJlZCI+Ny4gSW1hZ2VuIDwvRk9OVD4gDQogRW4gZXN0w6EgaW1hZ2VuIHBvZGVtb3MgYXByZWNpYXIgbGEgZnVlcnRlIGNvbXBldGl0aXZkaWFkIHF1ZSBoYWLDrWEgZW50cmUgbGFzIGVzY3VkZXLDrWEgZGUgRmVycmFyaSB5IE1lcmNlZGVzIHF1ZSBlc3RhYmFuIHBlbGFuZG8gcGFyYSBnYW5hciBlbCBjYW1wZW9uYXRvIG11bmRpYWwuIERlIGZvcm1hIG3DoXMgZGV0YWxsYWRhLCBzZSBwdWVkZSBvYnNlcnZhciBjb21vIGVuIGVsIEdyYW4gUHJlbWlvIGRlIFJ1c2lhLCBDaGFybGVzIExlY2xlcmMgZXN0YSBjb21waXRpZW5kbyBjb250cmEgTGV3aXMgSGFtaWx0b24gcGFyYSBwb2RlciBnYW5hciBlc3RlIGFwcmVjaWFkbyBQcmVtaW8uIA0KIA0KYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9VFJVRSwgIG91dC53aWR0aD0iODAlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzIChoZXJlOjpoZXJlKCAiL2ltYWdlbiIsImZlcnJhcml2c21lcmNlZGVzLmpwZyIpKQ0KDQpgYGANCg0KDQoNCg0KIyMgIDxGT05UIENPTE9SPSJyZWQiPjguIENvbmNsdXNpw7NuPC9GT05UPg0KDQpEZW50cm8gZGVsIHRyYWJham8gcmVhbGl6YWRvLCBhbCBmaW5hbCBzZSBwdWVkZSBvYnNlcnZhciBjb21vIExld2lzIEhhbWlsdG9uIGxvZ3JvIGNvbnF1aXN0YXIgcG9yIHNleHRhIHZleiBlbCB0w610dWxvIG11bmRpYWwgZGUgbGEgRm9ybXVsYSAxLiBBZGVtw6FzLCBzZSBwdWRvIG9ic2VydmFyIGNvbW8gbG9ncm8gc3VwZXJhciBhIHN1IGNvbXBhw7Flcm8gZGUgZXF1aXBvIFZhbHR0ZXJpIEJvdHRhcyBwb3IgbcOhcyBkZSAxMDAgcHVudG9zIHF1ZSBvYnR1dm8gZWwgc2VndW5kbyBsdWdhciBlbiBsYSBjbGFzaWZpY2FjacOzbiBnZW5lcmFsLiBUYW1iacOpbiBzZSBwdWVkZSBkZXN0YWNhciBxdWUgZXN0ZSBhw7FvIGhheSBtdWNob3MgcGlsb3RvcyBqw7N2ZW5lcyBxdWUgdGllbmVuIHVuIGdyYW4gZnV0dXJvIHBvciBkZWxhbnRlIGVuIGVzdGEgZ3JhbiBjb21wZXRlY2nDs24gY29tbyBsbyBoYSBkZW1vc3RyYWRvIE1heCBWZXJzdGFwcGVuLCBDaGFybGVzIExlY2xlcmMgbyBQaWVycmUgR2FzbHksIGNvbiBzdXMgaW5jcsOtYmxlcyBjYW50aWRhZCBkZSBwdW50b3MgeSBkZSBsb3MgY3VhbGVzIGxvcyBkb3MgcHJpbWVyb3MgbG9ncmFyb24gdmVuY2VyIGEgc3VzIGNvbXBhw7Flcm9zIGRlIGVxdWlwb3MuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPVRSVUUsICBvdXQud2lkdGg9IjgwJSJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyAoaGVyZTo6aGVyZSggIi9pbWFnZW4iLCJoYW1pbHRvbmdhbmFuZG9sYXVsdGltYWNhcnJlcmEuanBnIikpDQoNCmBgYA0KDQojIyAgIDxGT05UIENPTE9SPSJyZWQiPjkuIFJlZmVyZW5jaWFzIDwvRk9OVD4gDQoiaHR0cHM6Ly93d3cuc3Fsc2VydmVyY2VudHJhbC5jb20vYXJ0aWNsZXMvYW5hbHl6aW5nLWZvcm11bGEtMS1yZXN1bHRzLWluLXIiDQoNCiJodHRwczovL2VzLndpa2lwZWRpYS5vcmcvd2lraS9UZW1wb3JhZGFfMjAxOV9kZV9GJUMzJUIzcm11bGFfMSINCg0KDQoNCg0KDQoNCg0KDQo=