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

El título del trabajo es: Análisis de las mejores 100 universidades del mundo. Nuestro objetivo es hacer un estudio de la evolución respecto a diferentes variables de tres dataset que contienen diferentes rankings de las mejores 100 universidades del mundo desde el año 2012 hasta 2015. Planteamos preguntas como qué país tiene más universidades en el ranking, cuál es el número de estudiantes en las mejores universidades, o la relación entre la posición de una universidad en el ránking con su posición respecto al nivel de educación o el número de publicaciones.

Además, queremos mostrar la información de manera más visual mediante gráficos dinámicos comparando la evolución de las universidades en el top 10 durante los años, la posición de los diferentes países en el ránking, así como su evolución a lo largo del tiempo.

Vamos a basar, entre otros, en estas fuentes:

  1. Y. Bano, S. Vasantha. Influence Of University Reputation On Employability. 2019

  2. Datos recientes sobre el ránking de Shanghai

  3. What impact does university reputation have on students?

  4. Universidades líderes en el mundo. El posicionamiento de España. 2020


2. Datos

Datos

# Cargamos los datos previamente descargados de la página Kaggle
cwur <- rio::import("./datos/cwurData.csv")
Shanghai <- rio::import("./datos/shanghaiData.csv")
times_data <- rio::import("./datos/timesData.csv")

Hemos utilizado los datos de varias instituciones que han hecho un ranking de las mejores universidades introduciendo variables diferentes, sacados de Kaggle. Esas instituciones son:

  1. Center for World University Rankings (2200 filas, 14 columnas), que desde su fundación en 2012 recopila los datos de las mejores universidades desde Arabia Saudita.

  2. Times Higher Education World University Ranking (2603 rows, 14 columns), fundado en Reino Unido en 2010, es una de las clasificaciones más influyentes del momento, aunque algo criticado por su especial fijación en las universidades inglesas.

  3. Academic Ranking of World Universities (4897 filas, 11 columnas), más conocido como el tan influyente Shangai Ranking, que comenzó a publicar sus listados en 2003.

Todas las modificaciones que hemos hecho las podéis observar en la pestaña Limpieza de datos

Tidy

En realidad nuestros datos no han tenido que ser muy limpiados, ya que en la página de Kaggle aparecían bastante bien. Sin embargo, añadimos aquí cualquier modificación que han podido sufrir.

Aquí podemos ver un resumen de las variables según su tipo, y teniendo en cuenta también los NA’s

visdat::vis_dat(cwur) 
visdat::vis_dat(times_data)
visdat::vis_dat(Shanghai)

Sí vamos a filtrar los datos para obtener los mismos rangos de tiempo y el ranking de las mejores 100 universidades cada año, y poder así homogeneizar nuestro análisis.

cwur1 <- cwur %>% 
  filter(world_rank <= 100)

times1 <- times_data %>% 
  filter(year >=  2012 , year <= 2015) %>% 
  mutate(world_rank_N = as.integer(world_rank)) %>% 
  filter(world_rank_N <= 100)
 

Shanghai1 <- Shanghai %>%
  filter(year >=  2012 , year <= 2015) %>% 
  mutate(world_rank_N = as.integer(world_rank)) %>% 
  filter(world_rank_N <= 100)

  

Además, hacemos un repaso a los tipos de datos con los que vamos a trabajar.


str(cwur1)
#> 'data.frame':    400 obs. of  14 variables:
#>  $ world_rank          : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ institution         : chr  "Harvard University" "Massachusetts Institute of Technology" "Stanford University" "University of Cambridge" ...
#>  $ country             : chr  "USA" "USA" "USA" "United Kingdom" ...
#>  $ national_rank       : int  1 2 3 1 4 5 2 6 7 8 ...
#>  $ quality_of_education: int  7 9 17 10 2 8 13 14 23 16 ...
#>  $ alumni_employment   : int  9 17 11 24 29 14 28 31 21 52 ...
#>  $ quality_of_faculty  : int  1 3 5 4 7 2 9 12 10 6 ...
#>  $ publications        : int  1 12 4 16 37 53 15 14 13 6 ...
#>  $ influence           : int  1 4 2 16 22 33 13 6 12 5 ...
#>  $ citations           : int  1 4 2 11 22 26 19 15 14 3 ...
#>  $ broad_impact        : int  NA NA NA NA NA NA NA NA NA NA ...
#>  $ patents             : int  5 1 15 50 18 101 26 66 5 16 ...
#>  $ score               : num  100 91.7 89.5 86.2 85.2 ...
#>  $ year                : int  2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...

str(times1)
#> 'data.frame':    402 obs. of  15 variables:
#>  $ world_rank            : chr  "1" "2" "2" "4" ...
#>  $ university_name       : chr  "California Institute of Technology" "Harvard University" "Stanford University" "University of Oxford" ...
#>  $ country               : chr  "United States of America" "United States of America" "United States of America" "United Kingdom" ...
#>  $ teaching              : num  95.7 95.8 94.8 89.5 91.5 90.5 92.7 88.8 89.4 82.8 ...
#>  $ international         : chr  "56.0" "67.5" "57.2" "91.9" ...
#>  $ research              : num  98.2 97.4 98.9 96.6 99.1 94.2 87.4 88.7 90.8 99.4 ...
#>  $ citations             : num  99.9 99.8 99.8 97.9 100 97.3 100 93.9 99.4 99.4 ...
#>  $ income                : chr  "97.0" "35.9" "63.8" "62.1" ...
#>  $ total_score           : chr  "94.8" "93.9" "93.9" "93.6" ...
#>  $ num_students          : chr  "2,243" "20,152" "15,596" "19,919" ...
#>  $ student_staff_ratio   : num  6.9 8.9 7.8 11.6 8.4 11.8 9 11.7 6.9 16.4 ...
#>  $ international_students: chr  "27%" "25%" "22%" "34%" ...
#>  $ female_male_ratio     : chr  "33 : 67" "" "42 : 58" "46 : 54" ...
#>  $ year                  : int  2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
#>  $ world_rank_N          : int  1 2 2 4 5 6 7 8 9 10 ...

str(Shanghai1)
#> 'data.frame':    399 obs. of  12 variables:
#>  $ world_rank     : chr  "1" "2" "3" "4" ...
#>  $ university_name: chr  "Harvard University" "Stanford University" "Massachusetts Institute of Technology (MIT)" "University of California, Berkeley" ...
#>  $ national_rank  : chr  "1" "2" "3" "4" ...
#>  $ total_score    : num  100 72.8 71.8 71.6 69.8 64.1 62.1 60.1 57.2 56.1 ...
#>  $ alumni         : num  100 38 69 67.5 80.3 48.5 52.3 64.2 61.8 51.2 ...
#>  $ award          : num  100 79.7 83.2 80.9 97.2 68.8 91.3 68 85.3 56.6 ...
#>  $ hici           : num  100 88.9 68.2 69.7 54.6 57.4 62.2 57.4 52.2 48.9 ...
#>  $ ns             : num  100 71.6 69.2 68.5 55 64.8 44.4 51.2 40.6 52.1 ...
#>  $ pub            : num  100 69.6 61.6 68.1 65.9 46.2 44.5 67.8 49.2 68.9 ...
#>  $ pcp            : num  71.1 49.2 64.1 53.4 52.1 100 66.3 31 38.9 40.3 ...
#>  $ year           : int  2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
#>  $ world_rank_N   : int  1 2 3 4 5 6 7 8 9 10 ...

Y creamos unos df’s diferentes que usaremos después

cwur5 <- cwur %>% filter(world_rank <= 5)

times5 <- times1 %>%  filter(world_rank_N <= 5)

Shanghai5 <- Shanghai1 %>%  filter(world_rank_N <= 5)

3. Preguntas de investigación

Center for World University Rankings

Vamos a empezar a analizar las preguntas que nos hemos planteado y queremos resolver con la ayuda de los datos utilizados en este análisis de las 100 mejores universidades del mundo según el Center for World University Rankings.

Nos hemos preguntado qué país es el que tiene más instituciones en el ranking, y lo vamos a calcular para cada año por separado, y teniendo en cuenta ambos, el top 100 y el top 50 en cada caso. Además, incuiremos tablas dinámicas para mostrar los resultados de una manera más visual.

#Para 2012 top 100 y top 50
top_100_2012 <- cwur1 %>%
  select(country, institution, year, world_rank) %>%
  filter(year == 2012) %>%
  count(country) %>%
  arrange(desc(n))

DT::datatable(top_100_2012)
top_50_2012 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2012) %>% slice_max(world_rank, n = 50) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_50_2012)
#Para 2013 top 100 y top 50 top_100_2013 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2013) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_100_2013)
top_50_2013 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2013) %>% slice_max(world_rank, n = 50) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_50_2013)
#Para 2014 top 100 y top 50 top_100_2014 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2014) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_100_2014)
top_50_2014 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2014) %>% slice_max(world_rank, n = 50) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_50_2014)
#Para 2015 top 100 y top 50 top_100_2015 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2015) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_100_2015)
top_50_2015 <- cwur1 %>% select(country, institution, year, world_rank) %>% filter(year == 2015) %>% slice_max(world_rank, n = 50) %>% count(country) %>% arrange(desc(n)) DT::datatable(top_50_2015)

Y entonces, ¿cuáles son los 5 países que contienen más universidades en este ránking? Volvemos a analizarlo de una manera más visual, y observamos que, de nuevo, USA es el país con más universidades bien posicinadas en la clasificación según el Centre for World University Rankings durante los años 2012-2015, aunque se observa un ligero descenso a partir de 2014. En segundo lugar se sitúa siempre también Reino Unido, seguido de Jaón y otros países como Suiza o Alemania.

Si seguimos en la línea de los países mejor dotados de universidades incluidas en el ránking durante todo el período y lo visualizamos en un mapa, podemos volver a verlo de una manera más visual, aunque el resultado no cambia prácticamente. Obtenemos los mismos resultados, pero visualmente más atractivos.

Este análisis se puede extender a todos los países en el ranking teniendo en cuenta los datos del CWUR. Obviamente, EEUU sigue siendo el país con más universidades en el ránking, pero aparecen otros países interesantes, como Noruega o Israel, por ejemplo. No observamos ninguna universidad española entre las seleccionadas, sin embargo.

También podemos comparar este gráfico con las mejores países según el segundo dataset, Times, que analizaremos un poco más dentro de nada.

Siguiendo con nuestro análisis, en la siguiente tabla analizamos, en resumen, cuáles han sido las diez mejores universidades según este ránking a través de los años 2012-2015.

university name 2012 2013 2014 2015
Harvard University 1 1 1 1
Massachusetts Institute of Technology 2 4 3 3
Stanford University 3 2 2 2
University of Cambridge 4 5 4 4
California Institute of Technology 5 NA NA NA
Princeton University 6 8 9 9
University of Oxford 7 3 5 5
Yale University 8 10 10 NA
Columbia University 9 6 6 6
University of California, Berkeley 10 7 7 7
University of Chicago NA 9 8 8
Cornell University NA NA NA 10

Teniendo en cuenta ahora las cinco mejores universidades según este ránking, podemos hacer un análisis de una manera más visual, a través (de nuevo) de los años 2012-2015. Para eso utilizamos un mapa animado. Podemos observar cómo Harvard se ha mantenido en primera posición durante todo el período, y lo mismo ocurre con Stanford a partir de 2013, cuando pasa del tercero al segundo puesto y después mantiene su posición. El MIT, sin embargo, empieza situado en el segundo puesto y baja escalones hasta el cuarto, volviendo a subir al tercer lugar y menteniendo esta posición después. Además, Oxford aparece en 2013 para ocupar el tercer puesto y baja después para mantenerse en la quinta posición. Por su parte, Cambridge se situa entre el cuarto y quinto puesto todo de manera alterna, y el California Insitute of Technology aparece sólo en 2012 en quinta posición. Se puede observar todo esto de manera muy gráfica aquí:

Pero, ¿cómo son estas universidades? Vamos a ver imágenes que nos las enseñen y así poder hacer nosotros una comparación dependiendo de cómo de bonitas sean.

  • Tenemos en primer lugar a Harvard, la clara ganadora durante todos los años.

  • Pero no muy por detrás se encuentra Stanford, otra preciosa facultad rodeada de jardines.

  • Y como no, el MIT, con su increíble capitolio.

  • No podemos dejar de incluir, en este caso juntas, a las famosísimas universidades de Oxford y Cambridge, con sus espectaculares campus.

  • Por último, observemos la belleza del California Insitute of Technology.

Ahora, queremos tener en cuenta cuánto de buenas son estas universidades si consideramos diferentes variables, como la posición de cada una en el ránking a nivel nacional, el número de patentes, la calidad de la educación, el número de publicaciones, la posterior empleabilidad de sus alumnos o el número de citas. Para eso utilizamos “spider graphs”, que nos muestran de manera sencilla lo que queremos analizar. Tendremos en cuenta que cuanto más afuera se encuentra el extremo de la variable analizada, mejor situada en el ránking aparecerá esa universidad respecto a esta variable. Vamos a ver entonces cómo cambian estos gráficos dependiendo de el año en el que nos encontremos.

Resultados de 5 mejores universidades del mundo en diferentes categorías en 2015

Resultados de 5 mejores universidades del mundo en diferentes categorías en 2014

Resultados de 5 mejores universidades del mundo en diferentes categorías en 2013

Resultados de 5 mejores universidades del mundo en diferentes categorías en 2012

Para observar la relación entre la calidad de la educación y la posterior empleabilidad de los alumnos preparamos dos gráficos, donde podemos observar, que las universidades obtienen una clasificación más alta en términos de calidad de enseñanza que empleo de los alumnos


Times Higher Education World University Ranking

Cambiamos ahora de fuente y observamos los datos relativos a la institución Times Higher Education World University Ranking.

En la siguiente tabla analizamos, cuáles han sido las diez mejores universidades según Times ránking a través de los años 2012-2015. En este caso, no es Harvard la primera clasificada, sino el California Institue of Technology durante todo el período, seguido ahora sí de Harvard, Stanford, Oxford y Princeton, que aparece aquí por encima de Cambridge y el MIT. De esta manera, concluimos que los diferentes ránkings nos proporcionan clasificaciones diferentes.

university name 2012 2013 2014 2015
California Institute of Technology 1 1 1 1
Harvard University 2 4 2 2
Stanford University 2 2 4 4
University of Oxford 4 2 2 3
Princeton University 5 6 6 7
University of Cambridge 6 7 7 5
Massachusetts Institute of Technology 7 5 5 6
Imperial College London 8 8 10 9
University of Chicago 9 10 9 NA
University of California, Berkeley 10 9 8 8
Yale University NA NA NA 9

Para mostrar el cambio en puestos de ranking a lo largo del tiempo, ahora utilizamos un gráfico animado, tal y como hemos hecho antes con los datos de CWUR. Nuevamente, lo que más nos llama la atención es la bajada consideable de Harvard, que vuelve a ascender después.

Para analizar variables diferentes a las ya estudiadas con el otro dataset, vamos a observar ahora el número de estudiantes matriculados en las 20 mejores universidades a lo largo del tiempo, y lo visualizaremos mediante un gráfico también. En el gganimate podemos ver cómo cambia este número al largo de los diferentes años (de 2012 a 2016).

