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í.


Introducción

Los Juegos Olímpicos son los principales eventos deportivos internacionales que incluyen competiciones deportivas de verano e invierno en las que miles de atletas de todo el mundo participan en una variedad de competiciones. Los Juegos Olímpicos se consideran la competición deportiva más importante del mundo con la participación de más de 200 naciones, estos se celebran cada cuatro años, donde los Juegos de Verano y de Invierno se alternan cada cuatro años, pero con dos años de diferencia.

La evolución del Movimiento Olímpico durante los siglos XX y XXI ha dado lugar a varios cambios en los Juegos Olímpicos. Algunos de estos ajustes incluyen la creación de los Juegos Olímpicos de Invierno para deportes de nieve y hielo, los Juegos Paralímpicos para atletas con discapacidad, los Juegos Olímpicos de la Juventud para atletas de 14 a 18 años, los cinco Juegos Continentales (Panamericanos, Africanos, Asiáticos, Europa y el Pacífico) y los Juegos Mundiales de deportes que no se disputan en los Juegos Olímpicos. Los Deaflympics y Special Olympics también cuentan con el respaldo del COI. El COI ha tenido que adaptarse a una variedad de avances económicos, políticos y tecnológicos. Como resultado, los Juegos Olímpicos se han alejado del amateurismo puro, como lo imaginó Coubertin, para permitir la participación de atletas profesionales. La creciente importancia de los medios de comunicación generó el problema del patrocinio empresarial y la comercialización de los Juegos. Las guerras mundiales llevaron a la cancelación de los Juegos de 1916, 1940 y 1944. Los grandes boicots durante la Guerra Fría limitaron la participación en los Juegos de 1980 y 1984. Este último, sin embargo, atrajo a 140 Comités Olímpicos Nacionales, lo que fue un récord en ese momento.

Para obtener más información, consulte la página oficial de los Juegos Olímpicos..

Datos

Extracción de datos

Este es un conjunto de datos históricos sobre los Juegos Olímpicos modernos, incluidos todos los Juegos desde Atenas 1896 hasta Río 2016. Estos datos los he extraido de Kaggle, una base de datos donde se pueden encontrar una infinidad de dataframes con información muy valios, desde la carrera de Cristiano Ronaldo en números, hasta modelos de Value Investing para la valoración de muchas empresas cotizadas.

Como estos datos pesan demasiado para ponerlos en el repositorio de Github, a continuación os dejo el enlace de descarga

Código

#Vamos a cargar los df

atheletes <- read.csv("./datos/athlete_events.csv", stringsAsFactors = F)
regions <- read.csv("./datos/noc_regions.csv", stringsAsFactors = F)

Análisis por Sexo:

Números aproximados:

La primera parte de nuestro análisis será útil para comprender cómo han evolucionado los Juegos Olímpicos a lo largo del tiempo.

df <- atheletes %>%
  group_by(Season, Sex) %>%
  summarise(Count = n()) %>%
  mutate(Percentage = round(Count*100 / sum(Count))) 
  
df %>%   
ggplot(aes(x=Season, y=Percentage, fill = Sex)) + geom_bar(stat='identity',position=position_dodge()) +
        ggtitle("Porcentaje de Hombres y mujeres que participan(2007-2017)") +
        geom_label(label=df$Percentage, position = position_dodge(0.9)) +
        theme_minimal() 
        

Durante el invierno y el verano el porcentaje y las mujeres se han mantenido iguales ya que apenas se puede observar una variación elevada.

Tendencia de participación:

Tendencia de participación por años:

A medida que avanzaban los Juegos Olímpicos a lo largo de los años, el número de personas que participaban en ellos habría aumentado, lo que significaba que el número de hombres y mujeres que participaban en los Juegos Olímpicos crecía.


p1 <- atheletes %>%
  group_by(Year, Season) %>%
  summarise(NumberOfParticipants = n()) %>%
  ggplot(aes(x = Year, y = NumberOfParticipants, group = Season)) +
  geom_line(aes(color = Season)) +
  geom_point(aes(color = Season)) +
  labs(x = "Año", y = "Número de participantes", title = "Número de participantes en las olimpiadas por año")+
  theme_minimal()

ggplotly(p1)

El número de participantes en los Juegos Olímpicos ha crecido con el paso del tiempo. También es obvio que el número de participantes en los juegos olímpicos de verano es mayor que el de los juegos olímpicos de invierno.

Tendencia por ratio de sexo:

groupMale <- atheletes %>%
              filter(Sex == "M") %>%
              group_by(Year, Season) %>%
              summarise(Number_Of_Men = n())

groupFemale <- atheletes %>%
              filter(Sex == "F") %>%
              group_by(Year, Season) %>%
              summarise(Number_Of_Women = n())

group <- groupMale %>%
          left_join(groupFemale) %>%
          mutate(Sex_Ratio = Number_Of_Men/Number_Of_Women)

group$Sex_Ratio[is.na(group$Sex_Ratio)] <- 175

p1 <- group %>%
    ggplot(aes(x = Year, y= Sex_Ratio, group = Season)) +
    geom_line(aes(color = Season)) +
    geom_point(aes(color = Season)) +
    labs(x = "Año", y = "Ratio de sexo", title = "Ratio de sexo en las Olimpiadas por años") +
    theme_minimal()

p2 <- group %>%
    filter(Year>1927) %>%
    ggplot(aes(x = Year, y= Sex_Ratio, group = Season)) +
    geom_line(aes(color = Season)) +
    geom_point(aes(color = Season)) +
    labs(x = "Año", y = "Ratio de sexo", title = "Ratio de sexo en las Olimpiadas después de 1927") +
    theme_minimal()

cowplot::plot_grid(p1,p2, ncol = 1, 
          align = 'h', axis = 'l')

Cuando comenzaron los Juegos Olímpicos, ninguna mujer participó en los Juegos Olímpicos. En 1900 las mujeres comenzaron a participar en los Juegos Olímpicos. A medida que pasaron los años, la proporción de sexos, es decir, la proporción de hombres a mujeres se hizo más pequeña. Después de 2000, la proporción comenzó a moverse hacia 1, lo que significa que los Juegos Olímpicos ahora son más diversos de lo que solían ser.

Análisis por Edad:

La edad es algo que podría haber cambiado desde que comenzaron los Juegos Olímpicos. Hipótesis: Los participantes durante los Juegos Olímpicos de 1900 tenían una edad media mayor que la edad media de los participantes durante los 2000.

Análisis de edad por densidad:

Primero que todo vamos a quitar los NA’s de nuestro df para poder calcular la media de edad, ya que si no en lugar de reportarnos la edad nos reportaria un NA como una casa de grande.

atheletes$Age[is.na(atheletes$Age)] <- median(atheletes$Age, na.rm = T)

Ahora calcularemos la media de edad para el conjunto de atletas olimpicos y luego la media de edad por sexo

La media de edad de los atletas en los juegos olimpicos es 24

cat("La media de edad de los atletas en los juegos olimpicos es", median(atheletes$Age))
#> La media de edad de los atletas en los juegos olimpicos es 24

La media de edad de los hombres atletas en los juegos olimpicos es 25

cat("La media de edad de los hombres atletas en los juegos olimpicos es", median(atheletes$Age[atheletes$Sex == "M"]))
#> La media de edad de los hombres atletas en los juegos olimpicos es 25

La media de edad de las mujeres atletas en los juegos olimpicos es 23

cat("La media de edad de las mujeres atletas en los juegos olimpicos es", median(atheletes$Age[atheletes$Sex == "F"]))
#> La media de edad de las mujeres atletas en los juegos olimpicos es 23

Como podemos observar de los analisis anteriores, la edad promedio de las atletas femeninas fue menor que la edad promedio de los atletas masculinos.

# Sustituimos los NA's con la edad media obtenida.

p1 <- atheletes %>%
      ggplot(aes(x = Age)) +
      geom_density(color = "black", fill = "tomato") +
      labs(x = "Año", title = "Distribución de edad") +
      theme_minimal()

p2 <- atheletes %>%
      ggplot(aes(x=Age, fill=Sex)) +
      geom_density(alpha=0.4) +
      labs(x = "Año", title = "Distribución de edad por Sexos") +
      theme_minimal()

cowplot::plot_grid(p1,p2, ncol = 1, 
          align = 'h', axis = 'l')

Edad de los atletas por años:

atheletes %>%
  group_by(Year, Sex) %>%
  summarise(Median_Age = median(Age)) %>%
  ggplot(aes(x = Year, y = Median_Age, Group = Sex)) +
  geom_line(aes(color = Sex)) +
  geom_point(aes(color = Sex)) + 
  labs( x = "Year", y = "Medain age of Athletes", title = "Median age of Male and Female athletes over the years")+
  theme_minimal()

La media de edad de los atletas masculinos y femeninos ha aumentado desde el 1980 tal y como podemos observar en el gráfico de arriba.

Análisis por equipo:

Los equipos aquí se refieren a los países y los diferentes clubes atléticos que han participado en los Juegos Olímpicos a lo largo de los años.

cat("El número total de equipos que han participado en las olimiadas es de ", length(unique(atheletes$Team)))
#> El número total de equipos que han participado en las olimiadas es de  1184

El número total de equipos que han participado en las olimiadas es de 1184

#Ahora vamos a unir en un mismo df los atletas y su región de pertenencia
atheletes <- atheletes %>%
              left_join(regions, by = "NOC")

Con el código que esta oculto arriba, acabamos de unir el conjunto de datos de los atletas con el conjunto de datos de las regiones. Me gustaría analizar el conjunto de datos basado en el Comité Olímpico Nacional en lugar de los equipos.

  cat("El número total de Comités Olímpicos Nacionales que han participado en las olimpiadas es de", length(unique(atheletes$region)))
#> El número total de Comités Olímpicos Nacionales que han participado en las olimpiadas es de 206

“El número total de Comités Olímpicos Nacionales que han participado en las olimpiadas es de 206”

A continuación vamos a representar un gráfico de barras donde observaremos cuales son los paises con más medallas ganadas de la historia.

atheletes %>%
  filter(Medal != "<NA>") %>%
  group_by(region) %>%
  summarise(Medal_Tally = length(Medal))%>%
  arrange(desc(Medal_Tally)) %>%
  ungroup() %>%
  mutate(region = reorder(region,Medal_Tally)) %>%
  top_n(10) %>%
  ggplot(aes(x = region,y = Medal_Tally)) +
    geom_bar(stat='identity',colour="white", fill = "tomato") +
    geom_text(aes(x = region, y = .1, label = paste0("(",round(Medal_Tally,2),")",sep="")),
              hjust=0, vjust=.5, size = 4, colour = 'black',
              fontface = 'bold') +
    theme(plot.title = element_text(size=10),
          axis.title = element_text(size=10),
          axis.text = element_text(size=10)) +
    labs(x = 'País', 
         y = 'Número de medallas'
         ) +
    coord_flip() + 
    theme_bw()

Como podemos observar del gráfico que vemos arriba, los paises con más medallas ganadas son:

  • Estados Unidos con un total de 5637 medallas.
  • Rusia con un total de 3947 medallas.
  • Alemania con un total de 3756 medallas.
  • Reino Unido con un total de 2068 medallas.
  • Francia con un total de 1777 medallas.

Comparación del Top 4 de países:

A continuación crearemos dos gráficos para observar que país ha conseguido más medallas por año y que país se ha llevado más medallas de oro por año:

#Primero que todo creamos un df distinto para cada tipo de medalla para posteriormente unirlos en un solo df

Gold <-  atheletes %>%
                filter(Medal == "Gold")%>%
                group_by(Year, Season, region) %>%
                summarise(Gold = n())

Silver <-  atheletes %>%
                filter(Medal == "Silver")%>%
                group_by(Year, Season, region) %>%
                summarise(Silver = n())

Bronze <-  atheletes %>%
                filter(Medal == "Bronze")%>%
                group_by(Year, Season, region) %>%
                summarise(Bronze = n())

Total <-  atheletes %>%
                filter(Medal != "<NA>")%>%
                group_by(Year, Season, region) %>%
                summarise(Total = n())

Total <- Total %>%
  left_join(Gold) %>%
  left_join(Silver) %>%
  left_join(Bronze)

#A continuación crearemos un par de tablas donde representemos el número total de medallas de cada país y el número de medallas de oro ganados durante nuestra serie temporal.

Total$Gold[is.na(Total$Gold)] <- 0
Total$Silver[is.na(Total$Silver)] <- 0
Total$Bronze[is.na(Total$Bronze)] <- 0
Total$Total[is.na(Total$Total)] <- 0

