Name: Rupa Barua ID: s3681672
Growing up I always used to play or watch Pokemon series. So, I have decided to use a pokemon dataset(3) for my project, where the data was collected from several different websites (1,2). It includes data of 721 Pokemon and is based on the pokemon games (NOT pokemon cards or Pokemon Go). The attributes involved are used for calculating how much damage an attack will do in the games. My objective is to be able to answer questions like:
What is the most common type of pokemon in this database?
Compare attributes like Health points (HP), Attack, Defense, speed across all types.
Are there any correlation or any best fit line among any two attributes?
Also, to use the correlation to justify two hypothesis:
The more health points a pokemon has, the stronger their attack power is.
The faster the pokemon, the greater the defense.
Section 1
We first start by loading our dataset into R, and have a look on how the dataset is structured.
library(tidyverse)
library(magrittr)
library(ggcorrplot)
library(ggplot2)
pokemon <- read_csv("Pokemon.csv")
Parsed with column specification:
cols(
`#` = [32mcol_double()[39m,
Name = [31mcol_character()[39m,
`Type 1` = [31mcol_character()[39m,
`Type 2` = [31mcol_character()[39m,
Total = [32mcol_double()[39m,
HP = [32mcol_double()[39m,
Attack = [32mcol_double()[39m,
Defense = [32mcol_double()[39m,
`Sp. Atk` = [32mcol_double()[39m,
`Sp. Def` = [32mcol_double()[39m,
Speed = [32mcol_double()[39m,
Generation = [32mcol_double()[39m,
Legendary = [33mcol_logical()[39m
)
head(pokemon)
Notice, that the column names contain mixture of upper and lowercases and have spaces in between, for our coding convenience we change them all to lowercases, and get rid of the spaces.
There are six generations of pokemon in the pokemon universe, and in order to explore the generations, we factor each generation as a level.
pokemon %<>% rename(
no = '#',
type1 = `Type 1`,
type2 = `Type 2`,
spatk = `Sp. Atk`,
spdef = `Sp. Def`
)
names(pokemon) <- tolower(names(pokemon))
pokemon$generation <- factor(pokemon$generation, levels = c(6,5,4,3,2,1))
Now that we know all the data types, and have changed the column names, let’s see what are the different types of pokemon existing in this dataset.
# Primary types
unique(pokemon$type1)
[1] "Grass" "Fire" "Water" "Bug" "Normal" "Poison"
[7] "Electric" "Ground" "Fairy" "Fighting" "Psychic" "Rock"
[13] "Ghost" "Ice" "Dragon" "Dark" "Steel" "Flying"
Each pokemon must belong to one or more types (Hence, type1 and type2). Not many pokemon have dual types, but to keep all the data, the null values were not removed from the type2 column.
#secondary types
unique(pokemon$type2)
[1] "Poison" NA "Flying" "Dragon" "Ground" "Fairy"
[7] "Grass" "Fighting" "Psychic" "Steel" "Ice" "Rock"
[13] "Dark" "Water" "Electric" "Fire" "Ghost" "Bug"
[19] "Normal"
In the next section, we try to plot the most common type of pokemon (Type1). According to the plot below, the most common type is “Water”, and the least common being “Flying”.
g <- ggplot(pokemon, aes(type1,fill= type1))
g + geom_bar()+ theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

As mentioned in the beginning, some pokemon have dual types, so it is not surprising that the “NA” bar has the highest count, but the second highest, or in this case the accurate, most common type2 will be “flying”, which means, most pokemon have a second “flying” personality.
Different hues are used to distinguish between each type so that the target audience can understand clearly.
g <- ggplot(pokemon, aes(type2,fill= type2))
g + geom_bar()+ theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

Let’s explore, how the different types of pokemon and their quantities are distributed all over the six generations. Only “type1” column was chosen to demonstrate this point, as not all pokemon have a type2.
# Number of Pokémon of each primary type per generation
ggplot(pokemon, aes(x=type1, fill=generation)) +
geom_bar() +
labs(x="Generation", y="Number of Pokémon",
title="Number of Pokémon of each primary type per generation") +
theme_bw() +
theme(axis.text.x=element_text(angle=45, hjust=1))

For this plot, a stacked bar plot was chosen to be able to compare which generation dominates which type. According to the plot above, Generation 1 and 3 have the most number of water pokemon, and there are only flying pokemon existing in generation 5 and 6. Fairy type pokemon only came in plenty in generation 6, and in Generation 5, the distribution of the overall quantity on all types are almost consistent.
The legendary status of a pokemon makes the pokemon rare, and powerful. A bar plot was chosen to display which generation has the most legendary pokemon in their midst.
According to our plot, it is Generation 3.
df2<- filter(pokemon, pokemon$legendary==TRUE)
ggplot(df2, aes(x=generation, fill=legendary)) +
geom_bar(position="dodge") +
labs(x="Generation", y="Number of Pokémon",
title="Number of Legendary Pokémon per generation") +
theme_bw()

Section 2
Some grouped boxplots were plotted for each feature/attribute segmented by Pokémon to see how the attributes are across different types. From the box plots we can observe that:
par(oma=c(2,2,2,2))
pokemon %>%
ggplot(aes(x=type1,y=spatk, fill=type1)) +
geom_boxplot()+ theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

pokemon %>%
ggplot(aes(x=type1,y=spdef, fill=type1)) +
geom_boxplot() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

pokemon %>%
ggplot(aes(x=type1,y=attack, fill=type1)) +
geom_boxplot() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

pokemon %>%
ggplot(aes(x=type1,y=defense, fill=type1)) +
geom_boxplot() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

pokemon %>%
ggplot(aes(x=type1,y=hp, fill=type1)) +
geom_boxplot() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

Dragon Type Pokemon have an advantage across most statistics. Steel Type Pokemon have an advantage over other types in Defense and Flying type has an advantage over other in Attack. Flying Pokémon have a significant speed advantage as well.
Section 3
Now, to investigate correlation statistics, we use multivariate plots, using all types(Type1) of pokemon, and investigating attributes like basic attack and defense powers, with the speed and health points of each pokemon.
Our first hypothesis is: The more health points a pokemon has, the stronger their attack power is.
To investigate this case, we use a scatter plot with a regression line fitted between two attributes : “Hp” and “Attack”.
library(plotly)
p1 <- plot_ly(data = pokemon, x = ~hp, y = ~attack,
color = ~type1, type = "scatter", mode = "markers",
colors = "RdYlBu", hoverinfo = "text") %>%
layout(yaxis = list(zeroline = FALSE, title = "Attack"),
xaxis = list(zeroline = FALSE, title = "Hp")) %>%
add_trace(mode = 'lines',x = ~hp,
y = fitted(lm(pokemon$attack~ pokemon$hp))
)
p1
For the plot above, we can see that the health point of a pokemon and the attack power of a pokemon are collinear to each other. Which indicates, the more the health points, the stronger their attacks are. The blue part (for water type pokemon) of the graph is distinct and most vivid in this graph supports our hypothesis, hence we fail to reject the null hypothesis.
Our second hypothesis is: The faster the pokemon, the greater the defense.
To investigate this hypothesis, we use a similar scatter plot, only this time, it is “Speed” vs “Defence”
library(plotly)
p2 <- plot_ly(data = pokemon, x = ~speed, y = ~defense,
color = ~type1, type = "scatter", mode = "markers",
colors = "RdYlBu", hoverinfo = "text") %>%
layout(yaxis = list(zeroline = FALSE, title = "Defense"),
xaxis = list(zeroline = FALSE, title = "Speed")) %>%
add_trace(mode = 'lines',x = ~speed,
y = fitted(lm(pokemon$defense~ pokemon$speed))
)
p2
Unfortunately, the plot above shows a straight line stating there is no correlation between the two attributes. Thus, our null hypothesis has been rejected.
Summary
We looked into what are the different type of pokemon are there, what are the most common ones, in terms of types and in generations, and how the different features interact with different types all across the different types. Different hues were selected in every plot to distinguish among the different plots, and plots like bar-graph and scatter plots were used in each case, which were able to catch and display the issue clearly instead of any kind of deception.
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpOYW1lOiBSdXBhIEJhcnVhDQpJRDogczM2ODE2NzINCg0KR3Jvd2luZyB1cCBJIGFsd2F5cyB1c2VkIHRvIHBsYXkgb3Igd2F0Y2ggUG9rZW1vbiBzZXJpZXMuIFNvLCBJIGhhdmUgZGVjaWRlZCB0byB1c2UgYSBwb2tlbW9uIGRhdGFzZXQoMykgZm9yIG15IHByb2plY3QsIHdoZXJlIHRoZSBkYXRhIHdhcyBjb2xsZWN0ZWQgZnJvbSBzZXZlcmFsIGRpZmZlcmVudCB3ZWJzaXRlcyAoMSwyKS4gSXQgaW5jbHVkZXMgZGF0YSBvZiA3MjEgUG9rZW1vbiBhbmQgaXMgYmFzZWQgb24gdGhlIHBva2Vtb24gZ2FtZXMgKE5PVCBwb2tlbW9uIGNhcmRzIG9yIFBva2Vtb24gR28pLiBUaGUgYXR0cmlidXRlcyBpbnZvbHZlZCBhcmUgdXNlZCBmb3IgY2FsY3VsYXRpbmcgaG93IG11Y2ggZGFtYWdlIGFuIGF0dGFjayB3aWxsIGRvIGluIHRoZSBnYW1lcy4gTXkgb2JqZWN0aXZlIGlzIHRvIGJlIGFibGUgdG8gYW5zd2VyIHF1ZXN0aW9ucyBsaWtlOg0KDQoxLiBXaGF0IGlzIHRoZSBtb3N0IGNvbW1vbiB0eXBlIG9mIHBva2Vtb24gaW4gdGhpcyBkYXRhYmFzZT8gDQoNCjIuIENvbXBhcmUgYXR0cmlidXRlcyBsaWtlIEhlYWx0aCBwb2ludHMgKEhQKSwgQXR0YWNrLCBEZWZlbnNlLCBzcGVlZCBhY3Jvc3MgYWxsIHR5cGVzLg0KDQozLiBBcmUgdGhlcmUgYW55IGNvcnJlbGF0aW9uIG9yIGFueSBiZXN0IGZpdCBsaW5lIGFtb25nIGFueSB0d28gYXR0cmlidXRlcz8NCg0KQWxzbywgdG8gdXNlIHRoZSBjb3JyZWxhdGlvbiB0byBqdXN0aWZ5IHR3byBoeXBvdGhlc2lzOg0KDQogIDEuIFRoZSBtb3JlIGhlYWx0aCBwb2ludHMgYSBwb2tlbW9uIGhhcywgdGhlIHN0cm9uZ2VyIHRoZWlyIGF0dGFjayBwb3dlciBpcy4NCiAgDQogIDIuIFRoZSBmYXN0ZXIgdGhlIHBva2Vtb24sIHRoZSBncmVhdGVyIHRoZSBkZWZlbnNlLiANCg0KIyNTZWN0aW9uIDENCg0KV2UgZmlyc3Qgc3RhcnQgYnkgbG9hZGluZyBvdXIgZGF0YXNldCBpbnRvIFIsIGFuZCBoYXZlIGEgbG9vayBvbiBob3cgdGhlIGRhdGFzZXQgaXMgc3RydWN0dXJlZC4NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobWFncml0dHIpDQpsaWJyYXJ5KGdnY29ycnBsb3QpDQpsaWJyYXJ5KGdncGxvdDIpDQpwb2tlbW9uIDwtIHJlYWRfY3N2KCJQb2tlbW9uLmNzdiIpDQpoZWFkKHBva2Vtb24pDQpgYGANCk5vdGljZSwgdGhhdCB0aGUgY29sdW1uIG5hbWVzIGNvbnRhaW4gbWl4dHVyZSBvZiB1cHBlciBhbmQgbG93ZXJjYXNlcyBhbmQgaGF2ZSBzcGFjZXMgaW4gYmV0d2VlbiwgZm9yIG91ciBjb2RpbmcgY29udmVuaWVuY2Ugd2UgY2hhbmdlIHRoZW0gYWxsIHRvIGxvd2VyY2FzZXMsIGFuZCBnZXQgcmlkIG9mIHRoZSBzcGFjZXMuIA0KDQpUaGVyZSBhcmUgc2l4IGdlbmVyYXRpb25zIG9mIHBva2Vtb24gaW4gdGhlIHBva2Vtb24gdW5pdmVyc2UsIGFuZCBpbiBvcmRlciB0byBleHBsb3JlIHRoZSBnZW5lcmF0aW9ucywgd2UgZmFjdG9yIGVhY2ggZ2VuZXJhdGlvbiBhcyBhIGxldmVsLiANCg0KYGBge3J9DQpwb2tlbW9uICU8PiUgcmVuYW1lKA0KICBubyA9ICcjJywNCiAgdHlwZTEgPSBgVHlwZSAxYCwNCiAgdHlwZTIgPSBgVHlwZSAyYCwNCiAgc3BhdGsgPSBgU3AuIEF0a2AsDQogIHNwZGVmID0gYFNwLiBEZWZgDQopDQpuYW1lcyhwb2tlbW9uKSA8LSB0b2xvd2VyKG5hbWVzKHBva2Vtb24pKQ0KcG9rZW1vbiRnZW5lcmF0aW9uIDwtIGZhY3Rvcihwb2tlbW9uJGdlbmVyYXRpb24sIGxldmVscyA9IGMoNiw1LDQsMywyLDEpKQ0KYGBgDQoNCk5vdyAgdGhhdCB3ZSBrbm93IGFsbCB0aGUgZGF0YSB0eXBlcywgYW5kIGhhdmUgY2hhbmdlZCB0aGUgY29sdW1uIG5hbWVzLCBsZXQncyBzZWUgd2hhdCBhcmUgdGhlIGRpZmZlcmVudCB0eXBlcyBvZiBwb2tlbW9uIGV4aXN0aW5nIGluIHRoaXMgZGF0YXNldC4gDQoNCg0KYGBge3J9DQojIFByaW1hcnkgdHlwZXMNCnVuaXF1ZShwb2tlbW9uJHR5cGUxKQ0KYGBgDQpFYWNoIHBva2Vtb24gbXVzdCBiZWxvbmcgdG8gb25lIG9yIG1vcmUgdHlwZXMgKEhlbmNlLCB0eXBlMSBhbmQgdHlwZTIpLiBOb3QgbWFueSBwb2tlbW9uIGhhdmUgZHVhbCB0eXBlcywgYnV0IHRvIGtlZXAgYWxsIHRoZSBkYXRhLCB0aGUgbnVsbCB2YWx1ZXMgd2VyZSBub3QgcmVtb3ZlZCBmcm9tIHRoZSB0eXBlMiBjb2x1bW4uDQoNCmBgYHtyfQ0KI3NlY29uZGFyeSB0eXBlcw0KdW5pcXVlKHBva2Vtb24kdHlwZTIpDQoNCmBgYA0KSW4gdGhlIG5leHQgc2VjdGlvbiwgd2UgdHJ5IHRvIHBsb3QgdGhlIG1vc3QgY29tbW9uIHR5cGUgb2YgcG9rZW1vbiAoVHlwZTEpLg0KQWNjb3JkaW5nIHRvIHRoZSBwbG90IGJlbG93LCB0aGUgbW9zdCBjb21tb24gdHlwZSBpcyAiV2F0ZXIiLCBhbmQgdGhlIGxlYXN0IGNvbW1vbiBiZWluZyAiRmx5aW5nIi4NCg0KYGBge3J9DQpnIDwtIGdncGxvdChwb2tlbW9uLCBhZXModHlwZTEsZmlsbD0gdHlwZTEpKQ0KDQpnICsgZ2VvbV9iYXIoKSsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpKQ0KYGBgDQoNCkFzIG1lbnRpb25lZCBpbiB0aGUgYmVnaW5uaW5nLCBzb21lIHBva2Vtb24gaGF2ZSBkdWFsIHR5cGVzLCBzbyBpdCBpcyBub3Qgc3VycHJpc2luZyB0aGF0IHRoZSAiTkEiIGJhciBoYXMgdGhlIGhpZ2hlc3QgY291bnQsIGJ1dCB0aGUgc2Vjb25kIGhpZ2hlc3QsIG9yIGluIHRoaXMgY2FzZSB0aGUgYWNjdXJhdGUsIG1vc3QgY29tbW9uIHR5cGUyIHdpbGwgYmUgImZseWluZyIsIHdoaWNoIG1lYW5zLCBtb3N0IHBva2Vtb24gaGF2ZSBhIHNlY29uZCAiZmx5aW5nIiBwZXJzb25hbGl0eS4NCg0KRGlmZmVyZW50IGh1ZXMgYXJlIHVzZWQgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBlYWNoIHR5cGUgc28gdGhhdCB0aGUgdGFyZ2V0IGF1ZGllbmNlIGNhbiB1bmRlcnN0YW5kIGNsZWFybHkuIA0KYGBge3J9DQpnIDwtIGdncGxvdChwb2tlbW9uLCBhZXModHlwZTIsZmlsbD0gdHlwZTIpKQ0KDQpnICsgZ2VvbV9iYXIoKSsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpKQ0KYGBgDQpMZXQncyBleHBsb3JlLCBob3cgdGhlIGRpZmZlcmVudCB0eXBlcyBvZiBwb2tlbW9uIGFuZCB0aGVpciBxdWFudGl0aWVzIGFyZSBkaXN0cmlidXRlZCBhbGwgb3ZlciB0aGUgc2l4IGdlbmVyYXRpb25zLiBPbmx5ICJ0eXBlMSIgY29sdW1uIHdhcyBjaG9zZW4gdG8gZGVtb25zdHJhdGUgdGhpcyBwb2ludCwgYXMgbm90IGFsbCBwb2tlbW9uIGhhdmUgYSB0eXBlMi4NCg0KDQpgYGB7cn0NCiMgTnVtYmVyIG9mIFBva+ltb24gb2YgZWFjaCBwcmltYXJ5IHR5cGUgcGVyIGdlbmVyYXRpb24NCmdncGxvdChwb2tlbW9uLCBhZXMoeD10eXBlMSwgZmlsbD1nZW5lcmF0aW9uKSkgKyANCiAgZ2VvbV9iYXIoKSArDQogIGxhYnMoeD0iR2VuZXJhdGlvbiIsIHk9Ik51bWJlciBvZiBQb2vpbW9uIiwNCiAgICAgICB0aXRsZT0iTnVtYmVyIG9mIFBva+ltb24gb2YgZWFjaCBwcmltYXJ5IHR5cGUgcGVyIGdlbmVyYXRpb24iKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpKQ0KYGBgDQoNCkZvciB0aGlzIHBsb3QsIGEgc3RhY2tlZCBiYXIgcGxvdCB3YXMgY2hvc2VuIHRvIGJlIGFibGUgdG8gY29tcGFyZSB3aGljaCBnZW5lcmF0aW9uIGRvbWluYXRlcyB3aGljaCB0eXBlLiBBY2NvcmRpbmcgdG8gdGhlIHBsb3QgYWJvdmUsIEdlbmVyYXRpb24gMSBhbmQgMyBoYXZlIHRoZSBtb3N0IG51bWJlciBvZiB3YXRlciBwb2tlbW9uLCBhbmQgdGhlcmUgYXJlIG9ubHkgZmx5aW5nIHBva2Vtb24gZXhpc3RpbmcgaW4gZ2VuZXJhdGlvbiA1IGFuZCA2LiBGYWlyeSB0eXBlIHBva2Vtb24gb25seSBjYW1lIGluIHBsZW50eSBpbiBnZW5lcmF0aW9uIDYsIGFuZCBpbiBHZW5lcmF0aW9uIDUsIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIG92ZXJhbGwgcXVhbnRpdHkgb24gYWxsIHR5cGVzIGFyZSBhbG1vc3QgY29uc2lzdGVudC4NCg0KDQpUaGUgbGVnZW5kYXJ5IHN0YXR1cyBvZiBhIHBva2Vtb24gbWFrZXMgdGhlIHBva2Vtb24gcmFyZSwgYW5kIHBvd2VyZnVsLiBBIGJhciBwbG90IHdhcyBjaG9zZW4gdG8gZGlzcGxheSB3aGljaCBnZW5lcmF0aW9uIGhhcyB0aGUgbW9zdCBsZWdlbmRhcnkgcG9rZW1vbiBpbiB0aGVpciBtaWRzdC4gDQoNCkFjY29yZGluZyB0byBvdXIgcGxvdCwgaXQgaXMgR2VuZXJhdGlvbiAzLg0KYGBge3J9DQpkZjI8LSBmaWx0ZXIocG9rZW1vbiwgcG9rZW1vbiRsZWdlbmRhcnk9PVRSVUUpDQpnZ3Bsb3QoZGYyLCBhZXMoeD1nZW5lcmF0aW9uLCBmaWxsPWxlZ2VuZGFyeSkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uPSJkb2RnZSIpICsNCiAgbGFicyh4PSJHZW5lcmF0aW9uIiwgeT0iTnVtYmVyIG9mIFBva+ltb24iLA0KICAgICAgIHRpdGxlPSJOdW1iZXIgb2YgTGVnZW5kYXJ5IFBva+ltb24gcGVyIGdlbmVyYXRpb24iKSArDQogIHRoZW1lX2J3KCkNCmBgYA0KDQojI1NlY3Rpb24gMg0KDQpTb21lIGdyb3VwZWQgYm94cGxvdHMgd2VyZSBwbG90dGVkIGZvciBlYWNoIGZlYXR1cmUvYXR0cmlidXRlIHNlZ21lbnRlZCBieSBQb2vpbW9uIHRvIHNlZSBob3cgdGhlIGF0dHJpYnV0ZXMgYXJlIGFjcm9zcyBkaWZmZXJlbnQgdHlwZXMuIEZyb20gdGhlIGJveCBwbG90cyB3ZSBjYW4gb2JzZXJ2ZSB0aGF0Og0KDQpgYGB7cn0NCnBhcihvbWE9YygyLDIsMiwyKSkNCnBva2Vtb24gJT4lIA0KICBnZ3Bsb3QoYWVzKHg9dHlwZTEseT1zcGF0aywgZmlsbD10eXBlMSkpICsNCiAgZ2VvbV9ib3hwbG90KCkrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41KSkNCg0KcG9rZW1vbiAlPiUgDQogIGdncGxvdChhZXMoeD10eXBlMSx5PXNwZGVmLCBmaWxsPXR5cGUxKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41KSkNCg0KcG9rZW1vbiAlPiUgDQogIGdncGxvdChhZXMoeD10eXBlMSx5PWF0dGFjaywgZmlsbD10eXBlMSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpDQoNCnBva2Vtb24gJT4lIA0KICBnZ3Bsb3QoYWVzKHg9dHlwZTEseT1kZWZlbnNlLCBmaWxsPXR5cGUxKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41KSkNCnBva2Vtb24gJT4lIA0KICBnZ3Bsb3QoYWVzKHg9dHlwZTEseT1ocCwgZmlsbD10eXBlMSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpDQoNCg0KYGBgDQpEcmFnb24gVHlwZSBQb2tlbW9uIGhhdmUgYW4gYWR2YW50YWdlIGFjcm9zcyBtb3N0IHN0YXRpc3RpY3MuIA0KU3RlZWwgVHlwZSBQb2tlbW9uIGhhdmUgYW4gYWR2YW50YWdlIG92ZXIgb3RoZXIgdHlwZXMgaW4gRGVmZW5zZSBhbmQgRmx5aW5nIHR5cGUgaGFzIGFuIGFkdmFudGFnZSBvdmVyIG90aGVyIGluIEF0dGFjay4gRmx5aW5nIFBva+ltb24gaGF2ZSBhIHNpZ25pZmljYW50IHNwZWVkIGFkdmFudGFnZSBhcyB3ZWxsLiANCg0KIyNTZWN0aW9uIDMNCg0KTm93LCB0byBpbnZlc3RpZ2F0ZSBjb3JyZWxhdGlvbiBzdGF0aXN0aWNzLCB3ZSB1c2UgbXVsdGl2YXJpYXRlIHBsb3RzLCB1c2luZyBhbGwgdHlwZXMoVHlwZTEpIG9mIHBva2Vtb24sIGFuZCBpbnZlc3RpZ2F0aW5nIGF0dHJpYnV0ZXMgbGlrZSBiYXNpYyBhdHRhY2sgYW5kIGRlZmVuc2UgcG93ZXJzLCB3aXRoIHRoZSBzcGVlZCBhbmQgaGVhbHRoIHBvaW50cyBvZiBlYWNoIHBva2Vtb24uIA0KDQpPdXIgZmlyc3QgaHlwb3RoZXNpcyBpczoNClRoZSBtb3JlIGhlYWx0aCBwb2ludHMgYSBwb2tlbW9uIGhhcywgdGhlIHN0cm9uZ2VyIHRoZWlyIGF0dGFjayBwb3dlciBpcy4NCg0KVG8gaW52ZXN0aWdhdGUgdGhpcyBjYXNlLCB3ZSB1c2UgYSBzY2F0dGVyIHBsb3Qgd2l0aCBhIHJlZ3Jlc3Npb24gbGluZSBmaXR0ZWQgYmV0d2VlbiB0d28gYXR0cmlidXRlcyA6ICJIcCIgYW5kICJBdHRhY2siLg0KDQpgYGB7cn0NCg0KbGlicmFyeShwbG90bHkpDQoNCnAxIDwtIHBsb3RfbHkoZGF0YSA9IHBva2Vtb24sIHggPSB+aHAsIHkgPSB+YXR0YWNrLA0KICAgICAgICAgICAgICBjb2xvciA9IH50eXBlMSwgdHlwZSA9ICJzY2F0dGVyIiwgbW9kZSA9ICJtYXJrZXJzIiwNCiAgICAgICAgICAgICAgY29sb3JzID0gIlJkWWxCdSIsIGhvdmVyaW5mbyA9ICJ0ZXh0IikgJT4lIA0KICANCiAgbGF5b3V0KHlheGlzID0gbGlzdCh6ZXJvbGluZSA9IEZBTFNFLCB0aXRsZSA9ICJBdHRhY2siKSwNCiAgICAgICAgIHhheGlzID0gbGlzdCh6ZXJvbGluZSA9IEZBTFNFLCB0aXRsZSA9ICJIcCIpKSAlPiUgDQogIA0KICBhZGRfdHJhY2UobW9kZSA9ICdsaW5lcycseCA9IH5ocCwgDQogICAgICAgICAgICB5ID0gZml0dGVkKGxtKHBva2Vtb24kYXR0YWNrfiBwb2tlbW9uJGhwKSkNCiAgICAgICAgICAgICkNCnAxDQoNCmBgYA0KDQpGb3IgdGhlIHBsb3QgYWJvdmUsIHdlIGNhbiBzZWUgdGhhdCB0aGUgaGVhbHRoIHBvaW50IG9mIGEgcG9rZW1vbiBhbmQgdGhlIGF0dGFjayBwb3dlciBvZiBhIHBva2Vtb24gYXJlIGNvbGxpbmVhciB0byBlYWNoIG90aGVyLiBXaGljaCBpbmRpY2F0ZXMsIHRoZSBtb3JlIHRoZSBoZWFsdGggcG9pbnRzLCB0aGUgc3Ryb25nZXIgdGhlaXIgYXR0YWNrcyBhcmUuIFRoZSBibHVlIHBhcnQgKGZvciB3YXRlciB0eXBlIHBva2Vtb24pIG9mIHRoZSBncmFwaCBpcyBkaXN0aW5jdCBhbmQgbW9zdCB2aXZpZCBpbiB0aGlzIGdyYXBoIHN1cHBvcnRzIG91ciBoeXBvdGhlc2lzLCBoZW5jZSB3ZSBmYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiANCg0KDQpPdXIgc2Vjb25kIGh5cG90aGVzaXMgaXM6DQpUaGUgZmFzdGVyIHRoZSBwb2tlbW9uLCB0aGUgZ3JlYXRlciB0aGUgZGVmZW5zZS4NCg0KVG8gaW52ZXN0aWdhdGUgdGhpcyBoeXBvdGhlc2lzLCB3ZSB1c2UgYSBzaW1pbGFyIHNjYXR0ZXIgcGxvdCwgb25seSB0aGlzIHRpbWUsIGl0IGlzICJTcGVlZCIgdnMgIkRlZmVuY2UiDQoNCg0KYGBge3J9DQpsaWJyYXJ5KHBsb3RseSkNCg0KcDIgPC0gcGxvdF9seShkYXRhID0gcG9rZW1vbiwgeCA9IH5zcGVlZCwgeSA9IH5kZWZlbnNlLA0KICAgICAgICAgICAgICBjb2xvciA9IH50eXBlMSwgdHlwZSA9ICJzY2F0dGVyIiwgbW9kZSA9ICJtYXJrZXJzIiwNCiAgICAgICAgICAgICAgY29sb3JzID0gIlJkWWxCdSIsIGhvdmVyaW5mbyA9ICJ0ZXh0IikgJT4lIA0KICANCiAgbGF5b3V0KHlheGlzID0gbGlzdCh6ZXJvbGluZSA9IEZBTFNFLCB0aXRsZSA9ICJEZWZlbnNlIiksDQogICAgICAgICB4YXhpcyA9IGxpc3QoemVyb2xpbmUgPSBGQUxTRSwgdGl0bGUgPSAiU3BlZWQiKSkgJT4lIA0KICANCiAgYWRkX3RyYWNlKG1vZGUgPSAnbGluZXMnLHggPSB+c3BlZWQsIA0KICAgICAgICAgICAgeSA9IGZpdHRlZChsbShwb2tlbW9uJGRlZmVuc2V+IHBva2Vtb24kc3BlZWQpKQ0KICAgICAgICAgICAgKQ0KcDINCmBgYA0KVW5mb3J0dW5hdGVseSwgdGhlIHBsb3QgYWJvdmUgc2hvd3MgYSBzdHJhaWdodCBsaW5lIHN0YXRpbmcgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdHdvIGF0dHJpYnV0ZXMuIFRodXMsIG91ciBudWxsIGh5cG90aGVzaXMgaGFzIGJlZW4gcmVqZWN0ZWQuIA0KDQojIyBTdW1tYXJ5IA0KV2UgbG9va2VkIGludG8gd2hhdCBhcmUgdGhlIGRpZmZlcmVudCB0eXBlIG9mIHBva2Vtb24gYXJlIHRoZXJlLCB3aGF0IGFyZSB0aGUgbW9zdCBjb21tb24gb25lcywgaW4gdGVybXMgb2YgdHlwZXMgYW5kIGluIGdlbmVyYXRpb25zLCBhbmQgaG93IHRoZSBkaWZmZXJlbnQgZmVhdHVyZXMgaW50ZXJhY3Qgd2l0aCBkaWZmZXJlbnQgdHlwZXMgYWxsIGFjcm9zcyB0aGUgZGlmZmVyZW50IHR5cGVzLiBEaWZmZXJlbnQgaHVlcyB3ZXJlIHNlbGVjdGVkIGluIGV2ZXJ5IHBsb3QgdG8gZGlzdGluZ3Vpc2ggYW1vbmcgdGhlIGRpZmZlcmVudCBwbG90cywgYW5kIHBsb3RzIGxpa2UgYmFyLWdyYXBoIGFuZCBzY2F0dGVyIHBsb3RzIHdlcmUgdXNlZCBpbiBlYWNoIGNhc2UsIHdoaWNoIHdlcmUgYWJsZSB0byBjYXRjaCBhbmQgZGlzcGxheSB0aGUgaXNzdWUgY2xlYXJseSBpbnN0ZWFkIG9mIGFueSBraW5kIG9mIGRlY2VwdGlvbi4gDQoNCiMjUmVmZXJlbmNlcw0KMS4gQnVsYmFwZWRpYSwgdGhlIGNvbW11bml0eS1kcml2ZW4gcG9rtGVtb24gZW5jeWNsb3BlZGlhLiBodHRwczovL2J1bGJhcGVkaWEuYnVsYmFnYXJkZW4ubmV0L3dpa2kvTWFpblAgYWdlLihBY2Nlc3NlZCBvbiAxMC8yOS8yMDE5KS4NCg0KMi4gVGhlIG8/Pz9jaWFsIHBva7RlbW9uIHdlYnNpdGUgLSBwb2tlbW9uLmNvbSAtIGV4cGxvcmUgdGhlIHdvcmxkIG9mIHBva7RlbW9uLiBodHRwczovL3d3dy5wb2tlbW9uLmNvbS91cy8uIChBY2Nlc3NlZCBvbiAxMC8yOS8yMDE5KS4NCg0KMy4gUG9rZW1vbiB3aXRoIHN0YXRzIC0ga2FnZ2xlLiBodHRwczovL3d3dy5rYWdnbGUuY29tL2FiY3Nkcy9wb2tlbW9uLiAoQWNjZXNzZWQgb24gMTAvMjkvMjAxOSku