# Vamos a eliminar algunas variables que no me interesan del df original y a crear un dataframe con las 20 mejores universidades por cada año 

times_data_1 <- times_data %>% select(world_rank, university_name, country, total_score, num_students, international_students, year)

df_2011 <- times_data_1 %>% filter(year == 2011) %>% slice_max(total_score, n = 20)

df_2012 <- times_data_1 %>% filter(year == 2012) %>% slice_max(total_score, n = 20)

df_2013 <- times_data_1 %>% filter(year == 2013) %>% slice_max(total_score, n = 20)

df_2014 <- times_data_1 %>% filter(year == 2014) %>% slice_max(total_score, n = 20)

df_2015 <- times_data_1 %>% filter(year == 2015) %>% slice_max(total_score, n = 20)

df_2016 <- times_data_1 %>% filter(year == 2016) %>% slice_max(total_score, n = 20)

df_total <- rbind(df_2011, df_2012, df_2013, df_2014, df_2015, df_2016)

rm(df_2011, df_2012, df_2013, df_2014, df_2015, df_2016, times_data, times_data_1)

Creamos ahora el gráfico animado que muestra el número de alumnos matriculados

Dado que estas universidades suelen ser bastante internacionales, también hemos querido observar cuál es exactamente el porcentaje de alumnos internacionales en relación con el anterior observado número de estudiantes.


Academic Ranking of World Universities

También conocido como Shanghai Ranking, es uno de los más conocidos y prestigiosos del mundo. Vamos a analizar bien sus datos de manera visual. Como en este caso no tenemos datos sobre los países, vamos a visualizar en una tabla cuáles han sido las diez mejores universidades a través de los años 2012-2015. Nuevamente aparece Harvard a la cabeza, seguida de Standord y el MIT. Sin embargo, ahora se clasifica en cuarto lugar la UC Berkeley por delante de Cambridge.

university name 2012 2013 2014 2015
Harvard University 1 1 1 1
Stanford University 2 2 2 2
Massachusetts Institute of Technology (MIT) 3 4 3 3
University of California, Berkeley 4 3 NA 4
University of Cambridge 5 5 5 5
California Institute of Technology 6 6 7 7
Princeton University 7 7 6 6
Columbia University 8 8 8 8
University of Chicago 9 9 9 9
University of Oxford 10 10 9 10
University of California-Berkeley NA NA 4 NA

Teniendo en cuenta ahora las cinco mejores universidades según este ránking, podemos hacer un análisis de una manera más visual, a través (de nuevo) de los años 2012-2015. Para eso utilizamos un mapa animado, tal y como hemos hecho antes con los datos de CWUR y TIMES. En esta ocasión, los datos son distintos, y podemos ver cómo los puestos 1, 2 y 5 se mantienen estables, mientras que el MIT y UC Berkeley van intercambiando posiciones.

A continuación en los gráficos queremos mostrar los resultados de las 10 mejores universidades en 2015, en dos categorías: Profesores de una institución, ganadores de premios Nobel y medallas Fields y Alumnos de una institución, ganadores de premios Nobel y medallas Fields.


4. Conclusiones

Después de analizar nuestros datos mediante gráficos y tablas, hemos visto como diferentes rankings nos ofrecen información diversa. Principalmente extraemos como conclusión que Estados Unidos es el país con las mejores universidades de todo el mundo, sin importar el dataset en que nos basemos. También hemos podido observar como un buen posicionamiento en el ránking mundial tiene relación también con una elevada posición respecto al número de publicaciones o citas, así como la posición en el ránking a nivel nacional. Además, hemos observado como las mejores universidades suelen mantener su estatus,y en raras ocasiones vemos cambios significativos en los rankings. Y también podemos afirmar que cada ránking, dependiendo en los criterios utilizados para clasificar las universidades, nos ofrece un orden diferente, por eso es interesante tener en cuenta diferentes instituciones cuando queremos hacer un análisis global de la situación.


5. Trabajos en los que nos hemos basado

Para realizar este estudio, nos hemos basado en otros trabajos a parte de tener ideas propias. Entre ellos, encontramos trabajos que se realizaron en esta asignatura el año pasado, de donde hemos sacado información sobre cómo elaborar el Rmarkdown de una manera más elegante.


6. Bibliografía

Además, hemos utilizado como principales herramientas en la elaboración del trabajo:





7. Sesión informativa

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  Polish_Poland.1250          
 ctype    Polish_Poland.1250          
 tz       Europe/Warsaw               
 date     2021-12-16                  

- Packages -------------------------------------------------------------------
 package      * version    date       lib source                        
 assertthat     0.2.1      2019-03-21 [1] CRAN (R 4.1.1)                
 backports      1.2.1      2020-12-09 [1] CRAN (R 4.1.0)                
 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.2)                
 cellranger     1.1.0      2016-07-27 [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.2)                
 crosstalk      1.2.0      2021-11-04 [1] CRAN (R 4.1.2)                
 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.2)                
 details        0.2.1      2020-01-12 [1] CRAN (R 4.1.1)                
 digest         0.6.27     2020-10-24 [1] CRAN (R 4.1.1)                
 dplyr        * 1.0.7      2021-06-18 [1] CRAN (R 4.1.1)                
 DT             0.20       2021-11-15 [1] CRAN (R 4.1.2)                
 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)                
 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)                
 fmsb         * 0.7.1      2021-05-11 [1] CRAN (R 4.1.0)                
 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)                
 fs             1.5.0      2020-07-31 [1] CRAN (R 4.1.1)                
 generics       0.1.1      2021-10-25 [1] CRAN (R 4.1.2)                
 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)                
 ggridges     * 0.5.3      2021-01-08 [1] CRAN (R 4.1.1)                
 gifski         1.4.3-1    2021-05-02 [1] CRAN (R 4.1.1)                
 glue           1.4.2      2020-08-27 [1] CRAN (R 4.1.1)                
 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.1      2021-09-26 [1] CRAN (R 4.1.2)                
 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)                
 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)                
 kableExtra   * 1.3.4      2021-02-20 [1] CRAN (R 4.1.1)                
 klippy       * 0.0.0.9500 2021-11-18 [1] Github (rlesur/klippy@378c247)
 knitr        * 1.33       2021-04-24 [1] CRAN (R 4.1.1)                
 labeling       0.4.2      2020-10-20 [1] CRAN (R 4.1.0)                
 lifecycle      1.0.1      2021-09-24 [1] CRAN (R 4.1.2)                
 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)                
 maps         * 3.3.0      2018-04-03 [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)                
 openxlsx       4.2.4      2021-06-16 [1] CRAN (R 4.1.1)                
 pillar         1.6.4      2021-10-18 [1] CRAN (R 4.1.2)                
 pkgconfig      2.0.3      2019-09-22 [1] CRAN (R 4.1.1)                
 plyr           1.8.6      2020-03-03 [1] CRAN (R 4.1.1)                
 png            0.1-7      2013-12-03 [1] CRAN (R 4.1.0)                
 prettyunits    1.1.1      2020-01-24 [1] CRAN (R 4.1.1)                
 progress       1.2.2      2019-05-16 [1] CRAN (R 4.1.1)                
 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.0)                
 Rcpp           1.0.7      2021-07-07 [1] CRAN (R 4.1.1)                
 readr        * 2.0.1      2021-08-10 [1] CRAN (R 4.1.1)                
 readxl         1.3.1      2019-03-13 [1] CRAN (R 4.1.1)                
 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.11     2021-04-30 [1] CRAN (R 4.1.1)                
 rmarkdown      2.10       2021-08-06 [1] CRAN (R 4.1.1)                
 rprojroot      2.0.2      2020-11-15 [1] CRAN (R 4.1.1)                
 rstudioapi     0.13       2020-11-12 [1] CRAN (R 4.1.1)                
 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)                
 stringi        1.7.4      2021-08-25 [1] CRAN (R 4.1.1)                
 stringr      * 1.4.0      2019-02-10 [1] CRAN (R 4.1.1)                
 svglite        2.0.0      2021-02-20 [1] CRAN (R 4.1.1)                
 systemfonts    1.0.3      2021-10-13 [1] CRAN (R 4.1.1)                
 tibble       * 3.1.4      2021-08-25 [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)                
 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)                
 visdat         0.5.3      2019-02-15 [1] CRAN (R 4.1.1)                
 webshot        0.5.2      2019-11-22 [1] CRAN (R 4.1.1)                
 withr          2.4.3      2021-11-30 [1] CRAN (R 4.1.2)                
 wordcloud2   * 0.2.1      2018-01-03 [1] CRAN (R 4.1.1)                
 xfun           0.25       2021-08-06 [1] CRAN (R 4.1.1)                
 xml2           1.3.2      2020-04-23 [1] CRAN (R 4.1.1)                
 yaml           2.2.1      2020-02-01 [1] CRAN (R 4.1.0)                
 zip            2.2.0      2021-05-31 [1] CRAN (R 4.1.1)                

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




