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