Total <- Total %>%
          filter(region %in% c("USA","Russia","Germany","France")) %>%
          filter(Season == "Summer")

p1 <- Total %>%
  ggplot(aes(x = Year, y = Total, group = region)) +
  geom_line(aes(color = region)) +
  geom_point(aes(color = region)) +
  theme_minimal()

p2 <- Total %>%
  ggplot(aes(x = Year, y = Gold, group = region)) +
  geom_line(aes(color = region)) +
  geom_point(aes(color = region)) +
  theme_minimal()

cowplot::plot_grid(p1,p2, ncol = 1, 
          align = 'h', axis = 'l')

De los gráficos anteriores podemos extraer que Francia es de los 4 paises el que menos medallas en total y medallas de oro se ha llevado en los ultimos años. También podemos observar que desde que Rusia entró en los Juegos Olímpicos, arrasaba en todos los deportes hasta 1980 donde emepezó a decaer.

También destacar que hasta día de hoy, Estados Unidos es el lider indiscutible.

Medallistas por paises


Gold_Winners <- atheletes %>%
                     filter(Medal == "Gold") %>%
                     group_by(region) %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally))

Silver_Winners <- atheletes %>%
                     filter(Medal == "Silver") %>%
                     group_by(region) %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally))

Bronze_Winners <- atheletes %>%
                     filter(Medal == "Bronze") %>%
                     group_by(region) %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally))

AllMedals <- atheletes %>%
                     filter(Medal != "<NA>") %>% 
                     group_by(region) %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally))

All <- atheletes %>%
                      group_by(region) %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally)) %>%
                     filter(!region %in% AllMedals$region) %>%
                     mutate(Medal_Tally = "No Medal")

AllMedals$Medal_Tally <- "Medal Winners"

Medal_Tally <- rbind(AllMedals, All)

map.world <- map_data("world")


AllSilver <- atheletes %>%
                      group_by(region) %>%
                      filter(Medal == "Silver") %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally)) %>%
                     filter(!region %in% Gold_Winners$region) %>%
                     mutate(Medal_Tally = "Silver")

AllBronze <- atheletes %>%
                      group_by(region) %>%
                      filter(Medal == "Bronze") %>%
                     summarise(Medal_Tally = length(Medal)) %>%
                     arrange(desc(Medal_Tally)) %>% 
                     mutate(region = str_trim(region),Medal_Tally = str_trim(Medal_Tally)) %>%
                     filter(!(region %in% Gold_Winners$region & region %in% Silver_Winners$region) )%>%
                     mutate(Medal_Tally = "Bronze")

Gold_Winners$Medal_Tally <- "Gold"
Gold_Winners <- Gold_Winners[1:99,]

Medal_Tally <- rbind(Gold_Winners, AllSilver)
Medal_Tally <- rbind(Medal_Tally, AllBronze)

map.world <- map_data("world")

#as.factor(medal_winners$region) %>% levels()

map.world_joined <- left_join(map.world, Medal_Tally, by ='region')

map.world_joined$Medal_Tally[is.na(map.world_joined$Medal_Tally)] <- "No Medal"

ggplot() +
  geom_polygon(data = map.world_joined, aes(x = long, y = lat, group = group, fill = Medal_Tally)) +
  scale_fill_manual(values = c("#cd7f32", "#FFDF00",  "#ff6347", "#808080")) +
  labs(x = " ", y = " ", title = 'Medal winners in the world') +
  theme_minimal() +
  theme(legend.position="bottom")

Análisis más profundo


Count <- atheletes %>%
  group_by(Year, Season, region) %>%
  summarise(NumberOfAthltes = n())

Gold_Winners <- atheletes %>%
                filter(Medal != "<NA>")%>%
                group_by(Year, Season, region) %>%
                summarise(NumberOfMedals = n())

Aggregated <- Count %>% left_join(Gold_Winners, by = c("Year", "Season", "region"))

groupMale <- atheletes %>%
              filter(Sex == "M") %>%
              group_by(Year, Season, region) %>%
              summarise(Number_Of_Men = n())

groupFemale <- atheletes %>%
              filter(Sex == "F") %>%
              group_by(Year, Season, region) %>%
              summarise(Number_Of_Women = n())

group <- groupMale %>%
          left_join(groupFemale) %>%
          mutate(Sex_Ratio = Number_Of_Men/Number_Of_Women)

group$Sex_Ratio[is.na(group$Sex_Ratio)] <- 236

Aggregated <- Aggregated %>%
              left_join(group, by = c("Year", "Season", "region"))

AgeAgg <- atheletes %>%
                group_by(Year, Season, region) %>%
                summarise(MedianAge = median(Age, na.rm = T))

HeightAgg <- atheletes %>%
                group_by(Year, Season, region) %>%
                summarise(MedianHeight = median(Height, na.rm = T))

WeightAgg <- atheletes %>%
                group_by(Year, Season, region) %>%
                summarise(MedianWeight = median(Weight, na.rm = T))

Aggregated <- Aggregated %>%
              left_join(AgeAgg, by = c("Year", "Season", "region"))
Aggregated <- Aggregated %>%
              left_join(HeightAgg, by = c("Year", "Season", "region"))
Aggregated <- Aggregated %>%
              left_join(WeightAgg, by = c("Year", "Season", "region"))

Aggregated$NumberOfMedals[is.na(Aggregated$NumberOfMedals)] <- 0
Aggregated$Sex_Ratio[is.na(Aggregated$Sex_Ratio)] <- 0

p7 <- Aggregated %>% 
        ggplot(aes(x=NumberOfAthltes, y=NumberOfMedals)) +
        geom_point(col="blue")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Number of Athletes", y = "Number of Medals")

ggplotly(p7)

Tal y como podemos observar en este gráfico, a medida que se han ido ampliando las categorias de los Juegos Olímpicos y han aumentado el número de atletas profesionales, también han aumentado el número de medallas repartidas aunque no tanto como lo ha hecho el número de atletas.


p1 <- Aggregated %>% 
        filter(!is.na(Number_Of_Women)) %>%
        ggplot(aes(x=Number_Of_Women, y=NumberOfMedals)) +
        geom_point(col="darkblue")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Number of Female Athletes", y = "Number of Medals")
        
p2 <- Aggregated %>% 
        filter(!is.na(Number_Of_Men)) %>%
        ggplot(aes(x=Number_Of_Men, y=NumberOfMedals)) +
        geom_point(col="red")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Number of Male Athletes", y = "Number of Medals")

cowplot::plot_grid(p1,p2, ncol = 1, 
          align = 'h', axis = 'l')

El número de hombres y el número de mujeres atletas se correlacionan con el número de medallas ganadas por una nación, no obstante el número de mujeres deportistas tiene una correlación menor con el número de medallas ganadas que el número de deportistas masculinos. ¿Qué pasa con la proporción de hombres y mujeres, eso tiene un impacto en la cantidad de medallas ganadas? A continuación lo analizamos.

Ratio de Sexo


p6 <- Aggregated %>% 
        filter(!is.na(Sex_Ratio)) %>%
        ggplot(aes(x=Sex_Ratio, y=NumberOfMedals)) +
        geom_point(col="darkblue")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Sex Ratio", y = "Number of Medals")

ggplotly(p6)

Entonces, la igualdad en el sexo no influye en la cantidad de medallas que gana un país. El contingente de una nación puede estar compuesto completamente por hombres y no importará. Pero, el problema aquí es que si el contingente está compuesto solo por hombres, entonces es bastante obvio que la nación perdería oportunidades de ganar medallas en atletismo femenino. No está de más tener una mezcla de hombres y mujeres en el país.

Edad Media


p5 <- Aggregated %>% 
        filter(!is.na(MedianAge)) %>%
        ggplot(aes(x=MedianAge, y=NumberOfMedals)) +
        geom_point(col="darkblue")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Median Age of the Contingent", y = "Number of Medals")

ggplotly(p5)

Como podemos observar, la edad tampoco afecta la cantidad de medallas que gana un país, esto se debe a que la edad a la que se retiran los atletas profesionales en los distintos juegos difiere bastante.

Peso y Altura Media


p1 <- Aggregated %>% 
        filter(!is.na(MedianHeight)) %>%
        ggplot(aes(x=MedianHeight, y=NumberOfMedals)) +
        geom_point(col="steelblue")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Median Height of the Contingent", y = "Number of Medals")
        
p2 <- Aggregated %>% 
        filter(!is.na(MedianWeight)) %>%
        ggplot(aes(x=MedianWeight, y=NumberOfMedals)) +
        geom_point(col="tomato")  + geom_smooth(method = "lm", se=TRUE, color="black", aes(group=1)) +
        theme_minimal() +
        labs(x = "Median Weight of the Contingent", y = "Number of Medals")

cowplot::plot_grid(p1,p2, ncol = 1, 
          align = 'h', axis = 'l')

Una vez más, la altura y el peso no influyen en el número de medallas que gana el país ya que el peso y altura óptimo de un atleta varia en función del juego en el que este participe, no puede pesar lo mismo un atleta que se dedica al atletismo en la prueba de 100m lisos que los atletas que se dedican a juegos más de fuerza como puede ser la halterofilia.

Bibliografía

Kaggle

Página oficial de los Juegos Olímpicos

Ggplot





Información de mi R-sesión:

- Session info  --------------------------------------------------------------
 hash: flag: United Nations, flower playing cards, flag: Guinea

 setting  value
 version  R version 4.1.1 (2021-08-10)
 os       Windows 10 x64 (build 19042)
 system   x86_64, mingw32
 ui       RTerm
 language (EN)
 collate  Spanish_Spain.1252
 ctype    Spanish_Spain.1252
 tz       Europe/Paris
 date     2022-01-07
 pandoc   2.11.4 @ C:/Program Files/RStudio/bin/pandoc/ (via rmarkdown)