LS0tDQp0aXRsZTogIkFuw6FsaXNpcyBkZSBsYXMgbWVqb3JlcyAxMDAgdW5pdmVyc2lkYWRlcyBkZWwgbXVuZG8iDQphdXRob3I6ICJBbm5hIENoZXNhIExsb3JlbnMgKGFuY2hlbGxvQGFsdW1uaS51di5lcykgIFxuXG4gTG9yZW56byBDaGlyY2hpcmlsbG8gKGxvY2hpckBhbHVtbmkudXYuZXMpICBcbiBcbiBBbGljamEgTcWCeW5layAoYW1seUBhbHVtbmkudXYuZXMpIFxuXG4gVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIg0KZGF0ZTogIkRpY2llbWJyZSBkZSAyMDIxIChhY3R1YWxpemFkbyBlbCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLSVtLSVZJylgKSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICAjY3NzOiAiLi9hc3NldHMvbXlfY3NzX2ZpbGUuY3NzIg0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUgDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzIA0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBkZl9wcmludDoga2FibGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiA3Mg0KLS0tDQoNCmBgYHtyIHBhY2thZ2VzLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa2xpcHB5KSAgI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCmxpYnJhcnkod29yZGNsb3VkMikgDQpsaWJyYXJ5KG1hcHMpDQpsaWJyYXJ5KGZtc2IpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbGlicmFyeShnZ3JpZGdlcykNCmBgYA0KDQpgYGB7ciBjaHVuay1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgICNyZXN1bHRzID0gImhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgIGNhY2hlID0gRkFMU0UsIGNhY2hlLnBhdGggPSAiL2NhY2hlcy8iLCBjb21tZW50ID0gIiM+IiwNCiAgICAgICAgICAgICAgICAgICAgICAjZmlnLndpZHRoID0gNywgI2ZpZy5oZWlnaHQ9IDcsICAgDQogICAgICAgICAgICAgICAgICAgICAgI291dC53aWR0aCA9IDcsIG91dC5oZWlnaHQgPSA3LA0KICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gVFJVRSwgIGZpZy5zaG93ID0gImhvbGQiLA0KICAgICAgICAgICAgICAgICAgICAgIGZpZy5hc3AgPSAwLjYyOCwgb3V0LndpZHRoID0gIjc1JSIsIGZpZy5hbGlnbiA9ICJjZW50ZXIiKQ0KI2tuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpDQpgYGANCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0KI29wdGlvbnMoInlhbWwuZXZhbC5leHByIiA9IFRSVUUpIA0KYGBgDQoNCmBgYHtyIGtsaXBweSwgZXZhbCA9IEZBTFNFLCBlY2hvID0gRkFMU0V9DQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoInRvcCIsICJyaWdodCIpKSAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpDQpgYGANCg0KPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+DQoNClRyYWJham8gZWxhYm9yYWRvIHBhcmEgbGEgYXNpZ25hdHVyYSAiUHJvZ3JhbWFjacOzbiB5IG1hbmVqbyBkZSBkYXRvcyBlbg0KbGEgZXJhIGRlbCBCaWcgRGF0YSIgZGUgbGEgVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIGR1cmFudGUgZWwgY3Vyc28NCjIwMjEtMjAyMi4gRWwgcmVwbyBkZWwgdHJhYmFqbyBlc3TDoQ0KW2FxdcOtXShodHRwczovL2dpdGh1Yi5jb20vQWxpY2phTWwvdHJhYmFqb19CaWdEYXRhX2VxdWlwbyl7dGFyZ2V0PSJfYmxhbmsifS4NCg0KTGEgcMOhZ2luYSB3ZWIgZGUgbGEgYXNpZ25hdHVyYSB5IGxvcyB0cmFiYWpvcyBkZSBtaXMgY29tcGHDsWVyb3MgcHVlZGVuDQp2ZXJzZQ0KW2FxdcOtXShodHRwczovL3BlcmV6cDQ0LmdpdGh1Yi5pby9pbnRyby1kcy0yMS0yMi13ZWIvMDctdHJhYmFqb3MuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4NCg0KPGhyIGNsYXNzPSJsaW5lYS1yZWQiPg0KDQojIDEuIEludHJvZHVjY2nDs24NCg0KRWwgdMOtdHVsbyBkZWwgdHJhYmFqbyBlczogQW7DoWxpc2lzIGRlIGxhcyBtZWpvcmVzIDEwMCB1bml2ZXJzaWRhZGVzIGRlbCBtdW5kby4gIE51ZXN0cm8gb2JqZXRpdm8gZXMgaGFjZXIgdW4gZXN0dWRpbyBkZSBsYSBldm9sdWNpw7NuIHJlc3BlY3RvIGEgZGlmZXJlbnRlcyB2YXJpYWJsZXMgZGUgdHJlcyBkYXRhc2V0IHF1ZSBjb250aWVuZW4gZGlmZXJlbnRlcyByYW5raW5ncyBkZSBsYXMgbWVqb3JlcyAxMDAgdW5pdmVyc2lkYWRlcyBkZWwgbXVuZG8gZGVzZGUgZWwgYcOxbyAyMDEyIGhhc3RhIDIwMTUuDQpQbGFudGVhbW9zIHByZWd1bnRhcyBjb21vIHF1w6kgcGHDrXMgdGllbmUgbcOhcyB1bml2ZXJzaWRhZGVzIGVuIGVsIHJhbmtpbmcsIGN1w6FsIGVzIGVsIG7Dum1lcm8gZGUgZXN0dWRpYW50ZXMgZW4gbGFzIG1lam9yZXMgdW5pdmVyc2lkYWRlcywgbyBsYSByZWxhY2nDs24gZW50cmUgbGEgcG9zaWNpw7NuIGRlIHVuYSB1bml2ZXJzaWRhZCBlbiBlbCByw6Fua2luZyBjb24gc3UgcG9zaWNpw7NuIHJlc3BlY3RvIGFsIG5pdmVsIGRlIGVkdWNhY2nDs24gbyBlbCBuw7ptZXJvIGRlIHB1YmxpY2FjaW9uZXMuIA0KDQpBZGVtw6FzLCBxdWVyZW1vcyBtb3N0cmFyIGxhIGluZm9ybWFjacOzbiBkZSBtYW5lcmEgbcOhcyB2aXN1YWwgbWVkaWFudGUgZ3LDoWZpY29zIGRpbsOhbWljb3MgY29tcGFyYW5kbyBsYSBldm9sdWNpw7NuIGRlIGxhcyB1bml2ZXJzaWRhZGVzIGVuIGVsIHRvcCAxMCBkdXJhbnRlIGxvcyBhw7FvcywgbGEgcG9zaWNpw7NuIGRlIGxvcyBkaWZlcmVudGVzIHBhw61zZXMgZW4gZWwgcsOhbmtpbmcsIGFzw60gY29tbyBzdSBldm9sdWNpw7NuIGEgbG8gbGFyZ28gZGVsIHRpZW1wby4gDQoNClZhbW9zIGEgYmFzYXIsIGVudHJlIG90cm9zLCBlbiBlc3RhcyBmdWVudGVzOlwNCg0KMS4gIFkuIEJhbm8sIFMuIFZhc2FudGhhLiBJbmZsdWVuY2UgT2YgVW5pdmVyc2l0eSBSZXB1dGF0aW9uIE9uDQogICAgRW1wbG95YWJpbGl0eS4gMjAxOQ0KDQoyLiAgW0RhdG9zIHJlY2llbnRlcyBzb2JyZSBlbCByw6Fua2luZyBkZQ0KICAgIFNoYW5naGFpXShodHRwczovL3d3dy5zaGFuZ2hhaXJhbmtpbmcuY29tL3JhbmtpbmdzL2Fyd3UvMjAyMSkNCg0KMy4gIFtXaGF0IGltcGFjdCBkb2VzIHVuaXZlcnNpdHkgcmVwdXRhdGlvbiBoYXZlIG9uDQogICAgc3R1ZGVudHM/XShodHRwczovL3d3dy50aW1lc2hpZ2hlcmVkdWNhdGlvbi5jb20vc3R1ZGVudC9uZXdzL3doYXQtaW1wYWN0LWRvZXMtdW5pdmVyc2l0eS1yZXB1dGF0aW9uLWhhdmUtc3R1ZGVudHMpey51cml9DQoNCjQuICBbVW5pdmVyc2lkYWRlcyBsw61kZXJlcyBlbiBlbCBtdW5kby4gRWwgcG9zaWNpb25hbWllbnRvIGRlDQogICAgRXNwYcOxYV0oaHR0cHM6Ly93d3cuaXZpZS5lcy9lc19FUy9wdHByb3llY3RvL2Z1dHVyby1kZWwtbGlkZXJhemdvLWxhcy11bml2ZXJzaWRhZGVzLWxhcy1zb2NpZWRhZGVzLWF2YW56YWRhcy8pLg0KICAgIDIwMjANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgMi4gRGF0b3Mgey50YWJzZXR9DQoNCiMjIyA8Rk9OVCBDT0xPUj0iRkY0RDAwIj4qKkRhdG9zKio8L0ZPTlQ+DQoNCmBgYHtyfQ0KIyBDYXJnYW1vcyBsb3MgZGF0b3MgcHJldmlhbWVudGUgZGVzY2FyZ2Fkb3MgZGUgbGEgcMOhZ2luYSBLYWdnbGUNCmN3dXIgPC0gcmlvOjppbXBvcnQoIi4vZGF0b3MvY3d1ckRhdGEuY3N2IikNClNoYW5naGFpIDwtIHJpbzo6aW1wb3J0KCIuL2RhdG9zL3NoYW5naGFpRGF0YS5jc3YiKQ0KdGltZXNfZGF0YSA8LSByaW86OmltcG9ydCgiLi9kYXRvcy90aW1lc0RhdGEuY3N2IikNCmBgYA0KDQpIZW1vcyB1dGlsaXphZG8gbG9zIGRhdG9zIGRlIHZhcmlhcyBpbnN0aXR1Y2lvbmVzIHF1ZSBoYW4gaGVjaG8gdW4NCnJhbmtpbmcgZGUgbGFzIG1lam9yZXMgdW5pdmVyc2lkYWRlcyBpbnRyb2R1Y2llbmRvIHZhcmlhYmxlcyBkaWZlcmVudGVzLA0Kc2FjYWRvcyBkZQ0KW0thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9teWxlc29uZWlsbC93b3JsZC11bml2ZXJzaXR5LXJhbmtpbmdzKS4NCkVzYXMgaW5zdGl0dWNpb25lcyBzb246DQoNCjEuICBbQ2VudGVyIGZvciBXb3JsZCBVbml2ZXJzaXR5IFJhbmtpbmdzXShodHRwczovL2N3dXIub3JnLykNCiAgICAoYHIgbnJvdyhjd3VyKWAgZmlsYXMsIGByIGxlbmd0aChuYW1lcyhjd3VyKSlgIGNvbHVtbmFzKSwgcXVlIGRlc2RlDQogICAgc3UgZnVuZGFjacOzbiBlbiAyMDEyIHJlY29waWxhIGxvcyBkYXRvcyBkZSBsYXMgbWVqb3JlcyB1bml2ZXJzaWRhZGVzDQogICAgZGVzZGUgQXJhYmlhIFNhdWRpdGEuDQoNCjIuICBbVGltZXMgSGlnaGVyIEVkdWNhdGlvbiBXb3JsZCBVbml2ZXJzaXR5DQogICAgUmFua2luZ10oaHR0cHM6Ly93d3cudGltZXNoaWdoZXJlZHVjYXRpb24uY29tL2NvbnRlbnQvd29ybGQtdW5pdmVyc2l0eS1yYW5raW5ncykNCiAgICAoYHIgbnJvdyh0aW1lc19kYXRhKWAgcm93cywgYHIgbGVuZ3RoKG5hbWVzKHRpbWVzX2RhdGEpKWAgY29sdW1ucyksDQogICAgZnVuZGFkbyBlbiBSZWlubyBVbmlkbyBlbiAyMDEwLCBlcyB1bmEgZGUgbGFzIGNsYXNpZmljYWNpb25lcyBtw6FzDQogICAgaW5mbHV5ZW50ZXMgZGVsIG1vbWVudG8sIGF1bnF1ZSBhbGdvIGNyaXRpY2FkbyBwb3Igc3UgZXNwZWNpYWwNCiAgICBmaWphY2nDs24gZW4gbGFzIHVuaXZlcnNpZGFkZXMgaW5nbGVzYXMuDQoNCjMuICBbQWNhZGVtaWMgUmFua2luZyBvZiBXb3JsZA0KICAgIFVuaXZlcnNpdGllc10oaHR0cDovL3d3dy5zaGFuZ2hhaXJhbmtpbmcuY29tLykgKGByIG5yb3coU2hhbmdoYWkpYA0KICAgIGZpbGFzLCBgciBsZW5ndGgobmFtZXMoU2hhbmdoYWkpKWAgY29sdW1uYXMpLCBtw6FzIGNvbm9jaWRvIGNvbW8gZWwNCiAgICB0YW4gaW5mbHV5ZW50ZSBTaGFuZ2FpIFJhbmtpbmcsIHF1ZSBjb21lbnrDsyBhIHB1YmxpY2FyIHN1cyBsaXN0YWRvcw0KICAgIGVuIDIwMDMuDQoNClRvZGFzIGxhcyBtb2RpZmljYWNpb25lcyBxdWUgaGVtb3MgaGVjaG8gbGFzIHBvZMOpaXMgb2JzZXJ2YXIgZW4gbGENCnBlc3Rhw7FhICoqTGltcGllemEgZGUgZGF0b3MqKg0KDQojIyMgPEZPTlQgQ09MT1I9IkZGNEQwMCI+KipUaWR5Kio8L0ZPTlQ+DQoNCkVuIHJlYWxpZGFkIG51ZXN0cm9zIGRhdG9zIG5vIGhhbiB0ZW5pZG8gcXVlIHNlciBtdXkgbGltcGlhZG9zLCB5YSBxdWUNCmVuIGxhIHDDoWdpbmEgZGUgW0thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS8pIGFwYXJlY8OtYW4gYmFzdGFudGUNCmJpZW4uIFNpbiBlbWJhcmdvLCBhw7FhZGltb3MgYXF1w60gY3VhbHF1aWVyIG1vZGlmaWNhY2nDs24gcXVlIGhhbiBwb2RpZG8NCnN1ZnJpci4NCg0KQXF1w60gcG9kZW1vcyB2ZXIgdW4gcmVzdW1lbiBkZSBsYXMgdmFyaWFibGVzIHNlZ8O6biBzdSB0aXBvLCB5IHRlbmllbmRvDQplbiBjdWVudGEgdGFtYmnDqW4gbG9zIE5BJ3MNCg0KYGBge3J9DQp2aXNkYXQ6OnZpc19kYXQoY3d1cikgDQp2aXNkYXQ6OnZpc19kYXQodGltZXNfZGF0YSkNCnZpc2RhdDo6dmlzX2RhdChTaGFuZ2hhaSkNCmBgYA0KDQpTw60gdmFtb3MgYSBmaWx0cmFyIGxvcyBkYXRvcyBwYXJhIG9idGVuZXIgbG9zIG1pc21vcyByYW5nb3MgZGUgdGllbXBvIHkNCmVsIHJhbmtpbmcgZGUgbGFzIG1lam9yZXMgMTAwIHVuaXZlcnNpZGFkZXMgY2FkYSBhw7FvLCB5IHBvZGVyIGFzw60NCmhvbW9nZW5laXphciBudWVzdHJvIGFuw6FsaXNpcy4NCg0KYGBge3J9DQpjd3VyMSA8LSBjd3VyICU+JSANCiAgZmlsdGVyKHdvcmxkX3JhbmsgPD0gMTAwKQ0KDQp0aW1lczEgPC0gdGltZXNfZGF0YSAlPiUgDQogIGZpbHRlcih5ZWFyID49ICAyMDEyICwgeWVhciA8PSAyMDE1KSAlPiUgDQogIG11dGF0ZSh3b3JsZF9yYW5rX04gPSBhcy5pbnRlZ2VyKHdvcmxkX3JhbmspKSAlPiUgDQogIGZpbHRlcih3b3JsZF9yYW5rX04gPD0gMTAwKQ0KIA0KDQpTaGFuZ2hhaTEgPC0gU2hhbmdoYWkgJT4lDQogIGZpbHRlcih5ZWFyID49ICAyMDEyICwgeWVhciA8PSAyMDE1KSAlPiUgDQogIG11dGF0ZSh3b3JsZF9yYW5rX04gPSBhcy5pbnRlZ2VyKHdvcmxkX3JhbmspKSAlPiUgDQogIGZpbHRlcih3b3JsZF9yYW5rX04gPD0gMTAwKQ0KDQogIA0KYGBgDQoNCkFkZW3DoXMsIGhhY2Vtb3MgdW4gcmVwYXNvIGEgbG9zIHRpcG9zIGRlIGRhdG9zIGNvbiBsb3MgcXVlIHZhbW9zIGENCnRyYWJhamFyLg0KDQpgYGB7cn0NCg0Kc3RyKGN3dXIxKQ0KDQpzdHIodGltZXMxKQ0KDQpzdHIoU2hhbmdoYWkxKQ0KYGBgDQoNClkgY3JlYW1vcyB1bm9zIGRmJ3MgZGlmZXJlbnRlcyBxdWUgdXNhcmVtb3MgZGVzcHXDqXMNCg0KYGBge3J9DQpjd3VyNSA8LSBjd3VyICU+JSBmaWx0ZXIod29ybGRfcmFuayA8PSA1KQ0KDQp0aW1lczUgPC0gdGltZXMxICU+JSAgZmlsdGVyKHdvcmxkX3JhbmtfTiA8PSA1KQ0KDQpTaGFuZ2hhaTUgPC0gU2hhbmdoYWkxICU+JSAgZmlsdGVyKHdvcmxkX3JhbmtfTiA8PSA1KQ0KDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgMy4gUHJlZ3VudGFzIGRlIGludmVzdGlnYWNpw7NuDQoNCiMjIyAqQ2VudGVyIGZvciBXb3JsZCBVbml2ZXJzaXR5IFJhbmtpbmdzKg0KDQpWYW1vcyBhIGVtcGV6YXIgYSBhbmFsaXphciBsYXMgcHJlZ3VudGFzIHF1ZSBub3MgaGVtb3MgcGxhbnRlYWRvIHkNCnF1ZXJlbW9zIHJlc29sdmVyIGNvbiBsYSBheXVkYSBkZSBsb3MgZGF0b3MgdXRpbGl6YWRvcyBlbiBlc3RlIGFuw6FsaXNpcw0KZGUgbGFzIDEwMCBtZWpvcmVzIHVuaXZlcnNpZGFkZXMgZGVsIG11bmRvIHNlZ8O6biBlbCBbQ2VudGVyIGZvciBXb3JsZA0KVW5pdmVyc2l0eSBSYW5raW5ncy5dKGh0dHBzOi8vY3d1ci5vcmcvKQ0KDQpOb3MgaGVtb3MgcHJlZ3VudGFkbyAqKnF1w6kgcGHDrXMgZXMgZWwgcXVlIHRpZW5lIG3DoXMgaW5zdGl0dWNpb25lcyBlbiBlbA0KcmFua2luZyoqLCB5IGxvIHZhbW9zIGEgY2FsY3VsYXIgcGFyYSBjYWRhIGHDsW8gcG9yIHNlcGFyYWRvLCB5IHRlbmllbmRvDQplbiBjdWVudGEgYW1ib3MsIGVsIHRvcCAxMDAgeSBlbCB0b3AgNTAgZW4gY2FkYSBjYXNvLiBBZGVtw6FzLCBpbmN1aXJlbW9zDQp0YWJsYXMgZGluw6FtaWNhcyBwYXJhIG1vc3RyYXIgbG9zIHJlc3VsdGFkb3MgZGUgdW5hIG1hbmVyYSBtw6FzIHZpc3VhbC4NCg0KYGBge3IsICBldmFsID0gVFJVRX0NCiNQYXJhIDIwMTIgdG9wIDEwMCB5IHRvcCA1MA0KdG9wXzEwMF8yMDEyIDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDEyKSAlPiUNCiAgY291bnQoY291bnRyeSkgJT4lDQogIGFycmFuZ2UoZGVzYyhuKSkNCg0KRFQ6OmRhdGF0YWJsZSh0b3BfMTAwXzIwMTIpDQoNCnRvcF81MF8yMDEyIDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDEyKSAlPiUNCiAgc2xpY2VfbWF4KHdvcmxkX3JhbmssIG4gPSA1MCkgJT4lDQogIGNvdW50KGNvdW50cnkpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpDQoNCkRUOjpkYXRhdGFibGUodG9wXzUwXzIwMTIpDQoNCiNQYXJhIDIwMTMgdG9wIDEwMCB5IHRvcCA1MA0KdG9wXzEwMF8yMDEzIDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDEzKSAlPiUNCiAgY291bnQoY291bnRyeSkgJT4lDQogIGFycmFuZ2UoZGVzYyhuKSkNCg0KRFQ6OmRhdGF0YWJsZSh0b3BfMTAwXzIwMTMpDQoNCnRvcF81MF8yMDEzIDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDEzKSAlPiUNCiAgc2xpY2VfbWF4KHdvcmxkX3JhbmssIG4gPSA1MCkgJT4lDQogIGNvdW50KGNvdW50cnkpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpDQoNCkRUOjpkYXRhdGFibGUodG9wXzUwXzIwMTMpDQoNCiNQYXJhIDIwMTQgdG9wIDEwMCB5IHRvcCA1MA0KdG9wXzEwMF8yMDE0IDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDE0KSAlPiUNCiAgY291bnQoY291bnRyeSkgJT4lDQogIGFycmFuZ2UoZGVzYyhuKSkNCg0KRFQ6OmRhdGF0YWJsZSh0b3BfMTAwXzIwMTQpDQoNCnRvcF81MF8yMDE0IDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDE0KSAlPiUNCiAgc2xpY2VfbWF4KHdvcmxkX3JhbmssIG4gPSA1MCkgJT4lDQogIGNvdW50KGNvdW50cnkpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpDQoNCkRUOjpkYXRhdGFibGUodG9wXzUwXzIwMTQpDQoNCiNQYXJhIDIwMTUgdG9wIDEwMCB5IHRvcCA1MA0KdG9wXzEwMF8yMDE1IDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDE1KSAlPiUNCiAgY291bnQoY291bnRyeSkgJT4lDQogIGFycmFuZ2UoZGVzYyhuKSkNCg0KRFQ6OmRhdGF0YWJsZSh0b3BfMTAwXzIwMTUpDQoNCnRvcF81MF8yMDE1IDwtIGN3dXIxICU+JQ0KICBzZWxlY3QoY291bnRyeSwgaW5zdGl0dXRpb24sIHllYXIsIHdvcmxkX3JhbmspICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDE1KSAlPiUNCiAgc2xpY2VfbWF4KHdvcmxkX3JhbmssIG4gPSA1MCkgJT4lDQogIGNvdW50KGNvdW50cnkpICU+JQ0KICBhcnJhbmdlKGRlc2MobikpDQoNCkRUOjpkYXRhdGFibGUodG9wXzUwXzIwMTUpDQoNCmBgYA0KDQpZIGVudG9uY2VzLCAqwr9jdcOhbGVzIHNvbiBsb3MgNSBwYcOtc2VzIHF1ZSBjb250aWVuZW4gbcOhcyB1bml2ZXJzaWRhZGVzIGVuDQplc3RlIHLDoW5raW5nPyogVm9sdmVtb3MgYSBhbmFsaXphcmxvIGRlIHVuYSBtYW5lcmEgbcOhcyB2aXN1YWwsIHkNCm9ic2VydmFtb3MgcXVlLCBkZSBudWV2bywgKipVU0EqKiBlcyBlbCBwYcOtcyBjb24gbcOhcyB1bml2ZXJzaWRhZGVzIGJpZW4NCnBvc2ljaW5hZGFzIGVuIGxhIGNsYXNpZmljYWNpw7NuIHNlZ8O6biBlbCBDZW50cmUgZm9yIFdvcmxkIFVuaXZlcnNpdHkNClJhbmtpbmdzIGR1cmFudGUgbG9zIGHDsW9zIDIwMTItMjAxNSwgYXVucXVlIHNlIG9ic2VydmEgdW4gbGlnZXJvDQpkZXNjZW5zbyBhIHBhcnRpciBkZSAyMDE0LiBFbiBzZWd1bmRvIGx1Z2FyIHNlIHNpdMO6YSBzaWVtcHJlIHRhbWJpw6luDQpSZWlubyBVbmlkbywgc2VndWlkbyBkZSBKYcOzbiB5IG90cm9zIHBhw61zZXMgY29tbyBTdWl6YSBvIEFsZW1hbmlhLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NCkN3dXJDb3VudHJpZXMgPC0gY3d1cjEgJT4lIGdyb3VwX2J5KHllYXIsIGNvdW50cnkpICU+JSBzdW1tYXJpc2UoTk4gPQ0KbigpKSAlPiUgdW5ncm91cCgpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgYXJyYW5nZShkZXNjKE5OKSkgJT4lDQpzbGljZV9tYXgoTk4sIG4gPSA1KQ0KDQpnZ3Bsb3QoQ3d1ckNvdW50cmllcywgYWVzKGNvdW50cnksIE5OKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwNCmZpbGw9IiNmNjgwNjAiLCBhbHBoYSA9IC42LCB3aWR0aCA9IC40KSArIGNvb3JkX2ZsaXAoKSArDQpmYWNldF93cmFwKHZhcnMoeWVhcikpICsgIHRoZW1lX21pbmltYWwoKSArIGxhYnModGl0bGUgPSAiTGFzIG1lam9yZXMgNSBwYcOtc2VzIHNlZ8O6biBDV1VSIiwgeSA9DQoicmFuayIpDQpgYGANCg0KU2kgc2VndWltb3MgZW4gbGEgbMOtbmVhIGRlIGxvcyAqKnBhw61zZXMgbWVqb3IgZG90YWRvcyBkZSB1bml2ZXJzaWRhZGVzDQppbmNsdWlkYXMgZW4gZWwgcsOhbmtpbmcqKiBkdXJhbnRlIHRvZG8gZWwgcGVyw61vZG8geSBsbyB2aXN1YWxpemFtb3MgZW4NCnVuIG1hcGEsIHBvZGVtb3Mgdm9sdmVyIGEgdmVybG8gZGUgdW5hIG1hbmVyYSBtw6FzIHZpc3VhbCwgYXVucXVlIGVsDQpyZXN1bHRhZG8gbm8gY2FtYmlhIHByw6FjdGljYW1lbnRlLiBPYnRlbmVtb3MgbG9zIG1pc21vcyByZXN1bHRhZG9zLCBwZXJvDQp2aXN1YWxtZW50ZSBtw6FzIGF0cmFjdGl2b3MuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0KDQpDd3VyQ291bnRyaWVzMTAgPC0gY3d1cjEgJT4lIA0KICByZW5hbWUocmVnaW9uID0gY291bnRyeSkgJT4lIA0KICBncm91cF9ieSh5ZWFyLCByZWdpb24pICU+JSANCiAgc3VtbWFyaXNlKE5OID0gbigpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIGdyb3VwX2J5KHllYXIpICU+JSANCiAgYXJyYW5nZShkZXNjKE5OKSkgJT4lIA0KICBzbGljZV9tYXgoTk4sIG4gPSAxMCkgJT4lDQogIHVuZ3JvdXAgJT4lIA0KICBzZWxlY3QoeWVhciwgcmVnaW9uKQ0KDQoNCldvcmxkIDwtIG1hcF9kYXRhKCJ3b3JsZCIpICAgDQoNCk1hcDEgPC0gbGVmdF9qb2luKEN3dXJDb3VudHJpZXMxMCwgV29ybGQsIGJ5ID0gInJlZ2lvbiIpIA0KDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBXb3JsZCwgYWVzICh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGwgPSAiI2YyZjJmMiIsIGNvbG9yID0gIndoaXRlIikgKw0KICBnZW9tX3BvbHlnb24oZGF0YSA9IE1hcDEsIGFlcyAoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCAgZmlsbCA9ICIjNjliM2EyIiwgY29sb3IgPSAid2hpdGUiKSArDQogIGZhY2V0X3dyYXAodmFycyh5ZWFyKSkgKyAgDQogIHRoZW1lX3ZvaWQoKSArDQogIGxhYnModGl0bGUgPSAiICAgICAgICAgICAgICAgICAgICAgICAgIExhcyBtZWpvcmVzIDEwIHBhw61zZXMgc2Vnw7puIENXVVIgZW4gMjAxMiAtIDIwMTUiKQ0KYGBgDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0KDQpEX3dvcmRzIDwtIGN3dXIxICU+JSBzZWxlY3QoY291bnRyeSkgJT4lIGdyb3VwX2J5KGNvdW50cnkpICU+JQ0Kc3VtbWFyaXNlKEZyZXEgPSBuKCkpICU+JSBhcnJhbmdlKGRlc2MoRnJlcSkpDQoNCndvcmRjbG91ZDIoZGF0YSA9IERfd29yZHMsIHNpemUgPSAxLjApDQoNCmBgYA0KDQpFc3RlIGFuw6FsaXNpcyBzZSBwdWVkZSBleHRlbmRlciBhICoqdG9kb3MgbG9zIHBhw61zZXMgZW4gZWwgcmFua2luZyoqIHRlbmllbmRvIGVuIGN1ZW50YSBsb3MgZGF0b3MgZGVsIENXVVIuDQpPYnZpYW1lbnRlLCBFRVVVIHNpZ3VlIHNpZW5kbyBlbCBwYcOtcyBjb24gbcOhcyB1bml2ZXJzaWRhZGVzIGVuIGVsDQpyw6Fua2luZywgcGVybyBhcGFyZWNlbiBvdHJvcyBwYcOtc2VzIGludGVyZXNhbnRlcywgY29tbyBOb3J1ZWdhIG8gSXNyYWVsLA0KcG9yIGVqZW1wbG8uIE5vIG9ic2VydmFtb3MgbmluZ3VuYSB1bml2ZXJzaWRhZCBlc3Bhw7FvbGEgZW50cmUgbGFzDQpzZWxlY2Npb25hZGFzLCBzaW4gZW1iYXJnby4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUV9DQpiZXN0X2NvdW50X2N3dXIgPC0gDQogIGN3dXIxICU+JSANCiAgc2VsZWN0KHllYXIsIGluc3RpdHV0aW9uLCBjb3VudHJ5LCB3b3JsZF9yYW5rKSAlPiUNCiAgZ3JvdXBfYnkoY291bnRyeSkgJT4lIA0KICBzdW1tYXJpc2UoTk4gPSBuKCkpICU+JSANCiAgYXJyYW5nZShkZXNjKE5OKSkgJT4lIA0KICB1bmdyb3VwIA0KDQoNCmJjIDwtIGdncGxvdChiZXN0X2NvdW50X2N3dXIsIGFlcyh4PSIiLCB5PU5OLCBmaWxsPWNvdW50cnkpKSsNCiAgZ2VvbV9iYXIod2lkdGggPSAxLCBzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gIkJlc3QgY291bnRyaWVzIGJ5IENXVVIgaW4gMjAxMiAtIDIwMTUiLA0KICAgICAgIHggPSAiICIsDQogICAgICAgeSA9ICIgIikNCg0KcGllIDwtIGJjICsgY29vcmRfcG9sYXIoInkiLCBzdGFydD0wKQ0KcGllICsgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KVGFtYmnDqW4gcG9kZW1vcyBjb21wYXJhciBlc3RlIGdyw6FmaWNvIGNvbiBsYXMgbWVqb3JlcyBwYcOtc2VzIHNlZ8O6biBlbA0Kc2VndW5kbyBkYXRhc2V0LCBUaW1lcywgcXVlIGFuYWxpemFyZW1vcyB1biBwb2NvIG3DoXMgZGVudHJvIGRlIG5hZGEuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0KYmVzdF9jb3VudF90aW1lcyA8LSANCiAgdGltZXMxICU+JSANCiAgc2VsZWN0KHllYXIsIHVuaXZlcnNpdHlfbmFtZSwgY291bnRyeSwgd29ybGRfcmFuaykgJT4lDQogIGdyb3VwX2J5KGNvdW50cnkpICU+JSANCiAgc3VtbWFyaXNlKE5OID0gbigpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhOTikpICU+JSANCiAgdW5ncm91cCANCg0KdGMgPC0gZ2dwbG90KGJlc3RfY291bnRfdGltZXMsIGFlcyh4PSIiLCB5PU5OLCBmaWxsPWNvdW50cnkpKSsNCiAgZ2VvbV9iYXIod2lkdGggPSAxLCBzdGF0ID0gImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gIkJlc3QgY291bnRyaWVzIGJ5IFRJTUVTIGluIDIwMTIgLSAyMDE1IiwNCiAgICAgICB4ID0gIiAiLA0KICAgICAgIHkgPSAiICIpDQoNCnBpZSA8LSB0YyArIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQ9MCkNCnBpZSArIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KU2lndWllbmRvIGNvbiBudWVzdHJvIGFuw6FsaXNpcywgZW4gbGEgc2lndWllbnRlIHRhYmxhIGFuYWxpemFtb3MsIGVuDQpyZXN1bWVuLCAqKmN1w6FsZXMgaGFuIHNpZG8gbGFzIGRpZXogbWVqb3JlcyB1bml2ZXJzaWRhZGVzKiogc2Vnw7puIGVzdGUNCnLDoW5raW5nIGEgdHJhdsOpcyBkZSBsb3MgYcOxb3MgMjAxMi0yMDE1Lg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NCg0KY3d1cjEwIDwtIGN3dXIxICU+JSANCiAgc2VsZWN0KHllYXIsIHdvcmxkX3JhbmssIGluc3RpdHV0aW9uKSAlPiUgDQogIGZpbHRlcih3b3JsZF9yYW5rIDw9IDEwKSAlPiUgDQogIHJlbmFtZSh3b3JsZF9yYW5rX2N3dXIgPSB3b3JsZF9yYW5rLCAidW5pdmVyc2l0eSBuYW1lIiA9IGluc3RpdHV0aW9uKQ0KDQpjd3VyMTBfd2lkZSA8LSBwaXZvdF93aWRlcihjd3VyMTAsIG5hbWVzX2Zyb20gPSB5ZWFyLCB2YWx1ZXNfZnJvbSA9IHdvcmxkX3JhbmtfY3d1cikNCg0Ka2JsKGN3dXIxMF93aWRlKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IGxpc3QoZW5hYmxlZCA9IFQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kID0gImxpZ2h0Ymx1ZSIpKSAlPiUgDQogIGthYmxlX3BhcGVyKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikNCg0KYGBgDQoNClRlbmllbmRvIGVuIGN1ZW50YSBhaG9yYSBsYXMgKipjaW5jbyBtZWpvcmVzIHVuaXZlcnNpZGFkZXMqKiBzZWfDum4gZXN0ZQ0KcsOhbmtpbmcsIHBvZGVtb3MgaGFjZXIgdW4gYW7DoWxpc2lzIGRlIHVuYSBtYW5lcmEgbcOhcyB2aXN1YWwsIGEgdHJhdsOpcw0KKGRlIG51ZXZvKSBkZSBsb3MgYcOxb3MgMjAxMi0yMDE1LiBQYXJhIGVzbyB1dGlsaXphbW9zIHVuIG1hcGEgYW5pbWFkby4NClBvZGVtb3Mgb2JzZXJ2YXIgY8OzbW8gSGFydmFyZCBzZSBoYSBtYW50ZW5pZG8gZW4gcHJpbWVyYSBwb3NpY2nDs24NCmR1cmFudGUgdG9kbyBlbCBwZXLDrW9kbywgeSBsbyBtaXNtbyBvY3VycmUgY29uIFN0YW5mb3JkIGEgcGFydGlyIGRlDQoyMDEzLCBjdWFuZG8gcGFzYSBkZWwgdGVyY2VybyBhbCBzZWd1bmRvIHB1ZXN0byB5IGRlc3B1w6lzIG1hbnRpZW5lIHN1DQpwb3NpY2nDs24uIEVsIE1JVCwgc2luIGVtYmFyZ28sIGVtcGllemEgc2l0dWFkbyBlbiBlbCBzZWd1bmRvIHB1ZXN0byB5DQpiYWphIGVzY2Fsb25lcyBoYXN0YSBlbCBjdWFydG8sIHZvbHZpZW5kbyBhIHN1YmlyIGFsIHRlcmNlciBsdWdhciB5DQptZW50ZW5pZW5kbyBlc3RhIHBvc2ljacOzbiBkZXNwdcOpcy4gQWRlbcOhcywgT3hmb3JkIGFwYXJlY2UgZW4gMjAxMyBwYXJhDQpvY3VwYXIgZWwgdGVyY2VyIHB1ZXN0byB5IGJhamEgZGVzcHXDqXMgcGFyYSBtYW50ZW5lcnNlIGVuIGxhIHF1aW50YQ0KcG9zaWNpw7NuLiBQb3Igc3UgcGFydGUsIENhbWJyaWRnZSBzZSBzaXR1YSBlbnRyZSBlbCBjdWFydG8geSBxdWludG8NCnB1ZXN0byB0b2RvIGRlIG1hbmVyYSBhbHRlcm5hLCB5IGVsIENhbGlmb3JuaWEgSW5zaXR1dGUgb2YgVGVjaG5vbG9neQ0KYXBhcmVjZSBzw7NsbyBlbiAyMDEyIGVuIHF1aW50YSBwb3NpY2nDs24uIFNlIHB1ZWRlIG9ic2VydmFyIHRvZG8gZXN0byBkZQ0KbWFuZXJhIG11eSBncsOhZmljYSBhcXXDrToNCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUV9DQpnZ3Bsb3QoY3d1cjUsIGFlcyh5ZWFyLCB3b3JsZF9yYW5rLCBjb2xvciA9IGluc3RpdHV0aW9uLCBzaGFwZSA9IGluc3RpdHV0aW9uKSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplID0gNCkpKw0KICBzY2FsZV9jb2xvcl9icmV3ZXIodHlwZT0icXVhbCIsIHBhbGV0dGUgPSAzKSArDQogIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArDQogIGVhc2VfYWVzKCdsaW5lYXInKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQmVzdCA1IFVuaXZlcnNpdGllcyBieSBDV1VSIiwNCiAgICAgICB5ID0gInJhbmsiKQ0KDQpgYGANCg0KUGVybywgwr9jw7NtbyBzb24gZXN0YXMgdW5pdmVyc2lkYWRlcz8gVmFtb3MgYSB2ZXIgaW3DoWdlbmVzIHF1ZSBub3MgbGFzDQplbnNlw7FlbiB5IGFzw60gcG9kZXIgaGFjZXIgbm9zb3Ryb3MgdW5hIGNvbXBhcmFjacOzbiBkZXBlbmRpZW5kbyBkZSBjw7Ntbw0KZGUgYm9uaXRhcyBzZWFuLg0KDQotICAgVGVuZW1vcyBlbiBwcmltZXIgbHVnYXIgYSBIYXJ2YXJkLCBsYSBjbGFyYSBnYW5hZG9yYSBkdXJhbnRlIHRvZG9zDQogICAgbG9zIGHDsW9zLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ltYWdlbmVzL2hhcnZhcmQuanBlZyIpDQpgYGANCg0KLSAgIFBlcm8gbm8gbXV5IHBvciBkZXRyw6FzIHNlIGVuY3VlbnRyYSBTdGFuZm9yZCwgb3RyYSBwcmVjaW9zYSBmYWN1bHRhZA0KICAgIHJvZGVhZGEgZGUgamFyZGluZXMuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4vaW1hZ2VuZXMvc3RhbmZvcmQuanBlZyIpDQpgYGANCg0KLSAgIFkgY29tbyBubywgZWwgTUlULCBjb24gc3UgaW5jcmXDrWJsZSBjYXBpdG9saW8uDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4vaW1hZ2VuZXMvTUlULmpwZWciKQ0KYGBgDQoNCi0gICBObyBwb2RlbW9zIGRlamFyIGRlIGluY2x1aXIsIGVuIGVzdGUgY2FzbyBqdW50YXMsIGEgbGFzIGZhbW9zw61zaW1hcw0KICAgIHVuaXZlcnNpZGFkZXMgZGUgT3hmb3JkIHkgQ2FtYnJpZGdlLCBjb24gc3VzIGVzcGVjdGFjdWxhcmVzIGNhbXB1cy4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUV9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9pbWFnZW5lcy9veGZvcmQuanBlZyIpDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi9pbWFnZW5lcy9jYW1icmlkZ2UuanBlZyIpDQpgYGANCg0KLSAgIFBvciDDumx0aW1vLCBvYnNlcnZlbW9zIGxhIGJlbGxlemEgZGVsIENhbGlmb3JuaWEgSW5zaXR1dGUgb2YNCiAgICBUZWNobm9sb2d5Lg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuL2ltYWdlbmVzL2NhbGlmb3JuaWEuanBlZyIpDQpgYGANCg0KQWhvcmEsIHF1ZXJlbW9zIHRlbmVyIGVuIGN1ZW50YSBjdcOhbnRvIGRlIGJ1ZW5hcyBzb24gZXN0YXMgdW5pdmVyc2lkYWRlcw0Kc2kgY29uc2lkZXJhbW9zIGRpZmVyZW50ZXMgdmFyaWFibGVzLCBjb21vIGxhIHBvc2ljacOzbiBkZSBjYWRhIHVuYSBlbiBlbA0KcsOhbmtpbmcgYSBuaXZlbCBuYWNpb25hbCwgZWwgbsO6bWVybyBkZSBwYXRlbnRlcywgbGEgY2FsaWRhZCBkZSBsYQ0KZWR1Y2FjacOzbiwgZWwgbsO6bWVybyBkZSBwdWJsaWNhY2lvbmVzLCBsYSBwb3N0ZXJpb3IgZW1wbGVhYmlsaWRhZCBkZSBzdXMNCmFsdW1ub3MgbyBlbCBuw7ptZXJvIGRlIGNpdGFzLiBQYXJhIGVzbyB1dGlsaXphbW9zICJzcGlkZXIgZ3JhcGhzIiwgcXVlDQpub3MgbXVlc3RyYW4gZGUgbWFuZXJhIHNlbmNpbGxhIGxvIHF1ZSBxdWVyZW1vcyBhbmFsaXphci4gVGVuZHJlbW9zIGVuDQpjdWVudGEgcXVlIGN1YW50byBtw6FzIGFmdWVyYSBzZSBlbmN1ZW50cmEgZWwgZXh0cmVtbyBkZSBsYSB2YXJpYWJsZQ0KYW5hbGl6YWRhLCBtZWpvciBzaXR1YWRhIGVuIGVsIHLDoW5raW5nIGFwYXJlY2Vyw6EgZXNhIHVuaXZlcnNpZGFkDQpyZXNwZWN0byBhIGVzdGEgdmFyaWFibGUuIFZhbW9zIGEgdmVyIGVudG9uY2VzIGPDs21vIGNhbWJpYW4gZXN0b3MNCmdyw6FmaWNvcyBkZXBlbmRpZW5kbyBkZSBlbCBhw7FvIGVuIGVsIHF1ZSBub3MgZW5jb250cmVtb3MuDQoNCjxGT05UIENPTE9SPSJTa3libHVlIj5SZXN1bHRhZG9zIGRlIDUgbWVqb3JlcyB1bml2ZXJzaWRhZGVzIGRlbCBtdW5kbyBlbg0KZGlmZXJlbnRlcyBjYXRlZ29yw61hcyBlbiAyMDE1PC9GT05UIENPTE9SPg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NCiNzcGlkZXJ3ZWIgZm9yIDIwMTUNCg0Kc3BpZGVyY3d1cjE1IDwtIGN3dXI1ICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNSkgJT4lIA0KICBzZWxlY3Qod29ybGRfcmFuaywgbmF0aW9uYWxfcmFuaywgY2l0YXRpb25zLCBhbHVtbmlfZW1wbG95bWVudCwgcHVibGljYXRpb25zLCBwYXRlbnRzLCBxdWFsaXR5X29mX2VkdWNhdGlvbikNCiAgDQpzcGlkZXJjd3VyMTUgPC0gYXMuZGF0YS5mcmFtZShzcGlkZXJjd3VyMTUpDQoNCiMgVG8gdXNlIHRoZSBmbXNiIHBhY2thZ2UsIEkgaGF2ZSB0byBhZGQgMiBsaW5lcyB0byB0aGUgZGF0YWZyYW1lOiB0aGUgbWF4IGFuZCBtaW4gb2YgZWFjaCANCg0KbWF4X21pbiA8LSBkYXRhLmZyYW1lKA0KICB3b3JsZF9yYW5rID0gYygwLCA1MCksIG5hdGlvbmFsX3JhbmsgPSBjKDAsIDUwKSwgIGNpdGF0aW9ucyA9IGMoMCwgNTApLA0KICBhbHVtbmlfZW1wbG95bWVudCA9IGMoMCwgNTApLCBwdWJsaWNhdGlvbnMgPSBjKDAsIDUwKSwNCiAgcGF0ZW50cyA9IGMoMCwgNTApLCBlZHVjYXRpb25fcXVhbGl0eSA9IGMoMCwgNTApKQ0Kcm93bmFtZXMobWF4X21pbikgPC0gYygiTWF4IiwgIk1pbiIpDQoNCiMgQmluZCB0aGUgdmFyaWFibGUgcmFuZ2VzIHRvIHRoZSBkYXRhDQpzcGlkZXJjd3VyMTUgPC0gcmJpbmQocmVwKDEsIDcpLCByZXAoNTAsIDcpLCBzcGlkZXJjd3VyMTUpDQoNCnJvd25hbWVzKHNwaWRlcmN3dXIxNSkgPC0gYygibWF4IiwgIm1pbiIsICJIYXJ2YXJkIFVuaXZlcnNpdHkiLCAiU3RhbmZvcmQgVW5pdmVyc2l0eSIsICJNYXNzYWNodXNldHRzIEluc3RpdHV0ZSBvZiBUZWNobm9sb2d5IiwgIlVuaXZlcnNpdHkgb2YgQ2FtYnJpZGdlIiwgIlVuaXZlcnNpdHkgb2YgT3hmb3JkIikNCg0KY29sbmFtZXMoc3BpZGVyY3d1cjE1KSA8LSBjKCJ3b3JsZCByYW5rIiwgIm5hdGlvbmFsIHJhbmsiICwgImNpdGF0aW9ucyIsICJhbHVtbmkgZW1wbG95bWVudCIgLCAicHVibGljYXRpb25zIiwgInBhdGVudHMiLCAiZWR1Y2F0aW9uIHF1YWxpdHkiKQ0KDQoNCg0KY291bCA8LSBicmV3ZXIucGFsKDMsICJQYWlyZWQiKQ0KY29sb3JzX2JvcmRlciA8LSBjb3VsDQpjb2xvcnNfaW4gPC0gYWxwaGEoY291bCwwLjMpDQoNCm9wIDwtIHBhcihtYXIgPSBjKDIsIDAuMiwgMiwgMCkpDQpwYXIobWZyb3cgPSBjKDIsMykpDQoNCg0KZm9yKGkgaW4gMzpucm93KHNwaWRlcmN3dXIxNSkpew0KICAgIHJhZGFyY2hhcnQoc3BpZGVyY3d1cjE1W2MoMToyLGkpLCBdLA0KICAgICAgICAgICAgICAgY2dsdHkgPSAxLCAgICAgIA0KICAgICAgICAgICAgICAgY2dsY29sID0gImdyYXkiLA0KICAgICAgICAgICAgICAgY2dsd2Q9MC44LA0KICAgICAgICAgICAgICAgcGNvbD1jb2xvcnNfYm9yZGVyLCANCiAgICAgICAgICAgICAgIHBmY29sPWNvbG9yc19pbiwgIA0KICAgICAgICAgICAgICAgcGx3ZCA9IDIsICAgICAgICANCiAgICAgICAgICAgICAgIHBsdHkgPSAxLCAgICAgDQogICAgICAgICAgICAgICBjYXhpc2xhYmVscz1zZXEoMCwgNTAsIDEwKSwgDQogICAgICAgICAgICAgICB2bGNleD0wLjYsIA0KICAgICAgICAgICAgICAgdGl0bGUgPSByb3cubmFtZXMoc3BpZGVyY3d1cjE1KSBbaV0pIA0KfQ0KDQpgYGANCg0KPEZPTlQgQ09MT1I9IkdyZWVuIj5SZXN1bHRhZG9zIGRlIDUgbWVqb3JlcyB1bml2ZXJzaWRhZGVzIGRlbCBtdW5kbyBlbg0KZGlmZXJlbnRlcyBjYXRlZ29yw61hcyBlbiAyMDE0PC9GT05UIENPTE9SPg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NCg0KIyBzcGlkZXJ3ZWIgMjAxNA0Kc3BpZGVyY3d1cjE0IDwtIGN3dXI1ICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNCkgJT4lIA0KICBzZWxlY3Qod29ybGRfcmFuaywgbmF0aW9uYWxfcmFuaywgY2l0YXRpb25zLCBhbHVtbmlfZW1wbG95bWVudCwgcHVibGljYXRpb25zLCBwYXRlbnRzLCBxdWFsaXR5X29mX2VkdWNhdGlvbikNCg0Kc3BpZGVyY3d1cjE0IDwtIGFzLmRhdGEuZnJhbWUoc3BpZGVyY3d1cjE0KQ0KDQptYXhfbWluIDwtIGRhdGEuZnJhbWUoDQogIHdvcmxkX3JhbmsgPSBjKDAsIDUwKSwgbmF0aW9uYWxfcmFuayA9IGMoMCwgNTApLCAgY2l0YXRpb25zID0gYygwLCA1MCksDQogIGFsdW1uaV9lbXBsb3ltZW50ID0gYygwLCA1MCksIHB1YmxpY2F0aW9ucyA9IGMoMCwgNTApLA0KICBwYXRlbnRzID0gYygwLCA1MCksIGVkdWNhdGlvbl9xdWFsaXR5ID0gYygwLCA1MCkpDQpyb3duYW1lcyhtYXhfbWluKSA8LSBjKCJNYXgiLCAiTWluIikNCg0KDQpzcGlkZXJjd3VyMTQgPC0gcmJpbmQocmVwKDEsIDcpLCByZXAoNTAsIDcpLCBzcGlkZXJjd3VyMTQpDQoNCnJvd25hbWVzKHNwaWRlcmN3dXIxNCkgPC0gYygibWF4IiwgIm1pbiIsICJIYXJ2YXJkIFVuaXZlcnNpdHkiLCAiU3RhbmZvcmQgVW5pdmVyc2l0eSIsICJNYXNzYWNodXNldHRzIEluc3RpdHV0ZSBvZiBUZWNobm9sb2d5IiwgIlVuaXZlcnNpdHkgb2YgQ2FtYnJpZGdlIiwgIlVuaXZlcnNpdHkgb2YgT3hmb3JkIikNCg0KY29sbmFtZXMoc3BpZGVyY3d1cjE0KSA8LSBjKCJ3b3JsZCByYW5rIiwgIm5hdGlvbmFsIHJhbmsiICwgImNpdGF0aW9ucyIsICJhbHVtbmkgZW1wbG95bWVudCIgLCAicHVibGljYXRpb25zIiwgInBhdGVudHMiLCAiZWR1Y2F0aW9uIHF1YWxpdHkiKQ0KDQoNCmNvdWwgPC0gYnJld2VyLnBhbCgxLCAiU2V0MiIpDQpjb2xvcnNfYm9yZGVyIDwtIGNvdWwNCmNvbG9yc19pbiA8LSBhbHBoYShjb3VsLDAuMykNCg0Kb3AgPC0gcGFyKG1hciA9IGMoMiwgMC4yLCAyLCAwKSkNCnBhcihtZnJvdyA9IGMoMiwzKSkNCg0KDQpmb3IoaSBpbiAzOm5yb3coc3BpZGVyY3d1cjE0KSl7DQogIHJhZGFyY2hhcnQoc3BpZGVyY3d1cjE0W2MoMToyLGkpLCBdLA0KICAgICAgICAgICAgIGNnbHR5ID0gMSwgICAgICAgDQogICAgICAgICAgICAgY2dsY29sID0gImdyYXkiLA0KICAgICAgICAgICAgIGNnbHdkPTAuOCwNCiAgICAgICAgICAgICBwY29sPWNvbG9yc19ib3JkZXIsIA0KICAgICAgICAgICAgIHBmY29sPWNvbG9yc19pbiwgICANCiAgICAgICAgICAgICBwbHdkID0gMiwgICAgICAgIA0KICAgICAgICAgICAgIHBsdHkgPSAxLCAgICANCiAgICAgICAgICAgICBjYXhpc2xhYmVscz1zZXEoMCwgNTAsIDEwKSwgDQogICAgICAgICAgICAgdmxjZXg9MC42LCANCiAgICAgICAgICAgICB0aXRsZSA9IHJvdy5uYW1lcyhzcGlkZXJjd3VyMTQpIFtpXSkgDQp9DQoNCmBgYA0KDQo8Rk9OVCBDT0xPUj0iUGluayI+UmVzdWx0YWRvcyBkZSA1IG1lam9yZXMgdW5pdmVyc2lkYWRlcyBkZWwgbXVuZG8gZW4NCmRpZmVyZW50ZXMgY2F0ZWdvcsOtYXMgZW4gMjAxMzwvRk9OVCBDT0xPUj4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUV9DQoNCg0KIyBzcGlkZXJ3ZWIgMjAxMw0Kc3BpZGVyY3d1cjEzIDwtIGN3dXI1ICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxMykgJT4lIA0KICBzZWxlY3Qod29ybGRfcmFuaywgbmF0aW9uYWxfcmFuaywgY2l0YXRpb25zLCBhbHVtbmlfZW1wbG95bWVudCwgcHVibGljYXRpb25zLCBwYXRlbnRzLCBxdWFsaXR5X29mX2VkdWNhdGlvbikNCg0Kc3BpZGVyY3d1cjEzIDwtIGFzLmRhdGEuZnJhbWUoc3BpZGVyY3d1cjEzKQ0KDQptYXhfbWluIDwtIGRhdGEuZnJhbWUoDQogIHdvcmxkX3JhbmsgPSBjKDAsIDUwKSwgbmF0aW9uYWxfcmFuayA9IGMoMCwgNTApLCAgY2l0YXRpb25zID0gYygwLCA1MCksDQogIGFsdW1uaV9lbXBsb3ltZW50ID0gYygwLCA1MCksIHB1YmxpY2F0aW9ucyA9IGMoMCwgNTApLA0KICBwYXRlbnRzID0gYygwLCA1MCksIGVkdWNhdGlvbl9xdWFsaXR5ID0gYygwLCA1MCkNCikNCnJvd25hbWVzKG1heF9taW4pIDwtIGMoIk1heCIsICJNaW4iKQ0KDQpzcGlkZXJjd3VyMTMgPC0gcmJpbmQocmVwKDEsIDcpLCByZXAoNTAsIDcpLCBzcGlkZXJjd3VyMTMpDQoNCnJvd25hbWVzKHNwaWRlcmN3dXIxMykgPC0gYygibWF4IiwgIm1pbiIsICJIYXJ2YXJkIFVuaXZlcnNpdHkiLCAiU3RhbmZvcmQgVW5pdmVyc2l0eSIsICJVbml2ZXJzaXR5IG9mIE94Zm9yZCIsICJNYXNzYWNodXNldHRzIEluc3RpdHV0ZSBvZiBUZWNobm9sb2d5IiwgIlVuaXZlcnNpdHkgb2YgQ2FtYnJpZGdlIikNCg0KY29sbmFtZXMoc3BpZGVyY3d1cjEzKSA8LSBjKCJ3b3JsZCByYW5rIiwgIm5hdGlvbmFsIHJhbmsiICwgImNpdGF0aW9ucyIsICJhbHVtbmkgZW1wbG95bWVudCIgLCAicHVibGljYXRpb25zIiwgInBhdGVudHMiLCAiZWR1Y2F0aW9uIHF1YWxpdHkiKQ0KDQoNCmNvdWwgPC0gYnJld2VyLnBhbCgxLCAiUGFzdGVsMSIpDQpjb2xvcnNfYm9yZGVyIDwtIGNvdWwNCmNvbG9yc19pbiA8LSBhbHBoYShjb3VsLDAuMykNCg0Kb3AgPC0gcGFyKG1hciA9IGMoMiwgMC4yLCAyLCAwKSkNCnBhcihtZnJvdyA9IGMoMiwzKSkNCg0KDQpmb3IoaSBpbiAzOm5yb3coc3BpZGVyY3d1cjEzKSl7DQogIHJhZGFyY2hhcnQoc3BpZGVyY3d1cjEzW2MoMToyLGkpLCBdLA0KICAgICAgICAgICAgIGNnbHR5ID0gMSwgICAgICAgDQogICAgICAgICAgICAgY2dsY29sID0gImdyYXkiLA0KICAgICAgICAgICAgIGNnbHdkPTAuOCwNCiAgICAgICAgICAgICBwY29sPWNvbG9yc19ib3JkZXIsIA0KICAgICAgICAgICAgIHBmY29sPWNvbG9yc19pbiwgICANCiAgICAgICAgICAgICBwbHdkID0gMiwgICAgICAgIA0KICAgICAgICAgICAgIHBsdHkgPSAxLCAgICAgDQogICAgICAgICAgICAgY2F4aXNsYWJlbHM9c2VxKDAsIDUwLCAxMCksIA0KICAgICAgICAgICAgIHZsY2V4PTAuNiwgDQogICAgICAgICAgICAgdGl0bGUgPSByb3cubmFtZXMoc3BpZGVyY3d1cjEzKSBbaV0pIA0KfQ0KYGBgDQoNCjxGT05UIENPTE9SPSJQdXJwbGUiPlJlc3VsdGFkb3MgZGUgNSBtZWpvcmVzIHVuaXZlcnNpZGFkZXMgZGVsIG11bmRvIGVuDQpkaWZlcmVudGVzIGNhdGVnb3LDrWFzIGVuIDIwMTI8L0ZPTlQgQ09MT1I+DQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0KDQojIHNwaWRlcndlYiAyMDEyDQpzcGlkZXJjd3VyMTIgPC0gY3d1cjUgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDEyKSAlPiUgDQogIHNlbGVjdCh3b3JsZF9yYW5rLCBuYXRpb25hbF9yYW5rLCBjaXRhdGlvbnMsIGFsdW1uaV9lbXBsb3ltZW50LCBwdWJsaWNhdGlvbnMsIHBhdGVudHMsIHF1YWxpdHlfb2ZfZWR1Y2F0aW9uKQ0KDQpzcGlkZXJjd3VyMTIgPC0gYXMuZGF0YS5mcmFtZShzcGlkZXJjd3VyMTIpDQoNCm1heF9taW4gPC0gZGF0YS5mcmFtZSgNCiAgd29ybGRfcmFuayA9IGMoMCwgNTApLCBuYXRpb25hbF9yYW5rID0gYygwLCA1MCksICBjaXRhdGlvbnMgPSBjKDAsIDUwKSwNCiAgYWx1bW5pX2VtcGxveW1lbnQgPSBjKDAsIDUwKSwgcHVibGljYXRpb25zID0gYygwLCA1MCksDQogIHBhdGVudHMgPSBjKDAsIDUwKSwgZWR1Y2F0aW9uX3F1YWxpdHkgPSBjKDAsIDUwKQ0KKQ0Kcm93bmFtZXMobWF4X21pbikgPC0gYygiTWF4IiwgIk1pbiIpDQoNCnNwaWRlcmN3dXIxMiA8LSByYmluZChyZXAoMSwgNyksIHJlcCg1MCwgNyksIHNwaWRlcmN3dXIxMikNCg0Kcm93bmFtZXMoc3BpZGVyY3d1cjEyKSA8LSBjKCJtYXgiLCAibWluIiwgIkhhcnZhcmQgVW5pdmVyc2l0eSIsICJNYXNzYWNodXNldHRzIEluc3RpdHV0ZSBvZiBUZWNobm9sb2d5IiwgIlN0YW5mb3JkIFVuaXZlcnNpdHkiLCAiVW5pdmVyc2l0eSBvZiBDYW1icmlkZ2UiLCAiQ2FsaWZvcm5pYSBJbnN0aXR1dGUgb2YgVGVjaG5vbG9neSIpDQoNCmNvbG5hbWVzKHNwaWRlcmN3dXIxMikgPC0gYygid29ybGQgcmFuayIsICJuYXRpb25hbCByYW5rIiAsICJjaXRhdGlvbnMiLCAiYWx1bW5pIGVtcGxveW1lbnQiICwgInB1YmxpY2F0aW9ucyIsICJwYXRlbnRzIiwgImVkdWNhdGlvbiBxdWFsaXR5IikNCg0KDQoNCmNvdWwgPC0gYnJld2VyLnBhbCgzLCAiUHVSZCIpDQpjb2xvcnNfYm9yZGVyIDwtIGNvdWwNCmNvbG9yc19pbiA8LSBhbHBoYShjb3VsLDAuNSkNCg0Kb3AgPC0gcGFyKG1hciA9IGMoMiwgMC4yLCAyLCAwKSkNCnBhcihtZnJvdyA9IGMoMiwzKSkNCg0KDQpmb3IoaSBpbiAzOm5yb3coc3BpZGVyY3d1cjEyKSl7DQogIHJhZGFyY2hhcnQoc3BpZGVyY3d1cjEyW2MoMToyLGkpLCBdLA0KICAgICAgICAgICAgIGNnbHR5ID0gMSwgICAgICAgDQogICAgICAgICAgICAgY2dsY29sID0gImdyYXkiLA0KICAgICAgICAgICAgIGNnbHdkPTAuOCwNCiAgICAgICAgICAgICBwY29sPWNvbG9yc19ib3JkZXIsIA0KICAgICAgICAgICAgIHBmY29sPWNvbG9yc19pbiwgIA0KICAgICAgICAgICAgIHBsd2QgPSAyLCAgICAgICAgDQogICAgICAgICAgICAgcGx0eSA9IDEsIA0KICAgICAgICAgICAgIGNheGlzbGFiZWxzPXNlcSgwLCA1MCwgMTApLCANCiAgICAgICAgICAgICB2bGNleD0wLjYsIA0KICAgICAgICAgICAgIHRpdGxlID0gcm93Lm5hbWVzKHNwaWRlcmN3dXIxMikgW2ldKSANCn0NCmBgYA0KDQpQYXJhIG9ic2VydmFyIGxhIHJlbGFjacOzbiBlbnRyZSBsYSAqKmNhbGlkYWQgZGUgbGEgZWR1Y2FjacOzbioqIHkgbGENCioqcG9zdGVyaW9yIGVtcGxlYWJpbGlkYWQqKiBkZSBsb3MgYWx1bW5vcyBwcmVwYXJhbW9zIGRvcyBncsOhZmljb3MsDQpkb25kZSBwb2RlbW9zIG9ic2VydmFyLCBxdWUgbGFzIHVuaXZlcnNpZGFkZXMgb2J0aWVuZW4gdW5hIGNsYXNpZmljYWNpw7NuDQptw6FzIGFsdGEgZW4gdMOpcm1pbm9zIGRlIGNhbGlkYWQgZGUgZW5zZcOxYW56YSBxdWUgZW1wbGVvIGRlIGxvcyBhbHVtbm9zDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0KZWR1X2VtcGwgPC0gY3d1cjEgJT4lIA0KICBmaWx0ZXIod29ybGRfcmFuayA8PSAxMCkgJT4lIA0KICBzZWxlY3QoeWVhciwgaW5zdGl0dXRpb24sIHF1YWxpdHlfb2ZfZWR1Y2F0aW9uLCBhbHVtbmlfZW1wbG95bWVudCkNCg0KZ2dwbG90KGVkdV9lbXBsLCBhZXMoeCA9IHF1YWxpdHlfb2ZfZWR1Y2F0aW9uLCB5ID0gaW5zdGl0dXRpb24pKSArDQogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWVzKGZpbGwgPSBpbnN0aXR1dGlvbiksIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiUXVhbGl0eSBvZiBlZHVjYXRpb24gaW4gMjAxMi0yMDE1IiwNCiAgICAgICB4ID0gImVkdWNhdGlvbiBxdWFsaXR5IikNCg0KZ2dwbG90KGVkdV9lbXBsLCBhZXMoeCA9IGFsdW1uaV9lbXBsb3ltZW50LCB5ID0gaW5zdGl0dXRpb24pKSArIA0KICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFlcyhmaWxsID0gaW5zdGl0dXRpb24pLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKHRpdGxlID0gIkFsdW1uaSBFbXBsb3ltZW50IGluIDIwMTItMjAxNSIsDQogICAgICAgeCA9ICJhbHVtbmkgZW1wbG95bWVudCIpDQoNCg0KYGBgDQoNCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCg0KIyMjICpUaW1lcyBIaWdoZXIgRWR1Y2F0aW9uIFdvcmxkIFVuaXZlcnNpdHkgUmFua2luZyoNCg0KQ2FtYmlhbW9zIGFob3JhIGRlIGZ1ZW50ZSB5IG9ic2VydmFtb3MgbG9zIGRhdG9zIHJlbGF0aXZvcyBhIGxhDQppbnN0aXR1Y2nDs24gW1RpbWVzIEhpZ2hlciBFZHVjYXRpb24gV29ybGQgVW5pdmVyc2l0eQ0KUmFua2luZ10oaHR0cHM6Ly93d3cudGltZXNoaWdoZXJlZHVjYXRpb24uY29tL2NvbnRlbnQvd29ybGQtdW5pdmVyc2l0eS1yYW5raW5ncykuDQoNCkVuIGxhIHNpZ3VpZW50ZSB0YWJsYSBhbmFsaXphbW9zLCAqKmN1w6FsZXMgaGFuIHNpZG8gbGFzIGRpZXogbWVqb3Jlcw0KdW5pdmVyc2lkYWRlcyoqIHNlZ8O6biBUaW1lcyByw6Fua2luZyBhIHRyYXbDqXMgZGUgbG9zIGHDsW9zIDIwMTItMjAxNS4gRW4NCmVzdGUgY2Fzbywgbm8gZXMgSGFydmFyZCBsYSBwcmltZXJhIGNsYXNpZmljYWRhLCBzaW5vIGVsICoqQ2FsaWZvcm5pYQ0KSW5zdGl0dWUgb2YgVGVjaG5vbG9neSoqIGR1cmFudGUgdG9kbyBlbCBwZXLDrW9kbywgc2VndWlkbyBhaG9yYSBzw60gZGUNCkhhcnZhcmQsIFN0YW5mb3JkLCBPeGZvcmQgeSBQcmluY2V0b24sIHF1ZSBhcGFyZWNlIGFxdcOtIHBvciBlbmNpbWEgZGUNCkNhbWJyaWRnZSB5IGVsIE1JVC4gRGUgZXN0YSBtYW5lcmEsIGNvbmNsdWltb3MgcXVlIGxvcyBkaWZlcmVudGVzDQpyw6Fua2luZ3Mgbm9zIHByb3BvcmNpb25hbiBjbGFzaWZpY2FjaW9uZXMgZGlmZXJlbnRlcy4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUV9DQoNCnRpbWVzMTAgPC0gdGltZXMxICU+JSANCiAgc2VsZWN0KHllYXIsIHdvcmxkX3JhbmtfTiwgdW5pdmVyc2l0eV9uYW1lKSAlPiUgDQogIGZpbHRlcih3b3JsZF9yYW5rX04gPD0gMTApICU+JSANCiAgcmVuYW1lKCJ1bml2ZXJzaXR5IG5hbWUiID0gdW5pdmVyc2l0eV9uYW1lKSANCg0KdGltZXMxMF93aWRlIDwtIHBpdm90X3dpZGVyKHRpbWVzMTAsIG5hbWVzX2Zyb20gPSB5ZWFyLCB2YWx1ZXNfZnJvbSA9IHdvcmxkX3JhbmtfTikNCg0Ka2JsKHRpbWVzMTBfd2lkZSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBsaXN0KGVuYWJsZWQgPSBULCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZCA9ICJsaWdodHBpbmsiKSkgJT4lIA0KICBrYWJsZV9wYXBlcihib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KUGFyYSBtb3N0cmFyIGVsIGNhbWJpbyBlbiBwdWVzdG9zIGRlIHJhbmtpbmcgYSBsbyBsYXJnbyBkZWwgdGllbXBvLA0KYWhvcmEgdXRpbGl6YW1vcyB1biBncsOhZmljbyBhbmltYWRvLCB0YWwgeSBjb21vIGhlbW9zIGhlY2hvIGFudGVzIGNvbg0KbG9zIGRhdG9zIGRlIENXVVIuIE51ZXZhbWVudGUsIGxvIHF1ZSBtw6FzIG5vcyBsbGFtYSBsYSBhdGVuY2nDs24gZXMgbGENCmJhamFkYSBjb25zaWRlYWJsZSBkZSBIYXJ2YXJkLCBxdWUgdnVlbHZlIGEgYXNjZW5kZXIgZGVzcHXDqXMuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIGV2YWwgPSBUUlVFfQ0KZ2dwbG90KHRpbWVzNSwgYWVzKHllYXIsIHdvcmxkX3JhbmtfTiwgY29sb3IgPSB1bml2ZXJzaXR5X25hbWUsIHNoYXBlID0gdW5pdmVyc2l0eV9uYW1lKSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplID0gNCkpKw0KICBzY2FsZV9jb2xvcl9icmV3ZXIodHlwZT0icXVhbCIsIHBhbGV0dGUgPSAzKSArDQogIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArDQogIGVhc2VfYWVzKCdsaW5lYXInKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQmVzdCA1IFVuaXZlcnNpdGllcyBieSBUSU1FUyIsDQogICAgICAgeSA9ICJyYW5rIikNCmBgYA0KDQpQYXJhIGFuYWxpemFyIHZhcmlhYmxlcyBkaWZlcmVudGVzIGEgbGFzIHlhIGVzdHVkaWFkYXMgY29uIGVsIG90cm8NCmRhdGFzZXQsIHZhbW9zIGEgb2JzZXJ2YXIgYWhvcmEgZWwgKipuw7ptZXJvIGRlIGVzdHVkaWFudGVzDQptYXRyaWN1bGFkb3MqKiBlbiBsYXMgMjAgbWVqb3JlcyB1bml2ZXJzaWRhZGVzIGEgbG8gbGFyZ28gZGVsIHRpZW1wbywgeQ0KbG8gdmlzdWFsaXphcmVtb3MgbWVkaWFudGUgdW4gZ3LDoWZpY28gdGFtYmnDqW4uIEVuIGVsIGdnYW5pbWF0ZSBwb2RlbW9zDQp2ZXIgY8OzbW8gY2FtYmlhIGVzdGUgbsO6bWVybyBhbCBsYXJnbyBkZSBsb3MgZGlmZXJlbnRlcyBhw7FvcyAoZGUgMjAxMiBhDQoyMDE2KS4NCg0KYGBge3IsIGVjaG89VFJVRX0NCiMgVmFtb3MgYSBlbGltaW5hciBhbGd1bmFzIHZhcmlhYmxlcyBxdWUgbm8gbWUgaW50ZXJlc2FuIGRlbCBkZiBvcmlnaW5hbCB5IGEgY3JlYXIgdW4gZGF0YWZyYW1lIGNvbiBsYXMgMjAgbWVqb3JlcyB1bml2ZXJzaWRhZGVzIHBvciBjYWRhIGHDsW8gDQoNCnRpbWVzX2RhdGFfMSA8LSB0aW1lc19kYXRhICU+JSBzZWxlY3Qod29ybGRfcmFuaywgdW5pdmVyc2l0eV9uYW1lLCBjb3VudHJ5LCB0b3RhbF9zY29yZSwgbnVtX3N0dWRlbnRzLCBpbnRlcm5hdGlvbmFsX3N0dWRlbnRzLCB5ZWFyKQ0KDQpkZl8yMDExIDwtIHRpbWVzX2RhdGFfMSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxMSkgJT4lIHNsaWNlX21heCh0b3RhbF9zY29yZSwgbiA9IDIwKQ0KDQpkZl8yMDEyIDwtIHRpbWVzX2RhdGFfMSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxMikgJT4lIHNsaWNlX21heCh0b3RhbF9zY29yZSwgbiA9IDIwKQ0KDQpkZl8yMDEzIDwtIHRpbWVzX2RhdGFfMSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxMykgJT4lIHNsaWNlX21heCh0b3RhbF9zY29yZSwgbiA9IDIwKQ0KDQpkZl8yMDE0IDwtIHRpbWVzX2RhdGFfMSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxNCkgJT4lIHNsaWNlX21heCh0b3RhbF9zY29yZSwgbiA9IDIwKQ0KDQpkZl8yMDE1IDwtIHRpbWVzX2RhdGFfMSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxNSkgJT4lIHNsaWNlX21heCh0b3RhbF9zY29yZSwgbiA9IDIwKQ0KDQpkZl8yMDE2IDwtIHRpbWVzX2RhdGFfMSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxNikgJT4lIHNsaWNlX21heCh0b3RhbF9zY29yZSwgbiA9IDIwKQ0KDQpkZl90b3RhbCA8LSByYmluZChkZl8yMDExLCBkZl8yMDEyLCBkZl8yMDEzLCBkZl8yMDE0LCBkZl8yMDE1LCBkZl8yMDE2KQ0KDQpybShkZl8yMDExLCBkZl8yMDEyLCBkZl8yMDEzLCBkZl8yMDE0LCBkZl8yMDE1LCBkZl8yMDE2LCB0aW1lc19kYXRhLCB0aW1lc19kYXRhXzEpDQoNCmBgYA0KDQpDcmVhbW9zIGFob3JhIGVsIGdyw6FmaWNvIGFuaW1hZG8gcXVlIG11ZXN0cmEgZWwgbsO6bWVybyBkZSBhbHVtbm9zDQptYXRyaWN1bGFkb3MNCg0KYGBge3IsIGVjaG89RkFMU0V9DQoNCg0KYW5pbWFjaW9uIDwtIGdncGxvdChkYXRhID0gZGZfdG90YWwpICsNCiAgZ2VvbV9jb2woYWVzKHVuaXZlcnNpdHlfbmFtZSwgbnVtX3N0dWRlbnRzLCBmaWxsID0gdW5pdmVyc2l0eV9uYW1lKSkgKw0KICBzY2FsZV95X2Rpc2NyZXRlKGJyZWFrcyA9IHNlcSgwLCAxMDAsIDEwKSwgbGFiZWwgPSBzY2FsZXM6OmRvbGxhcikgKw0KICBnZW9tX3RleHQoYWVzKHVuaXZlcnNpdHlfbmFtZSwgbnVtX3N0dWRlbnRzLCBsYWJlbCA9IG51bV9zdHVkZW50cyksIGhqdXN0PS0wLjUpICsNCiAgZ2VvbV90ZXh0KGFlcyh1bml2ZXJzaXR5X25hbWUsIHk9MCwgbGFiZWwgPSB1bml2ZXJzaXR5X25hbWUpLCBoanVzdD0xLjEpICsgDQogIGdlb21fdGV4dChhZXMoeD0xNSwgeT1tYXgobnVtX3N0dWRlbnRzKSAsIGxhYmVsID0gYXMuZmFjdG9yKHllYXIpKSwgdmp1c3QgPSA1LCBhbHBoYSA9IDAuNSwgIGNvbCA9ICJncmF5Iiwgc2l6ZSA9IDEwKSArDQogIGNvb3JkX2ZsaXAoY2xpcCA9ICJvZmYiLCBleHBhbmQgPSBGQUxTRSkgKyANCiAgdGhlbWVfbWluaW1hbCgpICsgdGhlbWUoDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMSwgNCwgMSwgOSwgImNtIikNCiAgKSArDQogIHRyYW5zaXRpb25fc3RhdGVzKHllYXIsIHN0YXRlX2xlbmd0aCA9IDAsIHRyYW5zaXRpb25fbGVuZ3RoID0gMikgKw0KICBlYXNlX2FlcyAoJ2xpbmVhcicpICsNCiAgbGFicyh0aXRsZSA9ICJOw7ptZXJvIGRlIGVzdHVkaWFudGVzIGEgbG8gbGFyZ28gZGVsIHRpZW1wbyIsDQogICAgICAgeSA9ICJOdW0gRXN0dWRpYW50ZXMiKQ0KDQphbmltYXRlKGFuaW1hY2lvbiwgd2lkdGggPSA3MDAsIGhlaWdodCA9IDQzMiwgZnBzID0gMjUsIGR1cmF0aW9uID0gMTUsIHJld2luZCA9IEZBTFNFKQ0KDQpgYGANCg0KRGFkbyBxdWUgZXN0YXMgdW5pdmVyc2lkYWRlcyBzdWVsZW4gc2VyIGJhc3RhbnRlIGludGVybmFjaW9uYWxlcywNCnRhbWJpw6luIGhlbW9zIHF1ZXJpZG8gb2JzZXJ2YXIgY3XDoWwgZXMgZXhhY3RhbWVudGUgZWwgKipwb3JjZW50YWplIGRlDQphbHVtbm9zIGludGVybmFjaW9uYWxlcyoqIGVuIHJlbGFjacOzbiBjb24gZWwgYW50ZXJpb3Igb2JzZXJ2YWRvIG7Dum1lcm8NCmRlIGVzdHVkaWFudGVzLg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KDQpkZl90b3RhbCA8LSBkZl90b3RhbCAlPiUgDQogIG11dGF0ZShpbnRlcm5hdGlvbmFsX3N0dWRlbnRzID0gcGFyc2VfbnVtYmVyKGludGVybmF0aW9uYWxfc3R1ZGVudHMpIC8gMTAwKSAlPiUNCiAgbXV0YXRlKG51bV9zdHVkZW50cyA9IHBhcnNlX251bWJlcihudW1fc3R1ZGVudHMpKSAlPiUNCiAgbXV0YXRlKG51bV9pbnRlcm5hdGlvbmFsX3N0dWRlbnRzID0gbnVtX3N0dWRlbnRzICogaW50ZXJuYXRpb25hbF9zdHVkZW50cykgJT4lIA0KICBtdXRhdGUoaW50ZXJuYXRpb25hbF9zdHVkZW50cyA9IHBlcmNlbnQoaW50ZXJuYXRpb25hbF9zdHVkZW50cykpICU+JSANCiAgbXV0YXRlKHRvdGFsID0gMTAwKSAlPiUgZmlsdGVyKHllYXIgPT0gMjAxNikNCiAgDQoNCnAxIDwtIGdncGxvdChkZl90b3RhbCwgYWVzKHVuaXZlcnNpdHlfbmFtZSwgbnVtX3N0dWRlbnRzKSkgKyBnZW9tX2NvbChmaWxsID0gImJsdWUiKSArIGNvb3JkX2ZsaXAoKSArIA0KICBnZW9tX2NvbChhZXModW5pdmVyc2l0eV9uYW1lLCBudW1faW50ZXJuYXRpb25hbF9zdHVkZW50cywgZmlsbCA9ICJyZWQiKSkgKw0KICBnZW9tX3RleHQoYWVzKHVuaXZlcnNpdHlfbmFtZSwgdG90YWwsIGxhYmVsID0gaW50ZXJuYXRpb25hbF9zdHVkZW50cyksIGhqdXN0ID0gLTYpICsNCiAgdGhlbWVfbWluaW1hbCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIk5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiUG9yY2VudGFqZSBFc3R1ZGlhbnRlcyBJbnRlcm5hY2lvbmFsZXMiLA0KICAgICAgIHN1YnRpdGxlID0gIkRhdG9zIGRlbCBhw7FvIDIwMTYiLA0KICAgICAgIHggPSAiVW5pdmVyc2lkYWRlcyIsDQogICAgICAgeSA9ICJOdW0gRXN0dWRpYW50ZXMiKQ0KDQpwMQ0KYGBgDQoNCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCg0KIyMjICpBY2FkZW1pYyBSYW5raW5nIG9mIFdvcmxkIFVuaXZlcnNpdGllcyoNCg0KVGFtYmnDqW4gY29ub2NpZG8gY29tbyBbU2hhbmdoYWkNClJhbmtpbmddKGh0dHA6Ly93d3cuc2hhbmdoYWlyYW5raW5nLmNvbS8pLCBlcyB1bm8gZGUgbG9zIG3DoXMgY29ub2NpZG9zIHkNCnByZXN0aWdpb3NvcyBkZWwgbXVuZG8uIFZhbW9zIGEgYW5hbGl6YXIgYmllbiBzdXMgZGF0b3MgZGUgbWFuZXJhDQp2aXN1YWwuIENvbW8gZW4gZXN0ZSBjYXNvIG5vIHRlbmVtb3MgZGF0b3Mgc29icmUgbG9zIHBhw61zZXMsIHZhbW9zIGENCnZpc3VhbGl6YXIgZW4gdW5hIHRhYmxhICoqY3XDoWxlcyBoYW4gc2lkbyBsYXMgZGlleiBtZWpvcmVzDQp1bml2ZXJzaWRhZGVzKiogYSB0cmF2w6lzIGRlIGxvcyBhw7FvcyAyMDEyLTIwMTUuIE51ZXZhbWVudGUgYXBhcmVjZQ0KSGFydmFyZCBhIGxhIGNhYmV6YSwgc2VndWlkYSBkZSBTdGFuZG9yZCB5IGVsIE1JVC4gU2luIGVtYmFyZ28sIGFob3JhIHNlDQpjbGFzaWZpY2EgZW4gY3VhcnRvIGx1Z2FyIGxhIFVDIEJlcmtlbGV5IHBvciBkZWxhbnRlIGRlIENhbWJyaWRnZS4NCg0KYGBge3IsIGVjaG89RkFMU0UsIGV2YWwgPSBUUlVFfQ0KDQpzaGFuZ2hhaTEwIDwtIFNoYW5naGFpMSAlPiUgDQogIHNlbGVjdCh5ZWFyLCB3b3JsZF9yYW5rX04sIHVuaXZlcnNpdHlfbmFtZSkgJT4lIA0KICBmaWx0ZXIod29ybGRfcmFua19OIDw9IDEwKSAlPiUgDQogIHJlbmFtZSgidW5pdmVyc2l0eSBuYW1lIiA9IHVuaXZlcnNpdHlfbmFtZSkNCg0Kc2hhbmdoYWkxMF93aWRlIDwtIHBpdm90X3dpZGVyKHNoYW5naGFpMTAsIG5hbWVzX2Zyb20gPSB5ZWFyLCB2YWx1ZXNfZnJvbSA9IHdvcmxkX3JhbmtfTikNCg0Ka2JsKHNoYW5naGFpMTBfd2lkZSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBsaXN0KGVuYWJsZWQgPSBULCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZCA9ICJsaWdodHllbGxvdyIpKSAlPiUgDQogIGthYmxlX3BhcGVyKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQpUZW5pZW5kbyBlbiBjdWVudGEgYWhvcmEgbGFzICoqY2luY28gbWVqb3JlcyB1bml2ZXJzaWRhZGVzKiogc2Vnw7puIGVzdGUNCnLDoW5raW5nLCBwb2RlbW9zIGhhY2VyIHVuIGFuw6FsaXNpcyBkZSB1bmEgbWFuZXJhIG3DoXMgdmlzdWFsLCBhIHRyYXbDqXMNCihkZSBudWV2bykgZGUgbG9zIGHDsW9zIDIwMTItMjAxNS4gUGFyYSBlc28gdXRpbGl6YW1vcyB1biBtYXBhIGFuaW1hZG8sDQp0YWwgeSBjb21vIGhlbW9zIGhlY2hvIGFudGVzIGNvbiBsb3MgZGF0b3MgZGUgQ1dVUiB5IFRJTUVTLiBFbiBlc3RhDQpvY2FzacOzbiwgbG9zIGRhdG9zIHNvbiBkaXN0aW50b3MsIHkgcG9kZW1vcyB2ZXIgY8OzbW8gbG9zIHB1ZXN0b3MgMSwgMiB5DQo1IHNlIG1hbnRpZW5lbiBlc3RhYmxlcywgbWllbnRyYXMgcXVlIGVsIE1JVCB5IFVDIEJlcmtlbGV5IHZhbg0KaW50ZXJjYW1iaWFuZG8gcG9zaWNpb25lcy4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgZXZhbCA9IFRSVUV9DQoNClNoYW5naGFpNWEgPC0gU2hhbmdoYWk1ICU+JSANCiAgc2VsZWN0KHdvcmxkX3JhbmtfTiwgdW5pdmVyc2l0eV9uYW1lLCB5ZWFyKQ0KDQpnZ3Bsb3QoU2hhbmdoYWk1YSwgYWVzKHllYXIsIHdvcmxkX3JhbmtfTiwgY29sb3IgPSB1bml2ZXJzaXR5X25hbWUsIHNoYXBlID0gdW5pdmVyc2l0eV9uYW1lKSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplID0gNCkpKw0KICBzY2FsZV9jb2xvcl9icmV3ZXIodHlwZT0icXVhbCIsIHBhbGV0dGUgPSAzKSArDQogIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArDQogIGVhc2VfYWVzKCdsaW5lYXInKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiQmVzdCA1IFVuaXZlcnNpdGllcyBieSBTaGFuZ2hhaSBSYW5raW5nIiwNCiAgICAgICB5ID0gInJhbmsiKQ0KYGBgDQoNCkEgY29udGludWFjacOzbiBlbiBsb3MgZ3LDoWZpY29zIHF1ZXJlbW9zIG1vc3RyYXIgbG9zIHJlc3VsdGFkb3MgZGUgbGFzDQoqKjEwIG1lam9yZXMgdW5pdmVyc2lkYWRlcyBlbiAyMDE1KiosIGVuIGRvcyBjYXRlZ29yw61hczogKipQcm9mZXNvcmVzKioNCmRlIHVuYSBpbnN0aXR1Y2nDs24sICoqZ2FuYWRvcmVzIGRlIHByZW1pb3MgTm9iZWwgeSBtZWRhbGxhcyBGaWVsZHMqKiB5DQoqKkFsdW1ub3MqKiBkZSB1bmEgaW5zdGl0dWNpw7NuLCAqKmdhbmFkb3JlcyBkZSBwcmVtaW9zIE5vYmVsIHkgbWVkYWxsYXMNCkZpZWxkcyoqLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gVFJVRX0NClNoYW5naGFpMTAgPC0gU2hhbmdoYWkxICU+JSANCiAgZmlsdGVyKHdvcmxkX3JhbmtfTiA8PSAxMCkgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDE1KQ0KDQpnZ3Bsb3QoU2hhbmdoYWkxMCwgYWVzKHggPSB1bml2ZXJzaXR5X25hbWUsIHkgPSBhd2FyZCkpICsNCiAgZ2VvbV9zZWdtZW50KGFlcyh4PXVuaXZlcnNpdHlfbmFtZSwgeGVuZD11bml2ZXJzaXR5X25hbWUsIHk9MCwgeWVuZD1hd2FyZCkpICsNCiAgZ2VvbV9wb2ludCggc2l6ZT01LCBjb2xvcj0iYmx1ZSIsIGZpbGw9YWxwaGEoImxpZ2h0cGluayIsIDAuMyksIGFscGhhPTAuNywgc2hhcGU9MjEsIHN0cm9rZT0yKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnModGl0bGUgPSAiU3RhZmYgd2lubmluZyBOb2JlbCBQcml6ZXMgYW5kIEZpZWxkcyBNZWRhbHMgaW4gMjAxNSIsDQogICAgICAgeCA9ICJ1bml2ZXJzaXR5IG5hbWUiLA0KICAgICAgeSA9ICJzdGFmZiIpDQoNCmdncGxvdChTaGFuZ2hhaTEwLCBhZXMoeCA9IHVuaXZlcnNpdHlfbmFtZSwgeSA9IGFsdW1uaSkpICsNCiAgZ2VvbV9zZWdtZW50KGFlcyh4PXVuaXZlcnNpdHlfbmFtZSwgeGVuZD11bml2ZXJzaXR5X25hbWUsIHk9MCwgeWVuZD1hbHVtbmkpKSArDQogIGdlb21fcG9pbnQoIHNpemU9NCwgY29sb3I9IkdyZWVuIiwgZmlsbD1hbHBoYSgieWVsbG93IiwgMC4zKSwgYWxwaGE9MC43LCBzaGFwZT0yMSwgc3Ryb2tlPTIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJBbHVtbmkgd2lubmluZyBOb2JlbCBQcml6ZXMgYW5kIEZpZWxkcyBNZWRhbHMgaW4gMjAxNSIsDQogICAgICAgeCA9ICJ1bml2ZXJzaXR5IG5hbWUiKQ0KICANCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyA0LiBDb25jbHVzaW9uZXMNCg0KRGVzcHXDqXMgZGUgYW5hbGl6YXIgbnVlc3Ryb3MgZGF0b3MgbWVkaWFudGUgZ3LDoWZpY29zIHkgdGFibGFzLCBoZW1vcw0KdmlzdG8gY29tbyBkaWZlcmVudGVzIHJhbmtpbmdzIG5vcyBvZnJlY2VuIGluZm9ybWFjacOzbiBkaXZlcnNhLg0KUHJpbmNpcGFsbWVudGUgZXh0cmFlbW9zIGNvbW8gY29uY2x1c2nDs24gcXVlIEVzdGFkb3MgVW5pZG9zIGVzIGVsIHBhw61zDQpjb24gbGFzIG1lam9yZXMgdW5pdmVyc2lkYWRlcyBkZSB0b2RvIGVsIG11bmRvLCBzaW4gaW1wb3J0YXIgZWwgZGF0YXNldA0KZW4gcXVlIG5vcyBiYXNlbW9zLiBUYW1iacOpbiBoZW1vcyBwb2RpZG8gb2JzZXJ2YXIgY29tbyB1biBidWVuDQpwb3NpY2lvbmFtaWVudG8gZW4gZWwgcsOhbmtpbmcgbXVuZGlhbCB0aWVuZSByZWxhY2nDs24gdGFtYmnDqW4gY29uIHVuYQ0KZWxldmFkYSBwb3NpY2nDs24gcmVzcGVjdG8gYWwgbsO6bWVybyBkZSBwdWJsaWNhY2lvbmVzIG8gY2l0YXMsIGFzw60gY29tbw0KbGEgcG9zaWNpw7NuIGVuIGVsIHLDoW5raW5nIGEgbml2ZWwgbmFjaW9uYWwuIEFkZW3DoXMsIGhlbW9zIG9ic2VydmFkbyBjb21vDQpsYXMgbWVqb3JlcyB1bml2ZXJzaWRhZGVzIHN1ZWxlbiBtYW50ZW5lciBzdSBlc3RhdHVzLHkgZW4gcmFyYXMNCm9jYXNpb25lcyB2ZW1vcyBjYW1iaW9zIHNpZ25pZmljYXRpdm9zIGVuIGxvcyByYW5raW5ncy4gWSB0YW1iacOpbg0KcG9kZW1vcyBhZmlybWFyIHF1ZSBjYWRhIHLDoW5raW5nLCBkZXBlbmRpZW5kbyBlbiBsb3MgY3JpdGVyaW9zDQp1dGlsaXphZG9zIHBhcmEgY2xhc2lmaWNhciBsYXMgdW5pdmVyc2lkYWRlcywgbm9zIG9mcmVjZSB1biBvcmRlbg0KZGlmZXJlbnRlLCBwb3IgZXNvIGVzIGludGVyZXNhbnRlIHRlbmVyIGVuIGN1ZW50YSBkaWZlcmVudGVzDQppbnN0aXR1Y2lvbmVzIGN1YW5kbyBxdWVyZW1vcyBoYWNlciB1biBhbsOhbGlzaXMgZ2xvYmFsIGRlIGxhIHNpdHVhY2nDs24uDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIDUuIFRyYWJham9zIGVuIGxvcyBxdWUgbm9zIGhlbW9zIGJhc2Fkbw0KDQpQYXJhIHJlYWxpemFyIGVzdGUgZXN0dWRpbywgbm9zIGhlbW9zIGJhc2FkbyBlbiBvdHJvcyB0cmFiYWpvcyBhIHBhcnRlDQpkZSB0ZW5lciBpZGVhcyBwcm9waWFzLiBFbnRyZSBlbGxvcywgZW5jb250cmFtb3MgdHJhYmFqb3MgcXVlIHNlDQpyZWFsaXphcm9uIGVuIGVzdGEgYXNpZ25hdHVyYSBlbCBhw7FvIHBhc2FkbywgZGUgZG9uZGUgaGVtb3Mgc2FjYWRvDQppbmZvcm1hY2nDs24gc29icmUgY8OzbW8gZWxhYm9yYXIgZWwgUm1hcmtkb3duIGRlIHVuYSBtYW5lcmEgbcOhcyBlbGVnYW50ZS4NCg0KLSAgIFtBbsOhbGlzaXMgc29icmUgbGENCiAgICBDb3ZpZC0xOV0oaHR0cHM6Ly9ub3NhbjUuZ2l0aHViLmlvL3RyYWJham9fQmlnRGF0YV9lcXVpcG8vKSAoSWduYWNpbw0KICAgIE1vbnRhdmEsIEFuZHJldSBFc3BhcnphIHkgTm9lbGlhIFPDoW5jaGV6KQ0KDQotICAgW1dvcmxkIFVuaXZlcnNpdHkgUmFua2luZ3MgQWR2YW5jZWQNCiAgICBBbmFseXNpc10oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9ncHJlZGEvd29ybGQtdW5pdmVyc2l0eS1yYW5raW5ncy1hZHZhbmNlZC1hbmFseXNpcy9yZXBvcnQpDQogICAgKEdhYnJpZWwgUHJlZGEpDQogICAgDQotICAgW1VuaXZlcnNpZGFkZXMgbMOtZGVyZXMgZW4gZWwgbXVuZG9dKGh0dHBzOi8vd3d3Lml2aWUuZXMvZXNfRVMvcHRwcm95ZWN0by9mdXR1cm8tZGVsLWxpZGVyYXpnby1sYXMtdW5pdmVyc2lkYWRlcy1sYXMtc29jaWVkYWRlcy1hdmFuemFkYXMvKQ0KICAoQmVsw6luIE1pcmF2YWxsZXMgUMOpcmV6LCBJbsOpcyBSb3NlbGwgUXVpbnRhbmlsbGEsIElyZW5lIFphZXJhIEN1YWRyYWRvLCANCiAgRGlyaWdpZG8gcG9yOiBGcmFuY2lzY28gUMOpcmV6IEdhcmPDrWEsIEpvYXF1w61uIEFsZMOhcyBNYW56YW5vLCBKb3PDqSBNYXLDrWEgUGVpcsOzIFNpbGxhKQ0KDQo8aHIgY2xhc3M9ImxpbmVhLXJlZCI+DQoNCiMgNi4gQmlibGlvZ3JhZsOtYQ0KDQpBZGVtw6FzLCBoZW1vcyB1dGlsaXphZG8gY29tbyBwcmluY2lwYWxlcyBoZXJyYW1pZW50YXMgZW4gbGEgZWxhYm9yYWNpw7NuDQpkZWwgdHJhYmFqbzoNCg0KLSAgIExhIFtww6FnaW5hIHdlYiBkZWwNCiAgICBjdXJzb10oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViL2luZGV4Lmh0bWwpIGRlDQogICAgUHJvZ3JhbWFjacOzbiB5IG1hbmVqbyBkZSBkYXRvcyBlbiBsYSBlcmEgZGVsIEJpZyBEYXRhLg0KDQotICAgTGEgYmFzZSBkZSBkYXRvcyBbS2FnZ2xlXShodHRwczovL3d3dy5rYWdnbGUuY29tLykuDQoNCi0gICBHYWxlcsOtYSBkZSBncsOhZmljb3MgZGUgW2dncGxvdF0oaHR0cHM6Ly93d3cuci1ncmFwaC1nYWxsZXJ5LmNvbS8pLg0KDQo8YnI+PGJyPg0KDQo8aHIgY2xhc3M9ImxpbmVhLXJlZCI+DQoNCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCg0KIyA3LiBTZXNpw7NuIGluZm9ybWF0aXZhDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkgJT4lIGRldGFpbHM6OmRldGFpbHMoc3VtbWFyeSA9ICdJbmZvcm1hY2nDs24gZGUgbWkgUi1zZXNpw7NuOicpIA0KYGBgDQoNCjxicj48YnI+DQoNCg0K