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
Hoy en día el cine se ha convertido en uno de los medios más populares para la difusión del arte, cultura y sobre todo entretenimiento. Es por eso que en este trabajo vamos a mostrar de una forma algo más detallada los aspectos más relevantes del cine en estos últimos años. Recorreremos a lo largo del proyecto las películas favoritas por la audiencia. Esperamos que este trabajo os sirva para incrementar vuestra cultura cineasta y os incite a ver alguna de las películas mencionadas.
1.- PRIMERA PARTE (10K PELICULAS)
1.1 DATOS A ANALIZAR
A continuación, vamos a mostrar una lista de las 10000 películas con las que vamos a trabajar inicialmente.
peliculas <- top10mil %>%
select(original_title)
reactable(peliculas, defaultPageSize = 8, paginationType = "jump", showPageSizeOptions = TRUE , pageSizeOptions = c ( 10 , 50 , 100, 150, 200, 260 ),defaultColDef = colDef(
align = "center",
minWidth = 70,
headerStyle = list(background = "#FFD700"),
filterable = TRUE), highlight = TRUE, outlined = TRUE,
columns = list(
`Item` = colDef(style = function(value) {
if (value > 0) {
color <- "#F5C710"}
else {
color <- "#B22222"
}
list(color = color, fontWeight = "bold",background = "#CD2626")
})))
1.2 IDIOMA ESTRELLA
En este apartado hemos querido representar cual es el idioma que predomina como lengua original en el paquete de datos con el que estamos trabajando. Claramente, de entre las diez mil películas, el idioma en la que la mayoría de ellas está es en Inglés (sin hacer distinción entre inglés británico o americano).
topmil_pais <- top10mil %>%
group_by(original_language) %>%
mutate(numpelis = sum(NN=n())) %>%
distinct(original_language, numpelis) %>%
arrange(desc(numpelis)) %>%
filter(numpelis>200) %>%
mutate(idioma = case_when(original_language == "en" ~ "Inglés",
original_language == "ja" ~ "Japonés" ,
original_language == "es" ~ "Español",
original_language == "fr" ~ "Francés"))
ggplot(topmil_pais, aes(x = idioma, y = numpelis, fill = idioma)) +
geom_bar(stat="identity") +
scale_fill_manual(values = c("yellow", "white", "blue", "red") ) +
scale_y_continuous( breaks = seq(0, 8000, 1000),
limits = c(0, 8000))
1.3 TOP PELÍCULAS
La siguiente gráfica es probablemente una de las más interesantes del trabajo, ya que básicamente nos muestra las 7 películas con más popularidad. Como podemos observar, el top 1 es Venom: Let There Be Carnage
popularidad <- top10mil %>%
arrange(desc(popularity)) %>%
filter(popularity > 1300)
ggplot(popularidad, aes(x=original_title, y=popularity)) +
geom_bar(stat="identity") +
coord_flip() +
xlab("") +
theme_bw() +
scale_y_continuous( breaks = seq(0, 5500, 500),
limits = c(0, 5500))
1.4 MÁXIMA VOTACIÓN
A continuación mostraremos en un gráfico animado las cuatro películas con una votación más elevada.
votos <- top10mil %>%
arrange(desc(vote_average)) %>%
filter(vote_average > 9.1) %>%
filter(original_language %in% c("zh", "es", "fr"))
votos$original_title <- iconv(votos$original_title, from = "UTF-8", to = "LATIN1")
ggvotos <- ggplot(votos, aes(x = original_title, y = vote_average)) +
geom_point() +
geom_segment( aes(x = original_title, xend = original_title, y = 0, yend = vote_average))
ggplotly(ggvotos)
2.- SEGUNDA PARTE (4K PELICULAS)
2.1 DATOS A ANALIZAR
La idea ahora es mostrar algunos de los apartados vistos anteriormente pero cambiando el paquete de datos usando ahora uno con menos películas y algo más recientes.
Mostramos a contiuación pues, los datos con los que vamos a trabajar ahora.
names(top4mil)[names(top4mil) == 'Movie Title'] <- 'movietitle'
peliculas4 <- top4mil %>%
select(movietitle)
reactable(peliculas4, defaultPageSize = 8, paginationType = "jump", showPageSizeOptions = TRUE , pageSizeOptions = c ( 10 , 50 , 100, 150, 200, 260 ),defaultColDef = colDef(
align = "center",
minWidth = 70,
headerStyle = list(background = "#FFD700"),
filterable = TRUE), highlight = TRUE, outlined = TRUE,
columns = list(
`Item` = colDef(style = function(value) {
if (value > 0) {
color <- "#F5C710"}
else {
color <- "#B22222"
}
list(color = color, fontWeight = "bold",background = "#CD2626")
})))
2.2 MAYOR PIB DOMÉSTICO
En este otro punto ordenamos las películas de forma descendente, las películas que han generado mayor PIB nacional.
names(top4mil)[names(top4mil) == 'Domestic Gross'] <- 'domesticPIB'
PIB <- top4mil %>%
arrange(desc(domesticPIB)) %>%
filter(domesticPIB > 543638042)
ggplot(PIB, aes(x=movietitle, y=domesticPIB)) +
geom_bar(stat="identity") +
coord_flip() +
xlab("") +
theme_bw() +
scale_y_continuous( breaks = seq(0, 80000, 858373000),
limits = c(0, 8583730000))
Como vemos en el gráfico, la pelicula que más ha aportado al PIB doméstico ha sido Star Wars Ep. VII: The Force Awakens
2.3 MAYOR PIB MUNDIAL
Muy parecido al apartado anterior, ahora las distinguimos pero mediante la aportación al PIB mundial.
names(top4mil)[names(top4mil) == 'Worldwide Gross'] <- 'PIB'
PIB <- top4mil %>%
arrange(desc(PIB)) %>%
filter(PIB > 1654367425)
ggplot(PIB, aes(x=movietitle, y=PIB)) +
geom_bar(stat="identity") +
coord_flip() +
xlab("") +
theme_bw() +
scale_y_continuous( breaks = seq(0, 429186500, 858373000),
limits = c(0, 8583730000))
En este otro gráfico podemos observar que las películas que más PIB mundial han aportado han sido, Avatar y Avengers: Endgame, con números bastante similares.
3.- TERCERA PARTE ( MÁS PELIS)
3.1 DATOS A ANALIZAR
Cambiamos ahora otra vez el conjunto de datos con el que vamos a trabajar y disminuimos el paquete a tan solo 118 películas. Pasaremos a analizar otros aspectos distintos de los anteriores.
peliculas <- maspelis %>%
select(Title)
reactable(peliculas, defaultPageSize = 8, paginationType = "jump", showPageSizeOptions = TRUE , pageSizeOptions = c ( 10 , 50 , 100, 150, 200, 260 ),defaultColDef = colDef(
align = "center",
minWidth = 70,
headerStyle = list(background = "#FFD700"),
filterable = TRUE), highlight = TRUE, outlined = TRUE,
columns = list(
`Item` = colDef(style = function(value) {
if (value > 0) {
color <- "#F5C710"}
else {
color <- "#B22222"
}
list(color = color, fontWeight = "bold",background = "#CD2626")
})))
3.2 GÉNERO DE LAS PELÍCULAS
categorias <- maspelis %>%
group_by(Genre1) %>%
mutate(numeroxgenero = sum(NN=n())) %>%
distinct(Genre1, numeroxgenero) %>%
arrange(desc(numeroxgenero))
ggplot(categorias, aes(x = Genre1, y = numeroxgenero, fill = Genre1)) +
geom_bar(stat="identity") +
scale_fill_manual(values = c("pink", "black", "purple", "red", "yellow", "green", "brown", "grey") ) +
scale_y_continuous( breaks = seq(0, 29, 6),
limits = c(0, 29))
Hemos querido representar con este gráfico tan colorido, los géneros de las películas. Podríamos decir que hay muchas más películas de acción y drama que de los otros géneros. Es cierto que es aquí en este conjunto de datos que se da así, pero si cogiésemos todas las películas que existen, las proporciones serían parecidas ya que son los géneros que más venden y más gustan a la mayoría de la población.
3.3 DURACIÓN PELÍCULAS
duration <- maspelis %>%
group_by(Runtime) %>%
mutate(sameduration = sum(NN=n())) %>%
distinct(Runtime, sameduration, Title) %>%
filter(Runtime >0) %>%
filter(Runtime > 166) %>%
filter(Runtime < 9) %>%
arrange(desc(Runtime))
grafduration <- ggplot (duration, aes(x = Title, y = Runtime)) + geom_bar(stat = "identity", fill = "steelblue")
grafduration + labs(title = "Gráfico: Duración de las películas",
subtitle = "(diferenciando por año)",
x = "Películas",
y = "Duración",
color = "Especie de lirio")
A través de este gráfico vemos las películas que más duran. En este top 3 están: - Interstellar (un peliculón, vale la pena la duración) - El hobbit (para gustos colores yo no la he visto) - El lobo de Wall Street, bastante conocida y famosa, con una duración de 3horas.
4.- CUARTA PARTE ( AÚN MÁS PELIS)
Con este cuarto y último paquete de datos que vamos a utilizar en este trabajo, vamos a mostrar la recaudación bruta de las películas en los Estados Unidos.
recaud <- aunmaspelis %>%
select(movie_name, us_grossMillions) %>%
head(us_grossMillions, n = 10)%>%
group_by(movie_name, us_grossMillions) %>%
arrange(desc(us_grossMillions))
recaud
movie_name
|
us_grossMillions
|
Avengers: Endgame
|
858.37000
|
Joker
|
335.45000
|
Knives Out
|
165.36000
|
1917
|
159.23000
|
Once Upon a Time… in Hollywood
|
142.50000
|
Little Women
|
108.10000
|
The Ten Commandments
|
93.74000
|
The Gentlemen
|
69.04371
|
Parasite
|
53.37000
|
The Shawshank Redemption
|
28.34000
|
wordcloud2(data=recaud, size=0.35)
En este gráfico interactivo se muestran las películas con más recaudación con un tamaño más grande y a medida que los títulos se hacen más pequeños significa que la recaudación es menor. Si mantenemos el cursor encima de los títulos de las películas nos dice exactamente el importe de la recaudación bruta. Destacaríamos sin duda Avengers: End Game y seguidamente Joker.
LS0tDQp0aXRsZTogIlRPUCBQZWxpY3VsYXMiDQpzdWJ0aXRsZTogIkFMQkEgRVNURUxBIEdBUkNJQSAoYWxlc2dhcjNAYWx1bW5pLnV2LmVzKSIgIy0gcG9uZ28gdMO6IG5vbWJyZSBhaMOtIHBhcmEgcSBhcGFyZXpjYSBtw6FzIGdyYW5kZSBxIGVsIGRlIGxhIFVWDQphdXRob3I6ICJVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEiDQpkYXRlOiAiRGljaWVtYnJlIGRlIDIwMjEgKGFjdHVhbGl6YWRvIGVsIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVknKWApIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgICNjc3M6ICIuL2Fzc2V0cy9teV9jc3NfZmlsZS5jc3MiDQogICAgdGhlbWU6IHBhcGVyDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZSANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMgDQogICAgdG9jX2Zsb2F0OiANCiAgICAgIGNvbGxhcHNlZDogdHJ1ZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQ0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQouY29sdW1ucyB7ZGlzcGxheTpmbGV4O30NCmgxLnRpdGxlIHtmb250LXNpemU6IDUwIHB4O2NvbG9yOiAjMDAwMDAwfQ0KaDEge2NvbG9yOiMwYTBhMGE7IGZvbnQtc2l6ZTogMzBweCA7Zm9udC1mYW1pbHk6IEFyaWFsIEJsYWNrfQ0KaDJ7Y29sb3I6ICMwYTBhMGE7IGZvbnQtc2l6ZTogMjBweDsgZm9udC1mYW1pbHk6IEFyaWFsIEJsYWNrfQ0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6ICM3M2VmZmF9DQphIHtjb2xvcjogIzAxMDEwMTt9DQoubGlzdC1ncm91cC1pdGVtLmFjdGl2ZSwgLmxpc3QtZ3JvdXAtaXRlbS5hY3RpdmU6Zm9jdXMsIC5saXN0LWdyb3VwLWl0ZW0uYWN0aXZlOmhvdmVyIHsNCiAgICB6LWluZGV4OiAyOw0KICAgIGNvbG9yOiA7DQogICAgYmFja2dyb3VuZC1jb2xvcjogI2M0MzQyZDsNCiAgICBib3JkZXItY29sb3I6IHBhbGVyZWQ7DQp9DQoubmF2LXBpbGxzID4gbGkuYWN0aXZlID4gYSwgLm5hdi1waWxscyA+IGxpLmFjdGl2ZSA+IGE6aG92ZXIsIC5uYXYtcGlsbHMgPiBsaS5hY3RpdmUgPiANCmBgYA0KDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocmVhY3RhYmxlKQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpsaWJyYXJ5KGhyYnJ0aGVtZXMpDQpsaWJyYXJ5KHBhdGNod29yaykNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeSh3b3JkY2xvdWQyKQ0KbGlicmFyeSh3ZWJzaG90KQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkoc3FsZGYpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikgDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KGdnVGhlbWVBc3Npc3QpDQoNCg0KdG9wMTBtaWwgPC0gcmlvOjppbXBvcnQoIi4vZGF0b3MvVE9QMTAwME1PVklFUy5jc3YiKQ0KdG9wNG1pbCA8LSByaW86OmltcG9ydCgiLi9kYXRvcy9UT1A0MDAwTU9WSUVTLmNzdiIpDQptYXNwZWxpcyA8LSByaW86OmltcG9ydCgiLi9kYXRvcy9JTURCLmNzdiIpDQphdW5tYXNwZWxpcyA8LSByaW86OmltcG9ydCgiLi9kYXRvcy9tb3ZpZXNfSU1EQi5jc3YiKQ0KDQoNCmBgYA0KDQoNCg0KDQoNCmBgYHtyIG9wdGlvbnMtc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAjLSBwYXJhIHF1aXRhciBsYSBub3RhY2nDs24gY2llbnTDrWZpY2ENCm9wdGlvbnMoInlhbWwuZXZhbC5leHByIiA9IFRSVUUpIA0KYGBgDQoNCg0KYGBge3Iga2xpcHB5LCBlY2hvID0gRkFMU0V9DQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoInRvcCIsICJyaWdodCIpKSAjLSByZW1vdGVzOjppbnN0YWxsX2dpdGh1Yigicmxlc3VyL2tsaXBweSIpDQpgYGANCg0KDQo8aHIgY2xhc3M9ImxpbmVhLWJsYWNrIj4NCg0KPCEtLSBFbCBww6FycmFmbyBkZSBhYmFqbyBoYXMgZGUgZGVqYXJsbyBjYXNpIGlndWFsLCBzb2xvIEhBUyBkZSBTVVNUSVRVSVIgInBlcmV6cDQ0IiBwb3IgdHUgdXN1YXJpbyBkZSBHaXRodWItLT4NClRyYWJham8gZWxhYm9yYWRvIHBhcmEgbGEgYXNpZ25hdHVyYSAiUHJvZ3JhbWFjacOzbiB5IG1hbmVqbyBkZSBkYXRvcyBlbiBsYSBlcmEgZGVsIEJpZyBEYXRhIiBkZSBsYSBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEgZHVyYW50ZSBlbCBjdXJzbyAyMDIxLTIwMjIuIEVsIHJlcG8gZGVsIHRyYWJham8gZXN0w6EgW2FxdcOtXShodHRwczovL2dpdGh1Yi5jb20vYWxiYWVzdGVsYTE0L3RyYWJham9fQmlnRGF0YSl7dGFyZ2V0PSJfYmxhbmsifS4gDQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gZXhhY3RhbWVudGUgaWd1YWwsIE5PIEhBUyBERSBDQU1CSUFSIE5BREEtLT4NCg0KTGEgcMOhZ2luYSB3ZWIgZGUgbGEgYXNpZ25hdHVyYSB5IGxvcyB0cmFiYWpvcyBkZSBtaXMgY29tcGHDsWVyb3MgcHVlZGVuIHZlcnNlIFthcXXDrV0oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLzA3LXRyYWJham9zLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uDQoNCg0KPGhyIGNsYXNzPSJsaW5lYS1yZWQiPg0KDQoNCiMgKipJTlRST0RVQ0NJw5NOKioNCg0KSG95IGVuIGTDrWEgZWwgY2luZSBzZSBoYSBjb252ZXJ0aWRvIGVuIHVubyBkZSBsb3MgbWVkaW9zIG3DoXMgcG9wdWxhcmVzIHBhcmEgbGEgZGlmdXNpw7NuIGRlbCBhcnRlLCBjdWx0dXJhIHkgc29icmUgdG9kbyBlbnRyZXRlbmltaWVudG8uIEVzIHBvciBlc28gcXVlIGVuIGVzdGUgdHJhYmFqbyB2YW1vcyBhIG1vc3RyYXIgZGUgdW5hIGZvcm1hIGFsZ28gbcOhcyBkZXRhbGxhZGEgbG9zIGFzcGVjdG9zIG3DoXMgcmVsZXZhbnRlcyBkZWwgY2luZSBlbiBlc3RvcyDDumx0aW1vcyBhw7Fvcy4gUmVjb3JyZXJlbW9zIGEgbG8gbGFyZ28gZGVsIHByb3llY3RvIGxhcyBwZWzDrWN1bGFzIGZhdm9yaXRhcyBwb3IgbGEgYXVkaWVuY2lhLg0KRXNwZXJhbW9zIHF1ZSBlc3RlIHRyYWJham8gb3Mgc2lydmEgcGFyYSBpbmNyZW1lbnRhciB2dWVzdHJhIGN1bHR1cmEgY2luZWFzdGEgeSBvcyBpbmNpdGUgYSB2ZXIgYWxndW5hIGRlIGxhcyBwZWzDrWN1bGFzIG1lbmNpb25hZGFzLg0KDQojICoqMS4tIFBSSU1FUkEgUEFSVEUgKigxMEsgUEVMSUNVTEFTKSoqKg0KDQojIyAxLjEgREFUT1MgQSBBTkFMSVpBUiANCg0KQSBjb250aW51YWNpw7NuLCB2YW1vcyBhIG1vc3RyYXIgdW5hIGxpc3RhIGRlIGxhcyAxMDAwMCBwZWzDrWN1bGFzIGNvbiBsYXMgcXVlIHZhbW9zIGEgdHJhYmFqYXIgaW5pY2lhbG1lbnRlLg0KDQoNCmBgYHtyfQ0KcGVsaWN1bGFzIDwtIHRvcDEwbWlsICU+JQ0Kc2VsZWN0KG9yaWdpbmFsX3RpdGxlKQ0KcmVhY3RhYmxlKHBlbGljdWxhcywgZGVmYXVsdFBhZ2VTaXplID0gIDgsICBwYWdpbmF0aW9uVHlwZSA9ICJqdW1wIiwgc2hvd1BhZ2VTaXplT3B0aW9ucyA9ICBUUlVFICwgcGFnZVNpemVPcHRpb25zID0gIGMgKCAxMCAsIDUwICwgMTAwLCAxNTAsIDIwMCwgMjYwICksZGVmYXVsdENvbERlZiA9IGNvbERlZigNCiAgICBhbGlnbiA9ICJjZW50ZXIiLA0KICAgIG1pbldpZHRoID0gNzAsDQogICAgaGVhZGVyU3R5bGUgPSBsaXN0KGJhY2tncm91bmQgPSAiI0ZGRDcwMCIpLA0KICAgIGZpbHRlcmFibGUgPSBUUlVFKSwgIGhpZ2hsaWdodCA9IFRSVUUsIG91dGxpbmVkID0gVFJVRSwNCiAgICBjb2x1bW5zID0gbGlzdCgNCiAgYEl0ZW1gID0gY29sRGVmKHN0eWxlID0gZnVuY3Rpb24odmFsdWUpIHsNCiAgICBpZiAodmFsdWUgPiAwKSB7DQogICAgICBjb2xvciA8LSAiI0Y1QzcxMCJ9DQogICAgICBlbHNlIHsNCiAgICAgIGNvbG9yIDwtICIjQjIyMjIyIg0KICAgIH0NCiAgICBsaXN0KGNvbG9yID0gY29sb3IsIGZvbnRXZWlnaHQgPSAiYm9sZCIsYmFja2dyb3VuZCA9ICIjQ0QyNjI2IikNCiAgfSkpKQ0KYGBgDQoNCg0KDQoNCg0KDQojIyAxLjIgSURJT01BIEVTVFJFTExBDQoNCkVuIGVzdGUgYXBhcnRhZG8gaGVtb3MgcXVlcmlkbyByZXByZXNlbnRhciBjdWFsIGVzIGVsIGlkaW9tYSBxdWUgcHJlZG9taW5hIGNvbW8gbGVuZ3VhIG9yaWdpbmFsIGVuIGVsIHBhcXVldGUgZGUgZGF0b3MgY29uIGVsIHF1ZSBlc3RhbW9zIHRyYWJhamFuZG8uIENsYXJhbWVudGUsIGRlIGVudHJlIGxhcyBkaWV6IG1pbCBwZWzDrWN1bGFzLCBlbCBpZGlvbWEgZW4gbGEgcXVlIGxhIG1heW9yw61hIGRlIGVsbGFzIGVzdMOhIGVzIGVuIEluZ2zDqXMgKHNpbiBoYWNlciBkaXN0aW5jacOzbiBlbnRyZSBpbmdsw6lzIGJyaXTDoW5pY28gbyBhbWVyaWNhbm8pLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnRvcG1pbF9wYWlzIDwtIHRvcDEwbWlsICU+JQ0KICBncm91cF9ieShvcmlnaW5hbF9sYW5ndWFnZSkgICU+JSAgDQogICBtdXRhdGUobnVtcGVsaXMgPSBzdW0oTk49bigpKSkgJT4lDQogIGRpc3RpbmN0KG9yaWdpbmFsX2xhbmd1YWdlLCBudW1wZWxpcykgJT4lIA0KICBhcnJhbmdlKGRlc2MobnVtcGVsaXMpKSAlPiUgDQogIGZpbHRlcihudW1wZWxpcz4yMDApICU+JSANCiAgbXV0YXRlKGlkaW9tYSA9IGNhc2Vfd2hlbihvcmlnaW5hbF9sYW5ndWFnZSA9PSAiZW4iIH4gIkluZ2zDqXMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbF9sYW5ndWFnZSA9PSAiamEiIH4gIkphcG9uw6lzIiAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxfbGFuZ3VhZ2UgPT0gImVzIiB+ICJFc3Bhw7FvbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxfbGFuZ3VhZ2UgPT0gImZyIiB+ICJGcmFuY8OpcyIpKQ0KICANCmdncGxvdCh0b3BtaWxfcGFpcywgYWVzKHggPSBpZGlvbWEsIHkgPSBudW1wZWxpcywgZmlsbCA9IGlkaW9tYSkpICsgIA0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygieWVsbG93IiwgIndoaXRlIiwgImJsdWUiLCAicmVkIikgKSArDQogIHNjYWxlX3lfY29udGludW91cyggYnJlYWtzID0gc2VxKDAsIDgwMDAsIDEwMDApLA0KICAgIGxpbWl0cyA9IGMoMCwgODAwMCkpDQogDQpgYGANCg0KDQojIyAxLjMgVE9QIFBFTMONQ1VMQVMNCg0KTGEgc2lndWllbnRlIGdyw6FmaWNhIGVzIHByb2JhYmxlbWVudGUgdW5hIGRlIGxhcyBtw6FzIGludGVyZXNhbnRlcyBkZWwgdHJhYmFqbywgeWEgcXVlIGLDoXNpY2FtZW50ZSBub3MgbXVlc3RyYSBsYXMgNyBwZWzDrWN1bGFzIGNvbiBtw6FzIHBvcHVsYXJpZGFkLiBDb21vIHBvZGVtb3Mgb2JzZXJ2YXIsIGVsIHRvcCAxIGVzICoqVmVub206IExldCBUaGVyZSBCZSBDYXJuYWdlKioNCg0KDQoNCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnBvcHVsYXJpZGFkIDwtIHRvcDEwbWlsICU+JSANCiAgYXJyYW5nZShkZXNjKHBvcHVsYXJpdHkpKSAlPiUgDQogIGZpbHRlcihwb3B1bGFyaXR5ID4gMTMwMCkNCiANCg0KICBnZ3Bsb3QocG9wdWxhcmlkYWQsIGFlcyh4PW9yaWdpbmFsX3RpdGxlLCB5PXBvcHVsYXJpdHkpKSArDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB4bGFiKCIiKSArDQogICAgdGhlbWVfYncoKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMoIGJyZWFrcyA9IHNlcSgwLCA1NTAwLCA1MDApLA0KICAgIGxpbWl0cyA9IGMoMCwgNTUwMCkpDQpgYGANCg0KIVtWZW5vbTogTGV0IFRoZXJlIEJlIENhcm5hZ2VdKC4vaW1hZ2VuZXMvdmVub20uanBnKSANCg0KDQojIyAxLjQgTcOBWElNQSBWT1RBQ0nDk04NCg0KQSBjb250aW51YWNpw7NuIG1vc3RyYXJlbW9zIGVuIHVuIGdyw6FmaWNvIGFuaW1hZG8gbGFzIGN1YXRybyBwZWzDrWN1bGFzIGNvbiB1bmEgdm90YWNpw7NuIG3DoXMgZWxldmFkYS4NCg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCnZvdG9zIDwtIHRvcDEwbWlsICU+JSANCiAgYXJyYW5nZShkZXNjKHZvdGVfYXZlcmFnZSkpICU+JSANCiAgZmlsdGVyKHZvdGVfYXZlcmFnZSA+IDkuMSkgJT4lIA0KICBmaWx0ZXIob3JpZ2luYWxfbGFuZ3VhZ2UgJWluJSBjKCJ6aCIsICJlcyIsICJmciIpKQ0KDQp2b3RvcyRvcmlnaW5hbF90aXRsZSA8LSBpY29udih2b3RvcyRvcmlnaW5hbF90aXRsZSwgZnJvbSA9ICJVVEYtOCIsIHRvID0gIkxBVElOMSIpDQoNCmdndm90b3MgPC0gZ2dwbG90KHZvdG9zLCBhZXMoeCA9IG9yaWdpbmFsX3RpdGxlLCB5ID0gdm90ZV9hdmVyYWdlKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3NlZ21lbnQoIGFlcyh4ID0gb3JpZ2luYWxfdGl0bGUsIHhlbmQgPSBvcmlnaW5hbF90aXRsZSwgeSA9IDAsIHllbmQgPSB2b3RlX2F2ZXJhZ2UpKQ0KDQpnZ3Bsb3RseShnZ3ZvdG9zKQ0KDQpgYGANCg0KDQohW0TDrWFzIGRlIENBTkdSRUJVUkdFUlNdKC4vaW1hZ2VuZXMvYm9iZXNwb25qYTEucG5nKSAhW0Vib2xhIFpvbWJpZXNdKC4vaW1hZ2VuZXMvZWJvbGEuanBnKSANCg0KDQoNCjxociBjbGFzcz0ibGluZWEtcmVkIj4NCg0KIyAqKjIuLSBTRUdVTkRBIFBBUlRFICooNEsgUEVMSUNVTEFTKSoqKg0KDQojIyAyLjEgREFUT1MgQSBBTkFMSVpBUg0KDQpMYSBpZGVhIGFob3JhIGVzIG1vc3RyYXIgYWxndW5vcyBkZSBsb3MgYXBhcnRhZG9zIHZpc3RvcyBhbnRlcmlvcm1lbnRlIHBlcm8gY2FtYmlhbmRvIGVsIHBhcXVldGUgZGUgZGF0b3MgdXNhbmRvIGFob3JhIHVubyBjb24gbWVub3MgcGVsw61jdWxhcyB5IGFsZ28gbcOhcyByZWNpZW50ZXMuDQoNCk1vc3RyYW1vcyBhIGNvbnRpdWFjacOzbiBwdWVzLCBsb3MgZGF0b3MgY29uIGxvcyBxdWUgdmFtb3MgYSB0cmFiYWphciBhaG9yYS4NCg0KYGBge3J9DQpuYW1lcyh0b3A0bWlsKVtuYW1lcyh0b3A0bWlsKSA9PSAnTW92aWUgVGl0bGUnXSA8LSAnbW92aWV0aXRsZScNCg0KDQoNCnBlbGljdWxhczQgPC0gdG9wNG1pbCAlPiUNCnNlbGVjdChtb3ZpZXRpdGxlKQ0KcmVhY3RhYmxlKHBlbGljdWxhczQsIGRlZmF1bHRQYWdlU2l6ZSA9ICA4LCAgcGFnaW5hdGlvblR5cGUgPSAianVtcCIsIHNob3dQYWdlU2l6ZU9wdGlvbnMgPSAgVFJVRSAsIHBhZ2VTaXplT3B0aW9ucyA9ICBjICggMTAgLCA1MCAsIDEwMCwgMTUwLCAyMDAsIDI2MCApLGRlZmF1bHRDb2xEZWYgPSBjb2xEZWYoDQogICAgYWxpZ24gPSAiY2VudGVyIiwNCiAgICBtaW5XaWR0aCA9IDcwLA0KICAgIGhlYWRlclN0eWxlID0gbGlzdChiYWNrZ3JvdW5kID0gIiNGRkQ3MDAiKSwNCiAgICBmaWx0ZXJhYmxlID0gVFJVRSksICBoaWdobGlnaHQgPSBUUlVFLCBvdXRsaW5lZCA9IFRSVUUsDQogICAgY29sdW1ucyA9IGxpc3QoDQogIGBJdGVtYCA9IGNvbERlZihzdHlsZSA9IGZ1bmN0aW9uKHZhbHVlKSB7DQogICAgaWYgKHZhbHVlID4gMCkgew0KICAgICAgY29sb3IgPC0gIiNGNUM3MTAifQ0KICAgICAgZWxzZSB7DQogICAgICBjb2xvciA8LSAiI0IyMjIyMiINCiAgICB9DQogICAgbGlzdChjb2xvciA9IGNvbG9yLCBmb250V2VpZ2h0ID0gImJvbGQiLGJhY2tncm91bmQgPSAiI0NEMjYyNiIpDQogIH0pKSkNCg0KYGBgDQoNCg0KIyMgMi4yIE1BWU9SIFBJQiBET03DiVNUSUNPDQoNCkVuIGVzdGUgb3RybyBwdW50byBvcmRlbmFtb3MgbGFzIHBlbMOtY3VsYXMgZGUgZm9ybWEgZGVzY2VuZGVudGUsIGxhcyBwZWzDrWN1bGFzIHF1ZSBoYW4gZ2VuZXJhZG8gbWF5b3IgUElCIG5hY2lvbmFsLg0KDQoNCmBgYHtyfQ0KbmFtZXModG9wNG1pbClbbmFtZXModG9wNG1pbCkgPT0gJ0RvbWVzdGljIEdyb3NzJ10gPC0gJ2RvbWVzdGljUElCJw0KDQpQSUIgPC0gdG9wNG1pbCAlPiUgDQogIGFycmFuZ2UoZGVzYyhkb21lc3RpY1BJQikpICU+JSANCiAgZmlsdGVyKGRvbWVzdGljUElCID4gNTQzNjM4MDQyKQ0KIA0KDQogIGdncGxvdChQSUIsIGFlcyh4PW1vdmlldGl0bGUsIHk9ZG9tZXN0aWNQSUIpKSArDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB4bGFiKCIiKSArDQogICAgdGhlbWVfYncoKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMoIGJyZWFrcyA9IHNlcSgwLCA4MDAwMCwgODU4MzczMDAwKSwNCiAgICBsaW1pdHMgPSBjKDAsIDg1ODM3MzAwMDApKQ0KDQpgYGANCg0KDQoNCg0KDQpDb21vIHZlbW9zIGVuIGVsIGdyw6FmaWNvLCBsYSBwZWxpY3VsYSBxdWUgbcOhcyBoYSBhcG9ydGFkbyBhbCBQSUIgZG9tw6lzdGljbyBoYSBzaWRvICoqU3RhciBXYXJzIEVwLiBWSUk6IFRoZSBGb3JjZSBBd2FrZW5zKioNCg0KIVtTdGFyIFdhcnMgRXAuIFZJSTogVGhlIEZvcmNlIEF3YWtlbnNdKC4vaW1hZ2VuZXMvc3RhcndhcnMxLmpwZykgICAgDQoNCg0KIyMgMi4zIE1BWU9SIFBJQiBNVU5ESUFMDQoNCk11eSBwYXJlY2lkbyBhbCBhcGFydGFkbyBhbnRlcmlvciwgYWhvcmEgbGFzIGRpc3Rpbmd1aW1vcyBwZXJvIG1lZGlhbnRlIGxhIGFwb3J0YWNpw7NuIGFsIFBJQiBtdW5kaWFsLg0KDQpgYGB7cn0NCm5hbWVzKHRvcDRtaWwpW25hbWVzKHRvcDRtaWwpID09ICdXb3JsZHdpZGUgR3Jvc3MnXSA8LSAnUElCJw0KDQpQSUIgPC0gdG9wNG1pbCAlPiUgDQogIGFycmFuZ2UoZGVzYyhQSUIpKSAlPiUgDQogIGZpbHRlcihQSUIgPiAJMTY1NDM2NzQyNSkNCiANCg0KICBnZ3Bsb3QoUElCLCBhZXMoeD1tb3ZpZXRpdGxlLCB5PVBJQikpICsNCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHhsYWIoIiIpICsNCiAgICB0aGVtZV9idygpICsNCiAgICAgIHNjYWxlX3lfY29udGludW91cyggYnJlYWtzID0gc2VxKDAsIDQyOTE4NjUwMCwgODU4MzczMDAwKSwNCiAgICBsaW1pdHMgPSBjKDAsIDg1ODM3MzAwMDApKQ0KDQoNCmBgYA0KDQoNCg0KDQpFbiBlc3RlIG90cm8gZ3LDoWZpY28gcG9kZW1vcyBvYnNlcnZhciBxdWUgbGFzIHBlbMOtY3VsYXMgcXVlIG3DoXMgUElCIG11bmRpYWwgaGFuIGFwb3J0YWRvIGhhbiBzaWRvLCAqKkF2YXRhcioqIHkgKipBdmVuZ2VyczogRW5kZ2FtZSoqLCBjb24gbsO6bWVyb3MgYmFzdGFudGUgc2ltaWxhcmVzLg0KDQohW0F2YXRhcl0oLi9pbWFnZW5lcy9hdmF0YXIxLmpwZykgIVtBdmVuZ2VyczogRW5kZ2FtZV0oLi9pbWFnZW5lcy9hdmVuZ2Vycy5qcGcpDQoNCg0KDQojICoqMy4tIFRFUkNFUkEgUEFSVEUgKiggTcOBUyBQRUxJUykqKioNCg0KDQojIyAzLjEgREFUT1MgQSBBTkFMSVpBUg0KDQpDYW1iaWFtb3MgYWhvcmEgb3RyYSB2ZXogZWwgY29uanVudG8gZGUgZGF0b3MgY29uIGVsIHF1ZSB2YW1vcyBhIHRyYWJhamFyIHkgZGlzbWludWltb3MgZWwgcGFxdWV0ZSBhIHRhbiBzb2xvIDExOCBwZWzDrWN1bGFzLiBQYXNhcmVtb3MgYSBhbmFsaXphciBvdHJvcyBhc3BlY3RvcyBkaXN0aW50b3MgZGUgbG9zIGFudGVyaW9yZXMuDQoNCg0KYGBge3J9DQpwZWxpY3VsYXMgPC0gbWFzcGVsaXMgJT4lDQpzZWxlY3QoVGl0bGUpDQpyZWFjdGFibGUocGVsaWN1bGFzLCBkZWZhdWx0UGFnZVNpemUgPSAgOCwgIHBhZ2luYXRpb25UeXBlID0gImp1bXAiLCBzaG93UGFnZVNpemVPcHRpb25zID0gIFRSVUUgLCBwYWdlU2l6ZU9wdGlvbnMgPSAgYyAoIDEwICwgNTAgLCAxMDAsIDE1MCwgMjAwLCAyNjAgKSxkZWZhdWx0Q29sRGVmID0gY29sRGVmKA0KICAgIGFsaWduID0gImNlbnRlciIsDQogICAgbWluV2lkdGggPSA3MCwNCiAgICBoZWFkZXJTdHlsZSA9IGxpc3QoYmFja2dyb3VuZCA9ICIjRkZENzAwIiksDQogICAgZmlsdGVyYWJsZSA9IFRSVUUpLCAgaGlnaGxpZ2h0ID0gVFJVRSwgb3V0bGluZWQgPSBUUlVFLA0KICAgIGNvbHVtbnMgPSBsaXN0KA0KICBgSXRlbWAgPSBjb2xEZWYoc3R5bGUgPSBmdW5jdGlvbih2YWx1ZSkgew0KICAgIGlmICh2YWx1ZSA+IDApIHsNCiAgICAgIGNvbG9yIDwtICIjRjVDNzEwIn0NCiAgICAgIGVsc2Ugew0KICAgICAgY29sb3IgPC0gIiNCMjIyMjIiDQogICAgfQ0KICAgIGxpc3QoY29sb3IgPSBjb2xvciwgZm9udFdlaWdodCA9ICJib2xkIixiYWNrZ3JvdW5kID0gIiNDRDI2MjYiKQ0KICB9KSkpDQpgYGANCg0KIyMgMy4yIEfDiU5FUk8gREUgTEFTIFBFTMONQ1VMQVMNCg0KYGBge3J9DQpjYXRlZ29yaWFzIDwtIG1hc3BlbGlzICU+JQ0KICBncm91cF9ieShHZW5yZTEpICAlPiUgIA0KICAgbXV0YXRlKG51bWVyb3hnZW5lcm8gPSBzdW0oTk49bigpKSkgJT4lDQogIGRpc3RpbmN0KEdlbnJlMSwgbnVtZXJveGdlbmVybykgJT4lIA0KICBhcnJhbmdlKGRlc2MobnVtZXJveGdlbmVybykpICANCg0KICANCmdncGxvdChjYXRlZ29yaWFzLCBhZXMoeCA9IEdlbnJlMSwgeSA9IG51bWVyb3hnZW5lcm8sIGZpbGwgPSBHZW5yZTEpKSArICANCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInBpbmsiLCAiYmxhY2siLCAicHVycGxlIiwgInJlZCIsICJ5ZWxsb3ciLCAiZ3JlZW4iLCAiYnJvd24iLCAiZ3JleSIpICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoIGJyZWFrcyA9IHNlcSgwLCAyOSwgNiksDQogICAgbGltaXRzID0gYygwLCAyOSkpDQoNCmBgYA0KDQpIZW1vcyBxdWVyaWRvIHJlcHJlc2VudGFyIGNvbiBlc3RlIGdyw6FmaWNvIHRhbiBjb2xvcmlkbywgbG9zIGfDqW5lcm9zIGRlIGxhcyBwZWzDrWN1bGFzLiBQb2Ryw61hbW9zIGRlY2lyIHF1ZSBoYXkgbXVjaGFzIG3DoXMgcGVsw61jdWxhcyBkZSBhY2Npw7NuIHkgZHJhbWEgcXVlIGRlIGxvcyBvdHJvcyBnw6luZXJvcy4gRXMgY2llcnRvIHF1ZSBlcyBhcXXDrSBlbiBlc3RlIGNvbmp1bnRvIGRlIGRhdG9zIHF1ZSBzZSBkYSBhc8OtLCBwZXJvIHNpIGNvZ2nDqXNlbW9zIHRvZGFzIGxhcyBwZWzDrWN1bGFzIHF1ZSBleGlzdGVuLCBsYXMgcHJvcG9yY2lvbmVzIHNlcsOtYW4gcGFyZWNpZGFzIHlhIHF1ZSBzb24gbG9zIGfDqW5lcm9zIHF1ZSBtw6FzIHZlbmRlbiB5IG3DoXMgZ3VzdGFuIGEgbGEgbWF5b3LDrWEgZGUgbGEgcG9ibGFjacOzbi4NCg0KIyMgMy4zIERVUkFDScOTTiBQRUzDjUNVTEFTDQoNCmBgYHtyfQ0KZHVyYXRpb24gPC0gbWFzcGVsaXMgJT4lDQogIGdyb3VwX2J5KFJ1bnRpbWUpICU+JQ0KICBtdXRhdGUoc2FtZWR1cmF0aW9uID0gc3VtKE5OPW4oKSkpICU+JQ0KICBkaXN0aW5jdChSdW50aW1lLCBzYW1lZHVyYXRpb24sIFRpdGxlKSAlPiUNCiAgZmlsdGVyKFJ1bnRpbWUgPjApICU+JQ0KICBmaWx0ZXIoUnVudGltZSA+IDE2NikgJT4lDQogIGZpbHRlcihSdW50aW1lIDwgOSkgJT4lDQogIGFycmFuZ2UoZGVzYyhSdW50aW1lKSkgDQogDQoNCg0KDQoNCg0KDQpncmFmZHVyYXRpb24gPC0gZ2dwbG90IChkdXJhdGlvbiwgYWVzKHggPSBUaXRsZSwgeSA9IFJ1bnRpbWUpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInN0ZWVsYmx1ZSIpDQpncmFmZHVyYXRpb24gKyBsYWJzKHRpdGxlID0gIkdyw6FmaWNvOiBEdXJhY2nDs24gZGUgbGFzIHBlbMOtY3VsYXMiLA0KICAgICAgIHN1YnRpdGxlID0gIihkaWZlcmVuY2lhbmRvIHBvciBhw7FvKSIsDQogICAgICAgeCA9ICJQZWzDrWN1bGFzIiwNCiAgICAgICB5ID0gIkR1cmFjacOzbiIsDQogICAgICAgY29sb3IgPSAiRXNwZWNpZSBkZSBsaXJpbyIpDQogIA0KICANCg0KYGBgDQoNCkEgdHJhdsOpcyBkZSBlc3RlIGdyw6FmaWNvIHZlbW9zIGxhcyBwZWzDrWN1bGFzIHF1ZSBtw6FzIGR1cmFuLiBFbiBlc3RlIHRvcCAzIGVzdMOhbjoNCi0gSW50ZXJzdGVsbGFyICoodW4gcGVsaWN1bMOzbiwgdmFsZSBsYSBwZW5hIGxhIGR1cmFjacOzbikqDQotIEVsIGhvYmJpdCAqKHBhcmEgZ3VzdG9zIGNvbG9yZXMgeW8gbm8gbGEgaGUgdmlzdG8pKg0KLSAqKkVsIGxvYm8gZGUgV2FsbCBTdHJlZXQqKiwgYmFzdGFudGUgY29ub2NpZGEgeSBmYW1vc2EsIGNvbiB1bmEgZHVyYWNpw7NuIGRlIDNob3Jhcy4NCg0KIVtUaGUgV29sZiBvZiBXYWxsIFN0cmVldF0oLi9pbWFnZW5lcy9sb2JvLmpwZykNCg0KDQoNCiMgKio0Li0gQ1VBUlRBIFBBUlRFICooIEHDmk4gTcOBUyBQRUxJUykqKioNCg0KQ29uIGVzdGUgY3VhcnRvIHkgw7psdGltbyBwYXF1ZXRlIGRlIGRhdG9zIHF1ZSB2YW1vcyBhIHV0aWxpemFyIGVuIGVzdGUgdHJhYmFqbywgdmFtb3MgYSBtb3N0cmFyIGxhIHJlY2F1ZGFjacOzbiBicnV0YSBkZSBsYXMgcGVsw61jdWxhcyBlbiBsb3MgRXN0YWRvcyBVbmlkb3MuDQoNCg0KYGBge3J9DQpyZWNhdWQgPC0gYXVubWFzcGVsaXMgJT4lDQogIHNlbGVjdChtb3ZpZV9uYW1lLCB1c19ncm9zc01pbGxpb25zKSAlPiUNCiAgaGVhZCh1c19ncm9zc01pbGxpb25zLCBuID0gMTApJT4lDQogIGdyb3VwX2J5KG1vdmllX25hbWUsIHVzX2dyb3NzTWlsbGlvbnMpICU+JQ0KICBhcnJhbmdlKGRlc2ModXNfZ3Jvc3NNaWxsaW9ucykpDQoNCnJlY2F1ZA0KDQoNCndvcmRjbG91ZDIoZGF0YT1yZWNhdWQsIHNpemU9MC4zNSkNCg0KDQpgYGANCg0KRW4gZXN0ZSBncsOhZmljbyBpbnRlcmFjdGl2byBzZSBtdWVzdHJhbiBsYXMgcGVsw61jdWxhcyBjb24gbcOhcyByZWNhdWRhY2nDs24gY29uIHVuIHRhbWHDsW8gbcOhcyBncmFuZGUgeSBhIG1lZGlkYSBxdWUgbG9zIHTDrXR1bG9zIHNlIGhhY2VuIG3DoXMgcGVxdWXDsW9zIHNpZ25pZmljYSBxdWUgbGEgcmVjYXVkYWNpw7NuIGVzIG1lbm9yLiBTaSBtYW50ZW5lbW9zIGVsIGN1cnNvciBlbmNpbWEgZGUgbG9zIHTDrXR1bG9zIGRlIGxhcyBwZWzDrWN1bGFzIG5vcyBkaWNlIGV4YWN0YW1lbnRlIGVsIGltcG9ydGUgZGUgbGEgcmVjYXVkYWNpw7NuIGJydXRhLiBEZXN0YWNhcsOtYW1vcyBzaW4gZHVkYSAqKkF2ZW5nZXJzOiBFbmQgR2FtZSoqIHkgc2VndWlkYW1lbnRlICoqSm9rZXIqKi4NCg0KDQoNCg0KDQoNCg0KDQojICBCSUJMSU9HUkFGw41BDQoNCg0KDQoNCi0gW0VubGFjZSBhIGxhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmFdKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIxLTIyLXdlYi9pbmRleC5odG1sKQ0KDQotIFtFbmxhY2UgZ2FsZXJpYSBkZSBncsOhZmljb3MgZGUgZ2dwbG90Ml0oaHR0cHM6Ly93d3cuci1ncmFwaC1nYWxsZXJ5LmNvbS8pDQoNCi0gW1R1dG9yaWFsZXMgZGUgbGEgYXNpZ25hdHVyYV0oaHR0cHM6Ly9wZXJlenA0NC5naXRodWIuaW8vaW50cm8tZHMtMjEtMjItd2ViLzA0LXR1dG9yaWFsZXMuaHRtbCkNCg0KLSBbRW5sYWNlIGEgbGEgcMOhZ2luYSB3ZWIgZGUgZ2dhbmltYXRlXShodHRwczovL2dnYW5pbWF0ZS5jb20vKQ0KDQo=