- Packages -------------------------------------------------------------------
 package      * version    date (UTC) lib source
 assertthat     0.2.1      2019-03-21 [1] CRAN (R 4.1.1)
 backports      1.3.0      2021-10-27 [1] CRAN (R 4.1.1)
 broom          0.7.10     2021-10-31 [1] CRAN (R 4.1.1)
 bslib          0.3.1      2021-10-06 [1] CRAN (R 4.1.1)
 cellranger     1.1.0      2016-07-27 [1] CRAN (R 4.1.1)
 cli            3.1.0      2021-10-27 [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)
 countrycode  * 1.3.0      2021-07-15 [1] CRAN (R 4.1.1)
 cowplot        1.1.1      2020-12-30 [1] CRAN (R 4.1.1)
 crayon         1.4.2      2021-10-29 [1] CRAN (R 4.1.1)
 crosstalk      1.2.0      2021-11-04 [1] CRAN (R 4.1.1)
 curl           4.3.2      2021-06-23 [1] CRAN (R 4.1.1)
 data.table     1.14.2     2021-09-27 [1] CRAN (R 4.1.2)
 DBI            1.1.1      2021-01-15 [1] CRAN (R 4.1.1)
 dbplyr         2.1.1      2021-04-06 [1] CRAN (R 4.1.1)
 desc           1.4.0      2021-09-28 [1] CRAN (R 4.1.1)
 details        0.2.1      2020-01-12 [1] CRAN (R 4.1.1)
 digest         0.6.28     2021-09-23 [1] CRAN (R 4.1.1)
 directlabels * 2021.1.13  2021-01-16 [1] CRAN (R 4.1.2)
 dplyr        * 1.0.7      2021-06-18 [1] CRAN (R 4.1.1)
 DT           * 0.19       2021-09-02 [1] CRAN (R 4.1.1)
 ellipsis       0.3.2      2021-04-29 [1] CRAN (R 4.1.1)
 evaluate       0.14       2019-05-28 [1] CRAN (R 4.1.1)
 fansi          0.5.0      2021-05-25 [1] CRAN (R 4.1.1)
 farver         2.1.0      2021-02-28 [1] CRAN (R 4.1.1)
 fastmap        1.1.0      2021-01-25 [1] CRAN (R 4.1.1)
 forcats      * 0.5.1      2021-01-27 [1] CRAN (R 4.1.1)
 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.1)
 ggExtra      * 0.9        2019-08-27 [1] CRAN (R 4.1.2)
 ggplot2      * 3.3.5      2021-06-25 [1] CRAN (R 4.1.1)
 ggthemes     * 4.2.4      2021-01-20 [1] CRAN (R 4.1.1)
 glue           1.5.0      2021-11-07 [1] CRAN (R 4.1.2)
 gridExtra      2.3        2017-09-09 [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)
 highcharter  * 0.8.2      2020-07-26 [1] CRAN (R 4.1.2)
 highr          0.9        2021-04-16 [1] CRAN (R 4.1.1)
 hms            1.1.1      2021-09-26 [1] CRAN (R 4.1.1)
 htmltools      0.5.2      2021-08-25 [1] CRAN (R 4.1.1)
 htmlwidgets    1.5.4      2021-09-08 [1] CRAN (R 4.1.1)
 httpuv         1.6.3      2021-09-09 [1] CRAN (R 4.1.1)
 httr           1.4.2      2020-07-20 [1] CRAN (R 4.1.1)
 igraph         1.2.8      2021-11-07 [1] CRAN (R 4.1.2)
 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)
 klippy       * 0.0.0.9500 2021-11-16 [1] Github (rlesur/klippy@378c247)
 knitr        * 1.36       2021-09-29 [1] CRAN (R 4.1.1)
 labeling       0.4.2      2020-10-20 [1] CRAN (R 4.1.0)
 later          1.3.0      2021-08-18 [1] CRAN (R 4.1.1)
 lattice        0.20-44    2021-05-02 [2] CRAN (R 4.1.1)
 lazyeval       0.2.2      2019-03-15 [1] CRAN (R 4.1.1)
 lifecycle      1.0.1      2021-09-24 [1] CRAN (R 4.1.1)
 lubridate    * 1.8.0      2021-10-07 [1] CRAN (R 4.1.1)
 magrittr       2.0.1      2020-11-17 [1] CRAN (R 4.1.1)
 maps           3.4.0      2021-09-25 [1] CRAN (R 4.1.2)
 Matrix         1.3-4      2021-06-01 [2] CRAN (R 4.1.1)
 mgcv           1.8-36     2021-06-01 [2] CRAN (R 4.1.1)
 mime           0.12       2021-09-28 [1] CRAN (R 4.1.1)
 miniUI         0.1.1.1    2018-05-18 [1] CRAN (R 4.1.1)
 modelr         0.1.8      2020-05-19 [1] CRAN (R 4.1.1)
 munsell        0.5.0      2018-06-12 [1] CRAN (R 4.1.1)
 nlme           3.1-152    2021-02-04 [2] CRAN (R 4.1.1)
 pillar         1.6.4      2021-10-18 [1] CRAN (R 4.1.1)
 pkgconfig      2.0.3      2019-09-22 [1] CRAN (R 4.1.1)
 plotly       * 4.10.0     2021-10-09 [1] CRAN (R 4.1.1)
 png            0.1-7      2013-12-03 [1] CRAN (R 4.1.0)
 promises       1.2.0.1    2021-02-11 [1] CRAN (R 4.1.1)
 purrr        * 0.3.4      2020-04-17 [1] CRAN (R 4.1.1)
 quadprog       1.5-8      2019-11-20 [1] CRAN (R 4.1.1)
 quantmod       0.4.18     2020-12-09 [1] CRAN (R 4.1.1)
 R6             2.5.1      2021-08-19 [1] CRAN (R 4.1.1)
 Rcpp           1.0.7      2021-07-07 [1] CRAN (R 4.1.1)
 readr        * 2.0.2      2021-09-27 [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)
 rlang          0.4.12     2021-10-18 [1] CRAN (R 4.1.1)
 rlist          0.4.6.2    2021-09-03 [1] CRAN (R 4.1.2)
 rmarkdown      2.11       2021-09-14 [1] CRAN (R 4.1.1)
 rprojroot      2.0.2      2020-11-15 [1] CRAN (R 4.1.1)
 rstudioapi     0.13       2020-11-12 [1] CRAN (R 4.1.1)
 rvest          1.0.2      2021-10-16 [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.2.1      2021-11-02 [1] CRAN (R 4.1.1)
 shiny          1.7.1      2021-10-02 [1] CRAN (R 4.1.1)
 stringi        1.7.5      2021-10-04 [1] CRAN (R 4.1.1)
 stringr      * 1.4.0      2019-02-10 [1] CRAN (R 4.1.1)
 tibble       * 3.1.6      2021-11-07 [1] CRAN (R 4.1.2)
 tidyr        * 1.1.4      2021-09-27 [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)
 TTR            0.24.2     2020-09-01 [1] CRAN (R 4.1.1)
 tzdb           0.2.0      2021-10-27 [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)
 viridis      * 0.6.2      2021-10-13 [1] CRAN (R 4.1.1)
 viridisLite  * 0.4.0      2021-04-13 [1] CRAN (R 4.1.1)
 withr          2.4.3      2021-11-30 [1] CRAN (R 4.1.2)
 xfun           0.28       2021-11-04 [1] CRAN (R 4.1.2)
 xml2           1.3.2      2020-04-23 [1] CRAN (R 4.1.1)
 xtable         1.8-4      2019-04-21 [1] CRAN (R 4.1.1)
 xts            0.12.1     2020-09-09 [1] CRAN (R 4.1.1)
 yaml           2.2.1      2020-02-01 [1] CRAN (R 4.1.0)
 zoo            1.8-9      2021-03-09 [1] CRAN (R 4.1.1)

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

------------------------------------------------------------------------------






LS0tDQp0aXRsZTogIkxvcyBKdWVnb3MgT2zDrW1waWNvcyINCnN1YnRpdGxlOiAiUGF1IFBpZXJhIFBhbGFjaW9zKHBhdXBpZXBhQGFsdW1uaS51di5lcykiICMtIHBvbmdvIHTDuiBub21icmUgYWjDrSBwYXJhIHEgYXBhcmV6Y2EgbcOhcyBncmFuZGUgcSBlbCBkZSBsYSBVVg0KYXV0aG9yOiAiVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIg0KZGF0ZTogIkRpY2llbWJyZSBkZSAyMDIxIChhY3R1YWxpemFkbyBlbCBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLSVtLSVZJylgKSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjc3M6ICIuL2Fzc2V0cy9lc3RpbG9fMS5jc3MiDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZSANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMgDQogICAgdG9jX2Zsb2F0OiANCiAgICAgIGNvbGxhcHNlZDogdHJ1ZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQ0KICAgICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSINCiAgICB0aGVtZTogcGFwZXINCiAgICBkZl9wcmludDoga2FibGUNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7ciBwYWNrYWdlcy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGtsaXBweSkgICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShjb3VudHJ5Y29kZSkNCmxpYnJhcnkoaGlnaGNoYXJ0ZXIpDQpsaWJyYXJ5KGRpcmVjdGxhYmVscykNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShEVCkNCmxpYnJhcnkoZ2d0aGVtZXMpDQpsaWJyYXJ5KGdnRXh0cmEpDQoNCg0KYGBgDQoNCmBgYHtyIGNodW5rLXNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGV2YWwgPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgI3Jlc3VsdHMgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgY2FjaGUgPSBGQUxTRSwgY2FjaGUucGF0aCA9ICIvY2FjaGVzLyIsIGNvbW1lbnQgPSAiIz4iLA0KICAgICAgICAgICAgICAgICAgICAgICNmaWcud2lkdGggPSA3LCAjZmlnLmhlaWdodD0gNywgICANCiAgICAgICAgICAgICAgICAgICAgICAjb3V0LndpZHRoID0gNywgb3V0LmhlaWdodCA9IDcsDQogICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLCAgZmlnLnNob3cgPSAiaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFzcCA9IDAuNjI4LCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLmFsaWduID0gImNlbnRlciIpDQprbml0cjo6b3B0c19jaHVuayRzZXQoZGV2ID0gInBuZyIsIGRldi5hcmdzID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKQ0KYGBgDQoNCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KDQpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmBgYA0KDQoNCjxociBjbGFzcz0ibGluZWEtYmxhY2siPg0KDQo8IS0tIEVsIHDDoXJyYWZvIGRlIGFiYWpvIGhhcyBkZSBkZWphcmxvIGNhc2kgaWd1YWwsIHNvbG8gSEFTIGRlIFNVU1RJVFVJUiAicGVyZXpwNDQiIHBvciB0dSB1c3VhcmlvIGRlIEdpdGh1Yi0tPg0KVHJhYmFqbyBlbGFib3JhZG8gcGFyYSBsYSBhc2lnbmF0dXJhICJQcm9ncmFtYWNpw7NuIHkgbWFuZWpvIGRlIGRhdG9zIGVuIGxhIGVyYSBkZWwgQmlnIERhdGEiIGRlIGxhIFVuaXZlcnNpdGF0IGRlIFZhbMOobmNpYSBkdXJhbnRlIGVsIGN1cnNvIDIwMjEtMjAyMi4gRWwgcmVwbyBkZWwgdHJhYmFqbyBlc3TDoSBbYXF1w61dKGh0dHBzOi8vZ2l0aHViLmNvbS9wYXVwaWVyYTIzL3RyYWJham9fQmlnRGF0YSl7dGFyZ2V0PSJfYmxhbmsifS4gDQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gZXhhY3RhbWVudGUgaWd1YWwsIE5PIEhBUyBERSBDQU1CSUFSIE5BREEtLT4NCg0KTGEgcMOhZ2luYSB3ZWIgZGUgbGEgYXNpZ25hdHVyYSB5IGxvcyB0cmFiYWpvcyBkZSBtaXMgY29tcGHDsWVyb3MgcHVlZGVuIHZlcnNlIFthcXXDrV0oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLzA3LXRyYWJham9zLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uDQoNCg0KPGhyIGNsYXNzPSJsaW5lYS1yZWQiPg0KDQojICAqKkludHJvZHVjY2nDs24qKg0KDQo8Y2VudGVyPjxpbWcgc3JjPSJodHRwczovL3VwbG9hZC53aWtpbWVkaWEub3JnL3dpa2lwZWRpYS9jb21tb25zL3RodW1iLzUvNWMvT2x5bXBpY19yaW5nc193aXRob3V0X3JpbXMuc3ZnLzEyMDBweC1PbHltcGljX3JpbmdzX3dpdGhvdXRfcmltcy5zdmcucG5nIiBzdHlsZT0id2lkdGg6IDYwMHB4OyIvPjwvY2VudGVyPg0KDQogIExvcyBKdWVnb3MgT2zDrW1waWNvcyBzb24gbG9zIHByaW5jaXBhbGVzIGV2ZW50b3MgZGVwb3J0aXZvcyBpbnRlcm5hY2lvbmFsZXMgcXVlIGluY2x1eWVuIGNvbXBldGljaW9uZXMgZGVwb3J0aXZhcyBkZSB2ZXJhbm8gZSBpbnZpZXJubyBlbiBsYXMgcXVlIG1pbGVzIGRlIGF0bGV0YXMgZGUgdG9kbyBlbCBtdW5kbyBwYXJ0aWNpcGFuIGVuIHVuYSB2YXJpZWRhZCBkZSBjb21wZXRpY2lvbmVzLiBMb3MgSnVlZ29zIE9sw61tcGljb3Mgc2UgY29uc2lkZXJhbiBsYSBjb21wZXRpY2nDs24gZGVwb3J0aXZhIG3DoXMgaW1wb3J0YW50ZSBkZWwgbXVuZG8gY29uIGxhIHBhcnRpY2lwYWNpw7NuIGRlIG3DoXMgZGUgMjAwIG5hY2lvbmVzLCBlc3RvcyBzZSBjZWxlYnJhbiBjYWRhIGN1YXRybyBhw7FvcywgZG9uZGUgbG9zIEp1ZWdvcyBkZSBWZXJhbm8geSBkZSBJbnZpZXJubyBzZSBhbHRlcm5hbiBjYWRhIGN1YXRybyBhw7FvcywgcGVybyBjb24gZG9zIGHDsW9zIGRlIGRpZmVyZW5jaWEuDQogIA0KICANCiAgTGEgZXZvbHVjacOzbiBkZWwgTW92aW1pZW50byBPbMOtbXBpY28gZHVyYW50ZSBsb3Mgc2lnbG9zIFhYIHkgWFhJIGhhIGRhZG8gbHVnYXIgYSB2YXJpb3MgY2FtYmlvcyBlbiBsb3MgSnVlZ29zIE9sw61tcGljb3MuIEFsZ3Vub3MgZGUgZXN0b3MgYWp1c3RlcyBpbmNsdXllbiBsYSBjcmVhY2nDs24gZGUgbG9zIEp1ZWdvcyBPbMOtbXBpY29zIGRlIEludmllcm5vIHBhcmEgZGVwb3J0ZXMgZGUgbmlldmUgeSBoaWVsbywgbG9zIEp1ZWdvcyBQYXJhbMOtbXBpY29zIHBhcmEgYXRsZXRhcyBjb24gZGlzY2FwYWNpZGFkLCBsb3MgSnVlZ29zIE9sw61tcGljb3MgZGUgbGEgSnV2ZW50dWQgcGFyYSBhdGxldGFzIGRlIDE0IGEgMTggYcOxb3MsIGxvcyBjaW5jbyBKdWVnb3MgQ29udGluZW50YWxlcyAoUGFuYW1lcmljYW5vcywgQWZyaWNhbm9zLCBBc2nDoXRpY29zLCBFdXJvcGEgeSBlbCBQYWPDrWZpY28pIHkgbG9zIEp1ZWdvcyBNdW5kaWFsZXMgZGUgZGVwb3J0ZXMgcXVlIG5vIHNlIGRpc3B1dGFuIGVuIGxvcyBKdWVnb3MgT2zDrW1waWNvcy4gTG9zIERlYWZseW1waWNzIHkgU3BlY2lhbCBPbHltcGljcyB0YW1iacOpbiBjdWVudGFuIGNvbiBlbCByZXNwYWxkbyBkZWwgQ09JLiBFbCBDT0kgaGEgdGVuaWRvIHF1ZSBhZGFwdGFyc2UgYSB1bmEgdmFyaWVkYWQgZGUgYXZhbmNlcyBlY29uw7NtaWNvcywgcG9sw610aWNvcyB5IHRlY25vbMOzZ2ljb3MuIENvbW8gcmVzdWx0YWRvLCBsb3MgSnVlZ29zIE9sw61tcGljb3Mgc2UgaGFuIGFsZWphZG8gZGVsIGFtYXRldXJpc21vIHB1cm8sIGNvbW8gbG8gaW1hZ2luw7MgQ291YmVydGluLCBwYXJhIHBlcm1pdGlyIGxhIHBhcnRpY2lwYWNpw7NuIGRlIGF0bGV0YXMgcHJvZmVzaW9uYWxlcy4gTGEgY3JlY2llbnRlIGltcG9ydGFuY2lhIGRlIGxvcyBtZWRpb3MgZGUgY29tdW5pY2FjacOzbiBnZW5lcsOzIGVsIHByb2JsZW1hIGRlbCBwYXRyb2NpbmlvIGVtcHJlc2FyaWFsIHkgbGEgY29tZXJjaWFsaXphY2nDs24gZGUgbG9zIEp1ZWdvcy4gTGFzIGd1ZXJyYXMgbXVuZGlhbGVzIGxsZXZhcm9uIGEgbGEgY2FuY2VsYWNpw7NuIGRlIGxvcyBKdWVnb3MgZGUgMTkxNiwgMTk0MCB5IDE5NDQuIExvcyBncmFuZGVzIGJvaWNvdHMgZHVyYW50ZSBsYSBHdWVycmEgRnLDrWEgbGltaXRhcm9uIGxhIHBhcnRpY2lwYWNpw7NuIGVuIGxvcyBKdWVnb3MgZGUgMTk4MCB5IDE5ODQuIEVzdGUgw7psdGltbywgc2luIGVtYmFyZ28sIGF0cmFqbyBhIDE0MCBDb21pdMOpcyBPbMOtbXBpY29zIE5hY2lvbmFsZXMsIGxvIHF1ZSBmdWUgdW4gcsOpY29yZCBlbiBlc2UgbW9tZW50by4NCiAgDQpQYXJhIG9idGVuZXIgbcOhcyBpbmZvcm1hY2nDs24sIGNvbnN1bHRlIGxhIFtww6FnaW5hIG9maWNpYWwgZGUgbG9zIEp1ZWdvcyBPbMOtbXBpY29zLl0oaHR0cHM6Ly9vbHltcGljcy5jb20vZW4vKS4NCg0KIyAgICAqKkRhdG9zKiogey50YWJzZXR9DQojIyAgKipFeHRyYWNjacOzbiBkZSBkYXRvcyoqIA0KRXN0ZSBlcyB1biBjb25qdW50byBkZSBkYXRvcyBoaXN0w7NyaWNvcyBzb2JyZSBsb3MgSnVlZ29zIE9sw61tcGljb3MgbW9kZXJub3MsIGluY2x1aWRvcyB0b2RvcyBsb3MgSnVlZ29zIGRlc2RlIEF0ZW5hcyAxODk2IGhhc3RhIFLDrW8gMjAxNi4gRXN0b3MgZGF0b3MgbG9zIGhlIGV4dHJhaWRvIGRlIFtLYWdnbGVdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vKSwgdW5hIGJhc2UgZGUgZGF0b3MgZG9uZGUgc2UgcHVlZGVuIGVuY29udHJhciB1bmEgaW5maW5pZGFkIGRlIGRhdGFmcmFtZXMgY29uIGluZm9ybWFjacOzbiBtdXkgdmFsaW9zLCBkZXNkZSBsYSBjYXJyZXJhIGRlIENyaXN0aWFubyBSb25hbGRvIGVuIG7Dum1lcm9zLCBoYXN0YSBtb2RlbG9zIGRlIFZhbHVlIEludmVzdGluZyBwYXJhIGxhIHZhbG9yYWNpw7NuIGRlIG11Y2hhcyBlbXByZXNhcyBjb3RpemFkYXMuDQoNCkNvbW8gZXN0b3MgZGF0b3MgcGVzYW4gZGVtYXNpYWRvIHBhcmEgcG9uZXJsb3MgZW4gZWwgcmVwb3NpdG9yaW8gZGUgR2l0aHViLCBhIGNvbnRpbnVhY2nDs24gb3MgZGVqbyBlbCAqKltlbmxhY2UgZGUgZGVzY2FyZ2FdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vaGVlc29vMzcvMTIwLXllYXJzLW9mLW9seW1waWMtaGlzdG9yeS1hdGhsZXRlcy1hbmQtcmVzdWx0cy9kb3dubG9hZCkqKg0KDQojIyAqKkPDs2RpZ28qKg0KYGBge3IgZXZhbD1UUlVFLCB3YXJuaW5nPVRSVUV9DQojVmFtb3MgYSBjYXJnYXIgbG9zIGRmDQoNCmF0aGVsZXRlcyA8LSByZWFkLmNzdigiLi9kYXRvcy9hdGhsZXRlX2V2ZW50cy5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRikNCnJlZ2lvbnMgPC0gcmVhZC5jc3YoIi4vZGF0b3Mvbm9jX3JlZ2lvbnMuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQoNCmBgYA0KDQoNCiMgKipBbsOhbGlzaXMgcG9yIFNleG86KioNCiMjIE7Dum1lcm9zIGFwcm94aW1hZG9zOiANCkxhIHByaW1lcmEgcGFydGUgZGUgbnVlc3RybyBhbsOhbGlzaXMgc2Vyw6Egw7p0aWwgcGFyYSBjb21wcmVuZGVyIGPDs21vIGhhbiBldm9sdWNpb25hZG8gbG9zIEp1ZWdvcyBPbMOtbXBpY29zIGEgbG8gbGFyZ28gZGVsIHRpZW1wby4NCmBgYHtyIGV2YWw9IFRSVUUsIHdhcm5pbmc9RkFMU0V9DQpkZiA8LSBhdGhlbGV0ZXMgJT4lDQogIGdyb3VwX2J5KFNlYXNvbiwgU2V4KSAlPiUNCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSAlPiUNCiAgbXV0YXRlKFBlcmNlbnRhZ2UgPSByb3VuZChDb3VudCoxMDAgLyBzdW0oQ291bnQpKSkgDQogIA0KZGYgJT4lICAgDQpnZ3Bsb3QoYWVzKHg9U2Vhc29uLCB5PVBlcmNlbnRhZ2UsIGZpbGwgPSBTZXgpKSArIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5Jyxwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgpKSArDQogICAgICAgIGdndGl0bGUoIlBvcmNlbnRhamUgZGUgSG9tYnJlcyB5IG11amVyZXMgcXVlIHBhcnRpY2lwYW4oMjAwNy0yMDE3KSIpICsNCiAgICAgICAgZ2VvbV9sYWJlbChsYWJlbD1kZiRQZXJjZW50YWdlLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSkpICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpIA0KICAgICAgICANCmBgYA0KDQpEdXJhbnRlIGVsIGludmllcm5vIHkgZWwgdmVyYW5vIGVsIHBvcmNlbnRhamUgeSBsYXMgbXVqZXJlcyBzZSBoYW4gbWFudGVuaWRvIGlndWFsZXMgeWEgcXVlIGFwZW5hcyBzZSBwdWVkZSBvYnNlcnZhciB1bmEgdmFyaWFjacOzbiBlbGV2YWRhLg0KDQojIyBUZW5kZW5jaWEgZGUgcGFydGljaXBhY2nDs246DQoNCiMjIyBUZW5kZW5jaWEgZGUgcGFydGljaXBhY2nDs24gcG9yIGHDsW9zOg0KDQpBIG1lZGlkYSBxdWUgYXZhbnphYmFuIGxvcyBKdWVnb3MgT2zDrW1waWNvcyBhIGxvIGxhcmdvIGRlIGxvcyBhw7FvcywgZWwgbsO6bWVybyBkZSBwZXJzb25hcyBxdWUgcGFydGljaXBhYmFuIGVuIGVsbG9zIGhhYnLDrWEgYXVtZW50YWRvLCBsbyBxdWUgc2lnbmlmaWNhYmEgcXVlIGVsIG7Dum1lcm8gZGUgaG9tYnJlcyB5IG11amVyZXMgcXVlIHBhcnRpY2lwYWJhbiBlbiBsb3MgSnVlZ29zIE9sw61tcGljb3MgY3JlY8OtYS4NCg0KYGBge3IsIGV2YWwgPSBUUlVFLCB3YXJuaW5nPUZBTFNFfQ0KDQpwMSA8LSBhdGhlbGV0ZXMgJT4lDQogIGdyb3VwX2J5KFllYXIsIFNlYXNvbikgJT4lDQogIHN1bW1hcmlzZShOdW1iZXJPZlBhcnRpY2lwYW50cyA9IG4oKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBOdW1iZXJPZlBhcnRpY2lwYW50cywgZ3JvdXAgPSBTZWFzb24pKSArDQogIGdlb21fbGluZShhZXMoY29sb3IgPSBTZWFzb24pKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gU2Vhc29uKSkgKw0KICBsYWJzKHggPSAiQcOxbyIsIHkgPSAiTsO6bWVybyBkZSBwYXJ0aWNpcGFudGVzIiwgdGl0bGUgPSAiTsO6bWVybyBkZSBwYXJ0aWNpcGFudGVzIGVuIGxhcyBvbGltcGlhZGFzIHBvciBhw7FvIikrDQogIHRoZW1lX21pbmltYWwoKQ0KDQpnZ3Bsb3RseShwMSkNCg0KYGBgDQoNCkVsIG7Dum1lcm8gZGUgcGFydGljaXBhbnRlcyBlbiBsb3MgSnVlZ29zIE9sw61tcGljb3MgaGEgY3JlY2lkbyBjb24gZWwgcGFzbyBkZWwgdGllbXBvLiBUYW1iacOpbiBlcyBvYnZpbyBxdWUgZWwgbsO6bWVybyBkZSBwYXJ0aWNpcGFudGVzIGVuIGxvcyBqdWVnb3Mgb2zDrW1waWNvcyBkZSB2ZXJhbm8gZXMgbWF5b3IgcXVlIGVsIGRlIGxvcyBqdWVnb3Mgb2zDrW1waWNvcyBkZSBpbnZpZXJuby4NCg0KDQojIyMgVGVuZGVuY2lhIHBvciByYXRpbyBkZSBzZXhvOg0KYGBge3IsIGV2YWwgPSBUUlVFLCB3YXJuaW5nPUZBTFNFfQ0KZ3JvdXBNYWxlIDwtIGF0aGVsZXRlcyAlPiUNCiAgICAgICAgICAgICAgZmlsdGVyKFNleCA9PSAiTSIpICU+JQ0KICAgICAgICAgICAgICBncm91cF9ieShZZWFyLCBTZWFzb24pICU+JQ0KICAgICAgICAgICAgICBzdW1tYXJpc2UoTnVtYmVyX09mX01lbiA9IG4oKSkNCg0KZ3JvdXBGZW1hbGUgPC0gYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICBmaWx0ZXIoU2V4ID09ICJGIikgJT4lDQogICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsIFNlYXNvbikgJT4lDQogICAgICAgICAgICAgIHN1bW1hcmlzZShOdW1iZXJfT2ZfV29tZW4gPSBuKCkpDQoNCmdyb3VwIDwtIGdyb3VwTWFsZSAlPiUNCiAgICAgICAgICBsZWZ0X2pvaW4oZ3JvdXBGZW1hbGUpICU+JQ0KICAgICAgICAgIG11dGF0ZShTZXhfUmF0aW8gPSBOdW1iZXJfT2ZfTWVuL051bWJlcl9PZl9Xb21lbikNCg0KZ3JvdXAkU2V4X1JhdGlvW2lzLm5hKGdyb3VwJFNleF9SYXRpbyldIDwtIDE3NQ0KDQpwMSA8LSBncm91cCAlPiUNCiAgICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5PSBTZXhfUmF0aW8sIGdyb3VwID0gU2Vhc29uKSkgKw0KICAgIGdlb21fbGluZShhZXMoY29sb3IgPSBTZWFzb24pKSArDQogICAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBTZWFzb24pKSArDQogICAgbGFicyh4ID0gIkHDsW8iLCB5ID0gIlJhdGlvIGRlIHNleG8iLCB0aXRsZSA9ICJSYXRpbyBkZSBzZXhvIGVuIGxhcyBPbGltcGlhZGFzIHBvciBhw7FvcyIpICsNCiAgICB0aGVtZV9taW5pbWFsKCkNCg0KcDIgPC0gZ3JvdXAgJT4lDQogICAgZmlsdGVyKFllYXI+MTkyNykgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeT0gU2V4X1JhdGlvLCBncm91cCA9IFNlYXNvbikpICsNCiAgICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gU2Vhc29uKSkgKw0KICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gU2Vhc29uKSkgKw0KICAgIGxhYnMoeCA9ICJBw7FvIiwgeSA9ICJSYXRpbyBkZSBzZXhvIiwgdGl0bGUgPSAiUmF0aW8gZGUgc2V4byBlbiBsYXMgT2xpbXBpYWRhcyBkZXNwdcOpcyBkZSAxOTI3IikgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQocDEscDIsIG5jb2wgPSAxLCANCiAgICAgICAgICBhbGlnbiA9ICdoJywgYXhpcyA9ICdsJykNCg0KYGBgDQoNCkN1YW5kbyBjb21lbnphcm9uIGxvcyBKdWVnb3MgT2zDrW1waWNvcywgbmluZ3VuYSBtdWplciBwYXJ0aWNpcMOzIGVuIGxvcyBKdWVnb3MgT2zDrW1waWNvcy4gRW4gMTkwMCBsYXMgbXVqZXJlcyBjb21lbnphcm9uIGEgcGFydGljaXBhciBlbiBsb3MgSnVlZ29zIE9sw61tcGljb3MuIEEgbWVkaWRhIHF1ZSBwYXNhcm9uIGxvcyBhw7FvcywgbGEgcHJvcG9yY2nDs24gZGUgc2V4b3MsIGVzIGRlY2lyLCBsYSBwcm9wb3JjacOzbiBkZSBob21icmVzIGEgbXVqZXJlcyBzZSBoaXpvIG3DoXMgcGVxdWXDsWEuIERlc3B1w6lzIGRlIDIwMDAsIGxhIHByb3BvcmNpw7NuIGNvbWVuesOzIGEgbW92ZXJzZSBoYWNpYSAxLCBsbyBxdWUgc2lnbmlmaWNhIHF1ZSBsb3MgSnVlZ29zIE9sw61tcGljb3MgYWhvcmEgc29uIG3DoXMgZGl2ZXJzb3MgZGUgbG8gcXVlIHNvbMOtYW4gc2VyLg0KDQojICAqKkFuw6FsaXNpcyBwb3IgRWRhZDoqKg0KDQpMYSBlZGFkIGVzIGFsZ28gcXVlIHBvZHLDrWEgaGFiZXIgY2FtYmlhZG8gZGVzZGUgcXVlIGNvbWVuemFyb24gbG9zIEp1ZWdvcyBPbMOtbXBpY29zLg0KSGlww7N0ZXNpczogTG9zIHBhcnRpY2lwYW50ZXMgZHVyYW50ZSBsb3MgSnVlZ29zIE9sw61tcGljb3MgZGUgMTkwMCB0ZW7DrWFuIHVuYSBlZGFkIG1lZGlhIG1heW9yIHF1ZSBsYSBlZGFkIG1lZGlhIGRlIGxvcyBwYXJ0aWNpcGFudGVzIGR1cmFudGUgbG9zIDIwMDAuDQoNCiMjICoqQW7DoWxpc2lzIGRlIGVkYWQgcG9yIGRlbnNpZGFkOioqIA0KDQpQcmltZXJvIHF1ZSB0b2RvIHZhbW9zIGEgcXVpdGFyIGxvcyBOQSdzIGRlIG51ZXN0cm8gZGYgcGFyYSBwb2RlciBjYWxjdWxhciBsYSBtZWRpYSBkZSBlZGFkLCB5YSBxdWUgc2kgbm8gZW4gbHVnYXIgZGUgcmVwb3J0YXJub3MgbGEgZWRhZCBub3MgcmVwb3J0YXJpYSB1biBOQSAqY29tbyB1bmEgY2FzYSBkZSBncmFuZGUuKg0KYGBge3J9DQphdGhlbGV0ZXMkQWdlW2lzLm5hKGF0aGVsZXRlcyRBZ2UpXSA8LSBtZWRpYW4oYXRoZWxldGVzJEFnZSwgbmEucm0gPSBUKQ0KYGBgDQoNCkFob3JhIGNhbGN1bGFyZW1vcyBsYSBtZWRpYSBkZSBlZGFkIHBhcmEgZWwgY29uanVudG8gZGUgYXRsZXRhcyBvbGltcGljb3MgeSBsdWVnbyBsYSBtZWRpYSBkZSBlZGFkIHBvciBzZXhvDQoNCkxhIG1lZGlhIGRlIGVkYWQgZGUgbG9zIGF0bGV0YXMgZW4gbG9zIGp1ZWdvcyBvbGltcGljb3MgZXMgMjQNCg0KYGBge3IsIHJlc3VsdHM9J2hvbGQnfQ0KY2F0KCJMYSBtZWRpYSBkZSBlZGFkIGRlIGxvcyBhdGxldGFzIGVuIGxvcyBqdWVnb3Mgb2xpbXBpY29zIGVzIiwgbWVkaWFuKGF0aGVsZXRlcyRBZ2UpKQ0KYGBgDQpMYSBtZWRpYSBkZSBlZGFkIGRlIGxvcyBob21icmVzIGF0bGV0YXMgZW4gbG9zIGp1ZWdvcyBvbGltcGljb3MgZXMgMjUNCmBgYHtyfQ0KY2F0KCJMYSBtZWRpYSBkZSBlZGFkIGRlIGxvcyBob21icmVzIGF0bGV0YXMgZW4gbG9zIGp1ZWdvcyBvbGltcGljb3MgZXMiLCBtZWRpYW4oYXRoZWxldGVzJEFnZVthdGhlbGV0ZXMkU2V4ID09ICJNIl0pKQ0KYGBgDQpMYSBtZWRpYSBkZSBlZGFkIGRlIGxhcyBtdWplcmVzIGF0bGV0YXMgZW4gbG9zIGp1ZWdvcyBvbGltcGljb3MgZXMgMjMNCmBgYHtyfQ0KY2F0KCJMYSBtZWRpYSBkZSBlZGFkIGRlIGxhcyBtdWplcmVzIGF0bGV0YXMgZW4gbG9zIGp1ZWdvcyBvbGltcGljb3MgZXMiLCBtZWRpYW4oYXRoZWxldGVzJEFnZVthdGhlbGV0ZXMkU2V4ID09ICJGIl0pKQ0KYGBgDQoNCkNvbW8gcG9kZW1vcyBvYnNlcnZhciBkZSBsb3MgYW5hbGlzaXMgYW50ZXJpb3JlcywgbGEgZWRhZCBwcm9tZWRpbyBkZSBsYXMgYXRsZXRhcyBmZW1lbmluYXMgZnVlIG1lbm9yIHF1ZSBsYSBlZGFkIHByb21lZGlvIGRlIGxvcyBhdGxldGFzIG1hc2N1bGlub3MuDQoNCmBgYHtyfQ0KIyBTdXN0aXR1aW1vcyBsb3MgTkEncyBjb24gbGEgZWRhZCBtZWRpYSBvYnRlbmlkYS4NCg0KcDEgPC0gYXRoZWxldGVzICU+JQ0KICAgICAgZ2dwbG90KGFlcyh4ID0gQWdlKSkgKw0KICAgICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJ0b21hdG8iKSArDQogICAgICBsYWJzKHggPSAiQcOxbyIsIHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgZWRhZCIpICsNCiAgICAgIHRoZW1lX21pbmltYWwoKQ0KDQpwMiA8LSBhdGhlbGV0ZXMgJT4lDQogICAgICBnZ3Bsb3QoYWVzKHg9QWdlLCBmaWxsPVNleCkpICsNCiAgICAgIGdlb21fZGVuc2l0eShhbHBoYT0wLjQpICsNCiAgICAgIGxhYnMoeCA9ICJBw7FvIiwgdGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBlZGFkIHBvciBTZXhvcyIpICsNCiAgICAgIHRoZW1lX21pbmltYWwoKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQocDEscDIsIG5jb2wgPSAxLCANCiAgICAgICAgICBhbGlnbiA9ICdoJywgYXhpcyA9ICdsJykNCmBgYA0KDQojIyAqKkVkYWQgZGUgbG9zIGF0bGV0YXMgcG9yIGHDsW9zOioqDQoNCmBgYHtyfQ0KYXRoZWxldGVzICU+JQ0KICBncm91cF9ieShZZWFyLCBTZXgpICU+JQ0KICBzdW1tYXJpc2UoTWVkaWFuX0FnZSA9IG1lZGlhbihBZ2UpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IE1lZGlhbl9BZ2UsIEdyb3VwID0gU2V4KSkgKw0KICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gU2V4KSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFNleCkpICsgDQogIGxhYnMoIHggPSAiWWVhciIsIHkgPSAiTWVkYWluIGFnZSBvZiBBdGhsZXRlcyIsIHRpdGxlID0gIk1lZGlhbiBhZ2Ugb2YgTWFsZSBhbmQgRmVtYWxlIGF0aGxldGVzIG92ZXIgdGhlIHllYXJzIikrDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCkxhIG1lZGlhIGRlIGVkYWQgZGUgbG9zIGF0bGV0YXMgbWFzY3VsaW5vcyB5IGZlbWVuaW5vcyBoYSBhdW1lbnRhZG8gZGVzZGUgZWwgMTk4MCB0YWwgeSBjb21vIHBvZGVtb3Mgb2JzZXJ2YXIgZW4gZWwgZ3LDoWZpY28gZGUgYXJyaWJhLg0KDQojICoqQW7DoWxpc2lzIHBvciBlcXVpcG86KioNCg0KTG9zIGVxdWlwb3MgYXF1w60gc2UgcmVmaWVyZW4gYSBsb3MgcGHDrXNlcyB5IGxvcyBkaWZlcmVudGVzIGNsdWJlcyBhdGzDqXRpY29zIHF1ZSBoYW4gcGFydGljaXBhZG8gZW4gbG9zIEp1ZWdvcyBPbMOtbXBpY29zIGEgbG8gbGFyZ28gZGUgbG9zIGHDsW9zLg0KDQoNCmBgYHtyfQ0KY2F0KCJFbCBuw7ptZXJvIHRvdGFsIGRlIGVxdWlwb3MgcXVlIGhhbiBwYXJ0aWNpcGFkbyBlbiBsYXMgb2xpbWlhZGFzIGVzIGRlICIsIGxlbmd0aCh1bmlxdWUoYXRoZWxldGVzJFRlYW0pKSkNCmBgYA0KDQpFbCBuw7ptZXJvIHRvdGFsIGRlIGVxdWlwb3MgcXVlIGhhbiBwYXJ0aWNpcGFkbyBlbiBsYXMgb2xpbWlhZGFzIGVzIGRlIDExODQNCg0KYGBge3J9DQojQWhvcmEgdmFtb3MgYSB1bmlyIGVuIHVuIG1pc21vIGRmIGxvcyBhdGxldGFzIHkgc3UgcmVnacOzbiBkZSBwZXJ0ZW5lbmNpYQ0KYXRoZWxldGVzIDwtIGF0aGVsZXRlcyAlPiUNCiAgICAgICAgICAgICAgbGVmdF9qb2luKHJlZ2lvbnMsIGJ5ID0gIk5PQyIpDQpgYGANCg0KQ29uIGVsIGPDs2RpZ28gcXVlIGVzdGEgb2N1bHRvIGFycmliYSwgYWNhYmFtb3MgZGUgdW5pciBlbCBjb25qdW50byBkZSBkYXRvcyBkZSBsb3MgYXRsZXRhcyBjb24gZWwgY29uanVudG8gZGUgZGF0b3MgZGUgbGFzIHJlZ2lvbmVzLiBNZSBndXN0YXLDrWEgYW5hbGl6YXIgZWwgY29uanVudG8gZGUgZGF0b3MgYmFzYWRvIGVuIGVsIENvbWl0w6kgT2zDrW1waWNvIE5hY2lvbmFsIGVuIGx1Z2FyIGRlIGxvcyBlcXVpcG9zLg0KYGBge3J9DQogIGNhdCgiRWwgbsO6bWVybyB0b3RhbCBkZSBDb21pdMOpcyBPbMOtbXBpY29zIE5hY2lvbmFsZXMgcXVlIGhhbiBwYXJ0aWNpcGFkbyBlbiBsYXMgb2xpbXBpYWRhcyBlcyBkZSIsIGxlbmd0aCh1bmlxdWUoYXRoZWxldGVzJHJlZ2lvbikpKQ0KYGBgDQoNCiJFbCBuw7ptZXJvIHRvdGFsIGRlIENvbWl0w6lzIE9sw61tcGljb3MgTmFjaW9uYWxlcyBxdWUgaGFuIHBhcnRpY2lwYWRvIGVuIGxhcyBvbGltcGlhZGFzIGVzIGRlIDIwNiINCg0KDQpBIGNvbnRpbnVhY2nDs24gdmFtb3MgYSByZXByZXNlbnRhciB1biBncsOhZmljbyBkZSBiYXJyYXMgZG9uZGUgb2JzZXJ2YXJlbW9zIGN1YWxlcyBzb24gbG9zIHBhaXNlcyBjb24gbcOhcyBtZWRhbGxhcyBnYW5hZGFzIGRlIGxhIGhpc3RvcmlhLg0KDQpgYGB7cn0NCmF0aGVsZXRlcyAlPiUNCiAgZmlsdGVyKE1lZGFsICE9ICI8TkE+IikgJT4lDQogIGdyb3VwX2J5KHJlZ2lvbikgJT4lDQogIHN1bW1hcmlzZShNZWRhbF9UYWxseSA9IGxlbmd0aChNZWRhbCkpJT4lDQogIGFycmFuZ2UoZGVzYyhNZWRhbF9UYWxseSkpICU+JQ0KICB1bmdyb3VwKCkgJT4lDQogIG11dGF0ZShyZWdpb24gPSByZW9yZGVyKHJlZ2lvbixNZWRhbF9UYWxseSkpICU+JQ0KICB0b3BfbigxMCkgJT4lDQogIGdncGxvdChhZXMoeCA9IHJlZ2lvbix5ID0gTWVkYWxfVGFsbHkpKSArDQogICAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknLGNvbG91cj0id2hpdGUiLCBmaWxsID0gInRvbWF0byIpICsNCiAgICBnZW9tX3RleHQoYWVzKHggPSByZWdpb24sIHkgPSAuMSwgbGFiZWwgPSBwYXN0ZTAoIigiLHJvdW5kKE1lZGFsX1RhbGx5LDIpLCIpIixzZXA9IiIpKSwNCiAgICAgICAgICAgICAgaGp1c3Q9MCwgdmp1c3Q9LjUsIHNpemUgPSA0LCBjb2xvdXIgPSAnYmxhY2snLA0KICAgICAgICAgICAgICBmb250ZmFjZSA9ICdib2xkJykgKw0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksDQogICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCkpICsNCiAgICBsYWJzKHggPSAnUGHDrXMnLCANCiAgICAgICAgIHkgPSAnTsO6bWVybyBkZSBtZWRhbGxhcycNCiAgICAgICAgICkgKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHRoZW1lX2J3KCkNCmBgYA0KDQpDb21vIHBvZGVtb3Mgb2JzZXJ2YXIgZGVsIGdyw6FmaWNvIHF1ZSB2ZW1vcyBhcnJpYmEsIGxvcyBwYWlzZXMgY29uIG3DoXMgbWVkYWxsYXMgZ2FuYWRhcyBzb246DQoNCi0gRXN0YWRvcyBVbmlkb3MgY29uIHVuIHRvdGFsIGRlIDU2MzcgbWVkYWxsYXMuDQotIFJ1c2lhIGNvbiB1biB0b3RhbCBkZSAzOTQ3IG1lZGFsbGFzLg0KLSBBbGVtYW5pYSBjb24gdW4gdG90YWwgZGUgMzc1NiBtZWRhbGxhcy4NCi0gUmVpbm8gVW5pZG8gY29uIHVuIHRvdGFsIGRlIDIwNjggbWVkYWxsYXMuDQotIEZyYW5jaWEgY29uIHVuIHRvdGFsIGRlIDE3NzcgbWVkYWxsYXMuDQoNCiMjIENvbXBhcmFjacOzbiBkZWwgVG9wIDQgZGUgcGHDrXNlczoNCg0KQSBjb250aW51YWNpw7NuIGNyZWFyZW1vcyBkb3MgZ3LDoWZpY29zIHBhcmEgb2JzZXJ2YXIgcXVlIHBhw61zIGhhIGNvbnNlZ3VpZG8gbcOhcyBtZWRhbGxhcyBwb3IgYcOxbyB5IHF1ZSBwYcOtcyBzZSBoYSBsbGV2YWRvIG3DoXMgbWVkYWxsYXMgZGUgb3JvIHBvciBhw7FvOg0KDQpgYGB7cn0NCiNQcmltZXJvIHF1ZSB0b2RvIGNyZWFtb3MgdW4gZGYgZGlzdGludG8gcGFyYSBjYWRhIHRpcG8gZGUgbWVkYWxsYSBwYXJhIHBvc3Rlcmlvcm1lbnRlIHVuaXJsb3MgZW4gdW4gc29sbyBkZg0KDQpHb2xkIDwtICBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgICAgZmlsdGVyKE1lZGFsID09ICJHb2xkIiklPiUNCiAgICAgICAgICAgICAgICBncm91cF9ieShZZWFyLCBTZWFzb24sIHJlZ2lvbikgJT4lDQogICAgICAgICAgICAgICAgc3VtbWFyaXNlKEdvbGQgPSBuKCkpDQoNClNpbHZlciA8LSAgYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICAgIGZpbHRlcihNZWRhbCA9PSAiU2lsdmVyIiklPiUNCiAgICAgICAgICAgICAgICBncm91cF9ieShZZWFyLCBTZWFzb24sIHJlZ2lvbikgJT4lDQogICAgICAgICAgICAgICAgc3VtbWFyaXNlKFNpbHZlciA9IG4oKSkNCg0KQnJvbnplIDwtICBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgICAgZmlsdGVyKE1lZGFsID09ICJCcm9uemUiKSU+JQ0KICAgICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsIFNlYXNvbiwgcmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UoQnJvbnplID0gbigpKQ0KDQpUb3RhbCA8LSAgYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICAgIGZpbHRlcihNZWRhbCAhPSAiPE5BPiIpJT4lDQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoWWVhciwgU2Vhc29uLCByZWdpb24pICU+JQ0KICAgICAgICAgICAgICAgIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkNCg0KVG90YWwgPC0gVG90YWwgJT4lDQogIGxlZnRfam9pbihHb2xkKSAlPiUNCiAgbGVmdF9qb2luKFNpbHZlcikgJT4lDQogIGxlZnRfam9pbihCcm9uemUpDQoNCiNBIGNvbnRpbnVhY2nDs24gY3JlYXJlbW9zIHVuIHBhciBkZSB0YWJsYXMgZG9uZGUgcmVwcmVzZW50ZW1vcyBlbCBuw7ptZXJvIHRvdGFsIGRlIG1lZGFsbGFzIGRlIGNhZGEgcGHDrXMgeSBlbCBuw7ptZXJvIGRlIG1lZGFsbGFzIGRlIG9ybyBnYW5hZG9zIGR1cmFudGUgbnVlc3RyYSBzZXJpZSB0ZW1wb3JhbC4NCg0KVG90YWwkR29sZFtpcy5uYShUb3RhbCRHb2xkKV0gPC0gMA0KVG90YWwkU2lsdmVyW2lzLm5hKFRvdGFsJFNpbHZlcildIDwtIDANClRvdGFsJEJyb256ZVtpcy5uYShUb3RhbCRCcm9uemUpXSA8LSAwDQpUb3RhbCRUb3RhbFtpcy5uYShUb3RhbCRUb3RhbCldIDwtIDANCg0KVG90YWwgPC0gVG90YWwgJT4lDQogICAgICAgICAgZmlsdGVyKHJlZ2lvbiAlaW4lIGMoIlVTQSIsIlJ1c3NpYSIsIkdlcm1hbnkiLCJGcmFuY2UiKSkgJT4lDQogICAgICAgICAgZmlsdGVyKFNlYXNvbiA9PSAiU3VtbWVyIikNCg0KcDEgPC0gVG90YWwgJT4lDQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBUb3RhbCwgZ3JvdXAgPSByZWdpb24pKSArDQogIGdlb21fbGluZShhZXMoY29sb3IgPSByZWdpb24pKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gcmVnaW9uKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KcDIgPC0gVG90YWwgJT4lDQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBHb2xkLCBncm91cCA9IHJlZ2lvbikpICsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IHJlZ2lvbikpICsNCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSByZWdpb24pKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQocDEscDIsIG5jb2wgPSAxLCANCiAgICAgICAgICBhbGlnbiA9ICdoJywgYXhpcyA9ICdsJykNCg0KDQoNCmBgYA0KDQpEZSBsb3MgZ3LDoWZpY29zIGFudGVyaW9yZXMgcG9kZW1vcyBleHRyYWVyIHF1ZSBGcmFuY2lhIGVzIGRlIGxvcyA0IHBhaXNlcyBlbCBxdWUgbWVub3MgbWVkYWxsYXMgZW4gdG90YWwgeSBtZWRhbGxhcyBkZSBvcm8gc2UgaGEgbGxldmFkbyBlbiBsb3MgdWx0aW1vcyBhw7Fvcy4gVGFtYmnDqW4gcG9kZW1vcyBvYnNlcnZhciBxdWUgZGVzZGUgcXVlIFJ1c2lhIGVudHLDsyBlbiBsb3MgSnVlZ29zIE9sw61tcGljb3MsIGFycmFzYWJhIGVuIHRvZG9zIGxvcyBkZXBvcnRlcyBoYXN0YSAxOTgwIGRvbmRlIGVtZXBlesOzIGEgZGVjYWVyLg0KDQoNClRhbWJpw6luIGRlc3RhY2FyIHF1ZSBoYXN0YSBkw61hIGRlIGhveSwgRXN0YWRvcyBVbmlkb3MgZXMgZWwgbGlkZXIgaW5kaXNjdXRpYmxlLg0KDQojIyBNZWRhbGxpc3RhcyBwb3IgcGFpc2VzDQoNCmBgYHtyLCBldmFsID0gVFJVRSwgd2FybmluZz1GQUxTRX0NCg0KR29sZF9XaW5uZXJzIDwtIGF0aGVsZXRlcyAlPiUNCiAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihNZWRhbCA9PSAiR29sZCIpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShNZWRhbF9UYWxseSA9IGxlbmd0aChNZWRhbCkpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgYXJyYW5nZShkZXNjKE1lZGFsX1RhbGx5KSkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHJlZ2lvbiA9IHN0cl90cmltKHJlZ2lvbiksTWVkYWxfVGFsbHkgPSBzdHJfdHJpbShNZWRhbF9UYWxseSkpDQoNClNpbHZlcl9XaW5uZXJzIDwtIGF0aGVsZXRlcyAlPiUNCiAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihNZWRhbCA9PSAiU2lsdmVyIikgJT4lDQogICAgICAgICAgICAgICAgICAgICBncm91cF9ieShyZWdpb24pICU+JQ0KICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKE1lZGFsX1RhbGx5ID0gbGVuZ3RoKE1lZGFsKSkgJT4lDQogICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKGRlc2MoTWVkYWxfVGFsbHkpKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICBtdXRhdGUocmVnaW9uID0gc3RyX3RyaW0ocmVnaW9uKSxNZWRhbF9UYWxseSA9IHN0cl90cmltKE1lZGFsX1RhbGx5KSkNCg0KQnJvbnplX1dpbm5lcnMgPC0gYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKE1lZGFsID09ICJCcm9uemUiKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KHJlZ2lvbikgJT4lDQogICAgICAgICAgICAgICAgICAgICBzdW1tYXJpc2UoTWVkYWxfVGFsbHkgPSBsZW5ndGgoTWVkYWwpKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgIGFycmFuZ2UoZGVzYyhNZWRhbF9UYWxseSkpICU+JSANCiAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShyZWdpb24gPSBzdHJfdHJpbShyZWdpb24pLE1lZGFsX1RhbGx5ID0gc3RyX3RyaW0oTWVkYWxfVGFsbHkpKQ0KDQpBbGxNZWRhbHMgPC0gYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKE1lZGFsICE9ICI8TkE+IikgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShNZWRhbF9UYWxseSA9IGxlbmd0aChNZWRhbCkpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgYXJyYW5nZShkZXNjKE1lZGFsX1RhbGx5KSkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHJlZ2lvbiA9IHN0cl90cmltKHJlZ2lvbiksTWVkYWxfVGFsbHkgPSBzdHJfdHJpbShNZWRhbF9UYWxseSkpDQoNCkFsbCA8LSBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShNZWRhbF9UYWxseSA9IGxlbmd0aChNZWRhbCkpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgYXJyYW5nZShkZXNjKE1lZGFsX1RhbGx5KSkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHJlZ2lvbiA9IHN0cl90cmltKHJlZ2lvbiksTWVkYWxfVGFsbHkgPSBzdHJfdHJpbShNZWRhbF9UYWxseSkpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKCFyZWdpb24gJWluJSBBbGxNZWRhbHMkcmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShNZWRhbF9UYWxseSA9ICJObyBNZWRhbCIpDQoNCkFsbE1lZGFscyRNZWRhbF9UYWxseSA8LSAiTWVkYWwgV2lubmVycyINCg0KTWVkYWxfVGFsbHkgPC0gcmJpbmQoQWxsTWVkYWxzLCBBbGwpDQoNCm1hcC53b3JsZCA8LSBtYXBfZGF0YSgid29ybGQiKQ0KDQoNCkFsbFNpbHZlciA8LSBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoTWVkYWwgPT0gIlNpbHZlciIpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKE1lZGFsX1RhbGx5ID0gbGVuZ3RoKE1lZGFsKSkgJT4lDQogICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKGRlc2MoTWVkYWxfVGFsbHkpKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICBtdXRhdGUocmVnaW9uID0gc3RyX3RyaW0ocmVnaW9uKSxNZWRhbF9UYWxseSA9IHN0cl90cmltKE1lZGFsX1RhbGx5KSkgJT4lDQogICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoIXJlZ2lvbiAlaW4lIEdvbGRfV2lubmVycyRyZWdpb24pICU+JQ0KICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKE1lZGFsX1RhbGx5ID0gIlNpbHZlciIpDQoNCkFsbEJyb256ZSA8LSBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoTWVkYWwgPT0gIkJyb256ZSIpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKE1lZGFsX1RhbGx5ID0gbGVuZ3RoKE1lZGFsKSkgJT4lDQogICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKGRlc2MoTWVkYWxfVGFsbHkpKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICBtdXRhdGUocmVnaW9uID0gc3RyX3RyaW0ocmVnaW9uKSxNZWRhbF9UYWxseSA9IHN0cl90cmltKE1lZGFsX1RhbGx5KSkgJT4lDQogICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoIShyZWdpb24gJWluJSBHb2xkX1dpbm5lcnMkcmVnaW9uICYgcmVnaW9uICVpbiUgU2lsdmVyX1dpbm5lcnMkcmVnaW9uKSApJT4lDQogICAgICAgICAgICAgICAgICAgICBtdXRhdGUoTWVkYWxfVGFsbHkgPSAiQnJvbnplIikNCg0KR29sZF9XaW5uZXJzJE1lZGFsX1RhbGx5IDwtICJHb2xkIg0KR29sZF9XaW5uZXJzIDwtIEdvbGRfV2lubmVyc1sxOjk5LF0NCg0KTWVkYWxfVGFsbHkgPC0gcmJpbmQoR29sZF9XaW5uZXJzLCBBbGxTaWx2ZXIpDQpNZWRhbF9UYWxseSA8LSByYmluZChNZWRhbF9UYWxseSwgQWxsQnJvbnplKQ0KDQptYXAud29ybGQgPC0gbWFwX2RhdGEoIndvcmxkIikNCg0KI2FzLmZhY3RvcihtZWRhbF93aW5uZXJzJHJlZ2lvbikgJT4lIGxldmVscygpDQoNCm1hcC53b3JsZF9qb2luZWQgPC0gbGVmdF9qb2luKG1hcC53b3JsZCwgTWVkYWxfVGFsbHksIGJ5ID0ncmVnaW9uJykNCg0KbWFwLndvcmxkX2pvaW5lZCRNZWRhbF9UYWxseVtpcy5uYShtYXAud29ybGRfam9pbmVkJE1lZGFsX1RhbGx5KV0gPC0gIk5vIE1lZGFsIg0KDQpnZ3Bsb3QoKSArDQogIGdlb21fcG9seWdvbihkYXRhID0gbWFwLndvcmxkX2pvaW5lZCwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gTWVkYWxfVGFsbHkpKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNjZDdmMzIiLCAiI0ZGREYwMCIsICAiI2ZmNjM0NyIsICIjODA4MDgwIikpICsNCiAgbGFicyh4ID0gIiAiLCB5ID0gIiAiLCB0aXRsZSA9ICdNZWRhbCB3aW5uZXJzIGluIHRoZSB3b3JsZCcpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKQ0KDQpgYGANCg0KIyAgKipBbsOhbGlzaXMgbcOhcyBwcm9mdW5kbyoqDQoNCmBgYHtyfQ0KDQpDb3VudCA8LSBhdGhlbGV0ZXMgJT4lDQogIGdyb3VwX2J5KFllYXIsIFNlYXNvbiwgcmVnaW9uKSAlPiUNCiAgc3VtbWFyaXNlKE51bWJlck9mQXRobHRlcyA9IG4oKSkNCg0KR29sZF9XaW5uZXJzIDwtIGF0aGVsZXRlcyAlPiUNCiAgICAgICAgICAgICAgICBmaWx0ZXIoTWVkYWwgIT0gIjxOQT4iKSU+JQ0KICAgICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsIFNlYXNvbiwgcmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UoTnVtYmVyT2ZNZWRhbHMgPSBuKCkpDQoNCkFnZ3JlZ2F0ZWQgPC0gQ291bnQgJT4lIGxlZnRfam9pbihHb2xkX1dpbm5lcnMsIGJ5ID0gYygiWWVhciIsICJTZWFzb24iLCAicmVnaW9uIikpDQoNCmdyb3VwTWFsZSA8LSBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgIGZpbHRlcihTZXggPT0gIk0iKSAlPiUNCiAgICAgICAgICAgICAgZ3JvdXBfYnkoWWVhciwgU2Vhc29uLCByZWdpb24pICU+JQ0KICAgICAgICAgICAgICBzdW1tYXJpc2UoTnVtYmVyX09mX01lbiA9IG4oKSkNCg0KZ3JvdXBGZW1hbGUgPC0gYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICBmaWx0ZXIoU2V4ID09ICJGIikgJT4lDQogICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsIFNlYXNvbiwgcmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgc3VtbWFyaXNlKE51bWJlcl9PZl9Xb21lbiA9IG4oKSkNCg0KZ3JvdXAgPC0gZ3JvdXBNYWxlICU+JQ0KICAgICAgICAgIGxlZnRfam9pbihncm91cEZlbWFsZSkgJT4lDQogICAgICAgICAgbXV0YXRlKFNleF9SYXRpbyA9IE51bWJlcl9PZl9NZW4vTnVtYmVyX09mX1dvbWVuKQ0KDQpncm91cCRTZXhfUmF0aW9baXMubmEoZ3JvdXAkU2V4X1JhdGlvKV0gPC0gMjM2DQoNCkFnZ3JlZ2F0ZWQgPC0gQWdncmVnYXRlZCAlPiUNCiAgICAgICAgICAgICAgbGVmdF9qb2luKGdyb3VwLCBieSA9IGMoIlllYXIiLCAiU2Vhc29uIiwgInJlZ2lvbiIpKQ0KDQpBZ2VBZ2cgPC0gYXRoZWxldGVzICU+JQ0KICAgICAgICAgICAgICAgIGdyb3VwX2J5KFllYXIsIFNlYXNvbiwgcmVnaW9uKSAlPiUNCiAgICAgICAgICAgICAgICBzdW1tYXJpc2UoTWVkaWFuQWdlID0gbWVkaWFuKEFnZSwgbmEucm0gPSBUKSkNCg0KSGVpZ2h0QWdnIDwtIGF0aGVsZXRlcyAlPiUNCiAgICAgICAgICAgICAgICBncm91cF9ieShZZWFyLCBTZWFzb24sIHJlZ2lvbikgJT4lDQogICAgICAgICAgICAgICAgc3VtbWFyaXNlKE1lZGlhbkhlaWdodCA9IG1lZGlhbihIZWlnaHQsIG5hLnJtID0gVCkpDQoNCldlaWdodEFnZyA8LSBhdGhlbGV0ZXMgJT4lDQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoWWVhciwgU2Vhc29uLCByZWdpb24pICU+JQ0KICAgICAgICAgICAgICAgIHN1bW1hcmlzZShNZWRpYW5XZWlnaHQgPSBtZWRpYW4oV2VpZ2h0LCBuYS5ybSA9IFQpKQ0KDQpBZ2dyZWdhdGVkIDwtIEFnZ3JlZ2F0ZWQgJT4lDQogICAgICAgICAgICAgIGxlZnRfam9pbihBZ2VBZ2csIGJ5ID0gYygiWWVhciIsICJTZWFzb24iLCAicmVnaW9uIikpDQpBZ2dyZWdhdGVkIDwtIEFnZ3JlZ2F0ZWQgJT4lDQogICAgICAgICAgICAgIGxlZnRfam9pbihIZWlnaHRBZ2csIGJ5ID0gYygiWWVhciIsICJTZWFzb24iLCAicmVnaW9uIikpDQpBZ2dyZWdhdGVkIDwtIEFnZ3JlZ2F0ZWQgJT4lDQogICAgICAgICAgICAgIGxlZnRfam9pbihXZWlnaHRBZ2csIGJ5ID0gYygiWWVhciIsICJTZWFzb24iLCAicmVnaW9uIikpDQoNCkFnZ3JlZ2F0ZWQkTnVtYmVyT2ZNZWRhbHNbaXMubmEoQWdncmVnYXRlZCROdW1iZXJPZk1lZGFscyldIDwtIDANCkFnZ3JlZ2F0ZWQkU2V4X1JhdGlvW2lzLm5hKEFnZ3JlZ2F0ZWQkU2V4X1JhdGlvKV0gPC0gMA0KDQpwNyA8LSBBZ2dyZWdhdGVkICU+JSANCiAgICAgICAgZ2dwbG90KGFlcyh4PU51bWJlck9mQXRobHRlcywgeT1OdW1iZXJPZk1lZGFscykpICsNCiAgICAgICAgZ2VvbV9wb2ludChjb2w9ImJsdWUiKSAgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1UUlVFLCBjb2xvcj0iYmxhY2siLCBhZXMoZ3JvdXA9MSkpICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICAgICAgbGFicyh4ID0gIk51bWJlciBvZiBBdGhsZXRlcyIsIHkgPSAiTnVtYmVyIG9mIE1lZGFscyIpDQoNCmdncGxvdGx5KHA3KQ0KDQpgYGANCg0KVGFsIHkgY29tbyBwb2RlbW9zIG9ic2VydmFyIGVuIGVzdGUgZ3LDoWZpY28sIGEgbWVkaWRhIHF1ZSBzZSBoYW4gaWRvIGFtcGxpYW5kbyBsYXMgY2F0ZWdvcmlhcyBkZSBsb3MgSnVlZ29zIE9sw61tcGljb3MgIHkgaGFuIGF1bWVudGFkbyBlbCBuw7ptZXJvIGRlIGF0bGV0YXMgcHJvZmVzaW9uYWxlcywgdGFtYmnDqW4gaGFuIGF1bWVudGFkbyBlbCBuw7ptZXJvIGRlIG1lZGFsbGFzIHJlcGFydGlkYXMgYXVucXVlIG5vIHRhbnRvIGNvbW8gbG8gaGEgaGVjaG8gZWwgbsO6bWVybyBkZSBhdGxldGFzLg0KDQpgYGB7cn0NCg0KcDEgPC0gQWdncmVnYXRlZCAlPiUgDQogICAgICAgIGZpbHRlcighaXMubmEoTnVtYmVyX09mX1dvbWVuKSkgJT4lDQogICAgICAgIGdncGxvdChhZXMoeD1OdW1iZXJfT2ZfV29tZW4sIHk9TnVtYmVyT2ZNZWRhbHMpKSArDQogICAgICAgIGdlb21fcG9pbnQoY29sPSJkYXJrYmx1ZSIpICArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPVRSVUUsIGNvbG9yPSJibGFjayIsIGFlcyhncm91cD0xKSkgKw0KICAgICAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgICAgICBsYWJzKHggPSAiTnVtYmVyIG9mIEZlbWFsZSBBdGhsZXRlcyIsIHkgPSAiTnVtYmVyIG9mIE1lZGFscyIpDQogICAgICAgIA0KcDIgPC0gQWdncmVnYXRlZCAlPiUgDQogICAgICAgIGZpbHRlcighaXMubmEoTnVtYmVyX09mX01lbikpICU+JQ0KICAgICAgICBnZ3Bsb3QoYWVzKHg9TnVtYmVyX09mX01lbiwgeT1OdW1iZXJPZk1lZGFscykpICsNCiAgICAgICAgZ2VvbV9wb2ludChjb2w9InJlZCIpICArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPVRSVUUsIGNvbG9yPSJibGFjayIsIGFlcyhncm91cD0xKSkgKw0KICAgICAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgICAgICBsYWJzKHggPSAiTnVtYmVyIG9mIE1hbGUgQXRobGV0ZXMiLCB5ID0gIk51bWJlciBvZiBNZWRhbHMiKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQocDEscDIsIG5jb2wgPSAxLCANCiAgICAgICAgICBhbGlnbiA9ICdoJywgYXhpcyA9ICdsJykNCg0KYGBgDQoNCkVsIG7Dum1lcm8gZGUgaG9tYnJlcyB5IGVsIG7Dum1lcm8gZGUgbXVqZXJlcyBhdGxldGFzIHNlIGNvcnJlbGFjaW9uYW4gY29uIGVsIG7Dum1lcm8gZGUgbWVkYWxsYXMgZ2FuYWRhcyBwb3IgdW5hIG5hY2nDs24sIG5vIG9ic3RhbnRlIGVsIG7Dum1lcm8gZGUgbXVqZXJlcyBkZXBvcnRpc3RhcyB0aWVuZSB1bmEgY29ycmVsYWNpw7NuIG1lbm9yIGNvbiBlbCBuw7ptZXJvIGRlIG1lZGFsbGFzIGdhbmFkYXMgcXVlIGVsIG7Dum1lcm8gZGUgZGVwb3J0aXN0YXMgbWFzY3VsaW5vcy4gwr9RdcOpIHBhc2EgY29uIGxhIHByb3BvcmNpw7NuIGRlIGhvbWJyZXMgeSBtdWplcmVzLCBlc28gdGllbmUgdW4gaW1wYWN0byBlbiBsYSBjYW50aWRhZCBkZSBtZWRhbGxhcyBnYW5hZGFzPyBBIGNvbnRpbnVhY2nDs24gbG8gYW5hbGl6YW1vcy4NCg0KIyMgUmF0aW8gZGUgU2V4bw0KDQpgYGB7cn0NCg0KcDYgPC0gQWdncmVnYXRlZCAlPiUgDQogICAgICAgIGZpbHRlcighaXMubmEoU2V4X1JhdGlvKSkgJT4lDQogICAgICAgIGdncGxvdChhZXMoeD1TZXhfUmF0aW8sIHk9TnVtYmVyT2ZNZWRhbHMpKSArDQogICAgICAgIGdlb21fcG9pbnQoY29sPSJkYXJrYmx1ZSIpICArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPVRSVUUsIGNvbG9yPSJibGFjayIsIGFlcyhncm91cD0xKSkgKw0KICAgICAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgICAgICBsYWJzKHggPSAiU2V4IFJhdGlvIiwgeSA9ICJOdW1iZXIgb2YgTWVkYWxzIikNCg0KZ2dwbG90bHkocDYpDQoNCg0KYGBgDQoNCkVudG9uY2VzLCBsYSBpZ3VhbGRhZCBlbiBlbCBzZXhvIG5vIGluZmx1eWUgZW4gbGEgY2FudGlkYWQgZGUgbWVkYWxsYXMgcXVlIGdhbmEgdW4gcGHDrXMuIEVsIGNvbnRpbmdlbnRlIGRlIHVuYSBuYWNpw7NuIHB1ZWRlIGVzdGFyIGNvbXB1ZXN0byBjb21wbGV0YW1lbnRlIHBvciBob21icmVzIHkgbm8gaW1wb3J0YXLDoS4gUGVybywgZWwgcHJvYmxlbWEgYXF1w60gZXMgcXVlIHNpIGVsIGNvbnRpbmdlbnRlIGVzdMOhIGNvbXB1ZXN0byBzb2xvIHBvciBob21icmVzLCBlbnRvbmNlcyBlcyBiYXN0YW50ZSBvYnZpbyBxdWUgbGEgbmFjacOzbiBwZXJkZXLDrWEgb3BvcnR1bmlkYWRlcyBkZSBnYW5hciBtZWRhbGxhcyBlbiBhdGxldGlzbW8gZmVtZW5pbm8uIE5vIGVzdMOhIGRlIG3DoXMgdGVuZXIgdW5hIG1lemNsYSBkZSBob21icmVzIHkgbXVqZXJlcyBlbiBlbCBwYcOtcy4NCg0KIyMgRWRhZCBNZWRpYQ0KDQpgYGB7cn0NCg0KcDUgPC0gQWdncmVnYXRlZCAlPiUgDQogICAgICAgIGZpbHRlcighaXMubmEoTWVkaWFuQWdlKSkgJT4lDQogICAgICAgIGdncGxvdChhZXMoeD1NZWRpYW5BZ2UsIHk9TnVtYmVyT2ZNZWRhbHMpKSArDQogICAgICAgIGdlb21fcG9pbnQoY29sPSJkYXJrYmx1ZSIpICArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPVRSVUUsIGNvbG9yPSJibGFjayIsIGFlcyhncm91cD0xKSkgKw0KICAgICAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgICAgICBsYWJzKHggPSAiTWVkaWFuIEFnZSBvZiB0aGUgQ29udGluZ2VudCIsIHkgPSAiTnVtYmVyIG9mIE1lZGFscyIpDQoNCmdncGxvdGx5KHA1KQ0KDQpgYGANCg0KQ29tbyBwb2RlbW9zIG9ic2VydmFyLCBsYSBlZGFkIHRhbXBvY28gYWZlY3RhIGxhIGNhbnRpZGFkIGRlIG1lZGFsbGFzIHF1ZSBnYW5hIHVuIHBhw61zLCBlc3RvIHNlIGRlYmUgYSBxdWUgbGEgZWRhZCBhIGxhIHF1ZSBzZSByZXRpcmFuIGxvcyBhdGxldGFzIHByb2Zlc2lvbmFsZXMgZW4gbG9zIGRpc3RpbnRvcyBqdWVnb3MgZGlmaWVyZSBiYXN0YW50ZS4NCg0KIyMgUGVzbyB5IEFsdHVyYSBNZWRpYQ0KDQpgYGB7cn0NCg0KcDEgPC0gQWdncmVnYXRlZCAlPiUgDQogICAgICAgIGZpbHRlcighaXMubmEoTWVkaWFuSGVpZ2h0KSkgJT4lDQogICAgICAgIGdncGxvdChhZXMoeD1NZWRpYW5IZWlnaHQsIHk9TnVtYmVyT2ZNZWRhbHMpKSArDQogICAgICAgIGdlb21fcG9pbnQoY29sPSJzdGVlbGJsdWUiKSAgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1UUlVFLCBjb2xvcj0iYmxhY2siLCBhZXMoZ3JvdXA9MSkpICsNCiAgICAgICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICAgICAgbGFicyh4ID0gIk1lZGlhbiBIZWlnaHQgb2YgdGhlIENvbnRpbmdlbnQiLCB5ID0gIk51bWJlciBvZiBNZWRhbHMiKQ0KICAgICAgICANCnAyIDwtIEFnZ3JlZ2F0ZWQgJT4lIA0KICAgICAgICBmaWx0ZXIoIWlzLm5hKE1lZGlhbldlaWdodCkpICU+JQ0KICAgICAgICBnZ3Bsb3QoYWVzKHg9TWVkaWFuV2VpZ2h0LCB5PU51bWJlck9mTWVkYWxzKSkgKw0KICAgICAgICBnZW9tX3BvaW50KGNvbD0idG9tYXRvIikgICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2U9VFJVRSwgY29sb3I9ImJsYWNrIiwgYWVzKGdyb3VwPTEpKSArDQogICAgICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgICAgIGxhYnMoeCA9ICJNZWRpYW4gV2VpZ2h0IG9mIHRoZSBDb250aW5nZW50IiwgeSA9ICJOdW1iZXIgb2YgTWVkYWxzIikNCg0KY293cGxvdDo6cGxvdF9ncmlkKHAxLHAyLCBuY29sID0gMSwgDQogICAgICAgICAgYWxpZ24gPSAnaCcsIGF4aXMgPSAnbCcpDQoNCmBgYA0KDQpVbmEgdmV6IG3DoXMsIGxhIGFsdHVyYSB5IGVsIHBlc28gbm8gaW5mbHV5ZW4gZW4gZWwgbsO6bWVybyBkZSBtZWRhbGxhcyBxdWUgZ2FuYSBlbCBwYcOtcyB5YSBxdWUgZWwgcGVzbyB5IGFsdHVyYSDDs3B0aW1vIGRlIHVuIGF0bGV0YSB2YXJpYSBlbiBmdW5jacOzbiBkZWwganVlZ28gZW4gZWwgcXVlIGVzdGUgcGFydGljaXBlLCBubyBwdWVkZSBwZXNhciBsbyBtaXNtbyB1biBhdGxldGEgcXVlIHNlIGRlZGljYSBhbCBhdGxldGlzbW8gZW4gbGEgcHJ1ZWJhIGRlIDEwMG0gbGlzb3MgcXVlIGxvcyBhdGxldGFzIHF1ZSBzZSBkZWRpY2FuIGEganVlZ29zIG3DoXMgZGUgZnVlcnphIGNvbW8gcHVlZGUgc2VyIGxhIGhhbHRlcm9maWxpYS4NCg0KDQoNCiMgKipCaWJsaW9ncmFmw61hKioNCg0KW0thZ2dsZV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS8pDQoNCg0KW1DDoWdpbmEgb2ZpY2lhbCBkZSBsb3MgSnVlZ29zIE9sw61tcGljb3NdKGh0dHBzOi8vb2x5bXBpY3MuY29tL2VuLykNCg0KDQpbR2dwbG90XShodHRwczovL3JwdWJzLmNvbS9kYW5pYmFsbGFyaS9nZ3Bsb3QpDQoNCg0KPGJyPjxicj4NCg0KPGhyIGNsYXNzPSJsaW5lYS1yZWQiPg0KPGhyIGNsYXNzPSJsaW5lYS1yZWQiPg0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkgJT4lIGRldGFpbHM6OmRldGFpbHMoc3VtbWFyeSA9ICdJbmZvcm1hY2nDs24gZGUgbWkgUi1zZXNpw7NuOicpIA0KYGBgDQoNCg0KPGJyPjxicj4NCg0KPGRpdiBjbGFzcz0idG9jaWZ5LWV4dGVuZC1wYWdlIiBkYXRhLXVuaXF1ZT0idG9jaWZ5LWV4dGVuZC1wYWdlIiBzdHlsZT0iaGVpZ2h0OiAwOyI+PC9kaXY+DQo8YnI+PGJyPg0KDQo8ZGl2IGNsYXNzPSJ0b2NpZnktZXh0ZW5kLXBhZ2UiIGRhdGEtdW5pcXVlPSJ0b2NpZnktZXh0ZW5kLXBhZ2UiIHN0eWxlPSJoZWlnaHQ6IDA7Ij48L2Rpdj4NCg==