Analysis
1. What is His Win Percentage Overall?
# count of win, draw, loss
overall_win <- df %>%
group_by(Result) %>%
summarise(Count = n())
# vars for inline code
ngame <- summarise(df, n()) %>% as.character()
wins <- overall_win[3, 2] %>% as.character()
loss <- overall_win[2, 2] %>% as.character()
draw <- overall_win[1, 2] %>% as.character()
wr <- round(as.numeric(wins) / as.numeric(ngame) * 100, 2)
# plot
overall_win %>%
ggplot(aes(x = reorder(Result, -Count), y = Count)) +
geom_bar(stat = "identity", width = 0.6) +
labs(
title = "Comparison of number of wins, losses, and draws",
x = "Result"
) +
theme_light()

His win percentage is 42.24 %. Out of 3262 games, 1378 are wins, 576 are losses, and 1308 are draws. Most of his games end in either a win or a draw.
2. What is His Win Percentage Grouped by Color?
# ratio of win, draw, loss by color
winrate <- df %>%
group_by(Color, Result) %>%
summarise(count = n()) %>%
mutate(Percentage = count / sum(count) * 100) %>%
select(-count)
# vars for inline code
w_wr <- round(winrate[6, 3], 2) %>% as.character()
b_wr <- round(winrate[3, 3], 2) %>% as.character()
# plot
winrate %>%
ggplot(aes(x = Color, y = Percentage, fill = Result)) +
geom_bar(stat = "identity", position = "fill", width = 0.6) +
coord_flip() +
labs(
title = "Ratio of Wins, Losses & Draws Grouped by Color",
y = "Win : Loss : Draw"
) +
guides(fill = guide_legend(reverse = TRUE)) +
theme_light()

His win-rate as white is 47.74 %, which is higher than his win-rate as black 36.7 %. Win to loss to draw ratio is roughly the same as white or black.
3. Which Openings Does He Play the Most Overall?
# openings and their game count
overall_op <- df %>%
group_by(Opening) %>%
summarise(N_games = n()) %>%
arrange(desc(N_games))
# top 10 most played openings
head(overall_op, 10) %>%
ggplot(aes(x = reorder(Opening, N_games), y = N_games)) +
geom_bar(stat = "identity") +
coord_flip() +
labs(
title = "Most Played Openings Overall",
x = "Opening",
y = "Number of Games"
) +
theme_light()

4. Which Openings Does He Play the Most Grouped by Color?
# top 10 most played openings grouped by color
top_by_color <- df %>%
group_by(Color, Opening) %>%
summarise(N_games = n()) %>%
top_n(n = 10, wt = N_games)
# top 10 most played openings by white
white <- head(top_by_color, 10) %>%
ggplot(aes(x = reorder(Opening, N_games), y = N_games)) +
geom_bar(stat = "identity") +
coord_flip() +
labs(
title = "Most Played Openings as White",
x = "Openings",
y = "Number of Games"
) +
theme_light()
# top 10 most played openings by black
black <- tail(top_by_color, 10) %>%
ggplot(aes(x = reorder(Opening, N_games), y = N_games)) +
geom_bar(stat = "identity") +
coord_flip() +
labs(
title = "Most Played Openings as Black",
x = "Openings",
y = "Number of Games"
) +
theme_light()
grid.arrange(white, black)

It looks like the most played opening is the sicilian defense for both white and black. This might happen because there are many variations of the sicilian defense, but all of them are grouped together in the data.
5. Does He Lose More Against Higher Rated Opponents?
# results against/not-against higher rated opponents
vs_higher <-df %>%
mutate(Vs_higher = if_else(Opponent_rating > Rating, "yes","no")) %>%
group_by(Vs_higher, Result) %>%
summarise(count = n()) %>%
mutate(Percentage = count / sum(count) * 100) %>%
select(-count) %>%
arrange(desc(Vs_higher))
# vars for inline code
highdraw <- round(vs_higher[1, 3], 2) %>% as.character()
lowwin <- round(vs_higher[6, 3], 2) %>% as.character()
#plot
vs_higher %>%
ggplot(aes(x = Vs_higher, y = Percentage, fill = Result)) +
geom_bar(stat = "identity", width = 0.6) +
coord_flip() +
labs(
title = "Ratio of Game Results Against & not Against Higher-Rated Opponents",
x = "Against Higher-Rated Opponents?",
y = "Win : Loss : Draw"
) +
guides(fill = guide_legend(reverse = TRUE)) +
theme_light()

Against higher-rated opponents, nearly half of his games end in a draw. More specifically 45.37 %. His win-rate is only slightly higher than his lose rate. On the other hand, 48.14 % of his games against lower-rated opponents are wins.
6. What is the Average Move Count in his Games?
# avg number of moves
avg_mv <- round(mean(df$Moves)) %>% as.character()
# move count distribution
df %>%
ggplot(aes(x = Moves)) +
geom_histogram(binwidth = 5) +
labs(
title = "Distribution of Number of Moves in a Game",
x = "Number of Moves",
y = "Count"
) +
theme_light()

The average number of moves of his games is 48 moves.
7. Does the Number of Moves Effect Game Results?
# avg moves for win/draw/loss plot
df %>%
group_by(Result) %>%
summarise(Mean_moves = mean(Moves)) %>%
ggplot(aes(x = reorder(Result, Mean_moves), y = Mean_moves)) +
geom_bar(stat = "identity", width = 0.6) +
labs(
title = "Average move counts of different game results",
x = "Results",
y = "Average move count"
) +
theme_light()

The average move count is roughly the same for wins, losses, and draws. Number of moves is unlikely to effect game results.
9. Who does he play with most often?
# top 10 most played opponents
reg_opp <- df %>%
group_by(Opponent) %>%
summarise(n = n()) %>%
arrange(desc(n)) %>%
head(10)
# top 10 barchart
reg_opp %>%
ggplot(aes(x = reorder(Opponent, n), y = n)) +
geom_bar(stat = "identity", width = 0.6) +
coord_flip() +
labs(
title = "Top 10 Players He Plays with Most Often",
x = "Opponent",
y = "Number of games played"
) +
theme_light()

10. What are Hikaru’s Game Results Like Against Them?
# w/d/l ratio
df %>%
group_by(Opponent, Result) %>%
filter(Opponent %in% reg_opp$Opponent) %>%
summarise(n = n()) %>%
ggplot(aes(x = Opponent, y = n, fill = Result)) +
geom_bar(stat = "identity",position = "fill", width = 0.6) +
coord_flip() +
labs(
title = "Results Against Players He Plays With Most Often",
x = "Opponent",
y = "Win : Loss : Draw"
) +
guides(fill = guide_legend(reverse = TRUE)) +
theme_light()

Against the players he plays with most often, the result is usually a draw. His win-rates are higher than his lose-rates except against Magnus Carlsen, the world champion.
11. Does the Opening Played Effect the Game Result?
12. Which Openings Have the Highest Win-Rate Overall?
# top 10 op overal
df %>%
filter(Opening %in% op_res$Opening) %>%
group_by(Opening, Result) %>%
summarise(Count = n()) %>%
mutate(Winrate = round(Count / sum(Count) * 100, 2)) %>%
filter(Result == "Win") %>%
select(-Count, -Result) %>%
arrange(desc(Winrate)) %>%
head(10) %>%
ggplot(aes(x = reorder(Opening, Winrate), y = Winrate)) +
geom_bar(stat = "Identity", width = 0.6) +
coord_flip() +
scale_y_continuous(limits = c(0, 100)) +
labs(
title = "Top 10 Win-Rates of Openings Overall",
x = "Opening",
y = "Win-rate in percentages(%)"
) +
theme_light()

12. Which Openings Have the Highest Win-Rate Grouped by Color?
# top 10 white op
opw <- df %>%
filter(Opening %in% op_res$Opening) %>%
group_by(Color, Opening, Result) %>%
summarise(Count = n()) %>%
mutate(Winrate = round(Count / sum(Count) * 100, 2)) %>%
filter(Result == "Win" & Color == "White") %>%
select(-Count, -Result) %>%
arrange(desc(Winrate)) %>%
head(10) %>%
ggplot(aes(x = reorder(Opening, Winrate), y = Winrate)) +
geom_bar(stat = "Identity", width = 0.6) +
coord_flip() +
scale_y_continuous(limits = c(0, 100)) +
labs(
title = "Top 10 Win-rates of Openings Played as White",
x = "Opening",
y = "Win-Rate in Percentages(%)"
) +
theme_light()
# top 10 black op
opb <- df %>%
filter(Opening %in% op_res$Opening) %>%
group_by(Color, Opening, Result) %>%
summarise(Count = n()) %>%
mutate(Winrate = round(Count / sum(Count) * 100, 2)) %>%
filter(Result == "Win" & Color == "Black") %>%
select(-Count, -Result) %>%
arrange(desc(Winrate)) %>%
head(10) %>%
ggplot(aes(x = reorder(Opening, Winrate), y = Winrate)) +
geom_bar(stat = "Identity", width = 0.6) +
coord_flip() +
scale_y_continuous(limits = c(0, 100)) +
labs(
title = "Top 10 Win-rates of Openings Played as Black",
x = "Opening",
y = "Win-Rate in Percentages(%)"
) +
theme_light()
grid.arrange(opw, opb)

LS0tCnRpdGxlOiAiRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcyBvZiBIaWthcnUgTmFrYW11cmEncyBHYW1lcyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0aGVtZTogcGFwZXIKLS0tCgpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UpCmBgYAoKIyMgKipJbXBvcnQgTGlicmFyaWVzKioKYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkRXh0cmEpCmBgYAoKIyMgKipJbXBvcnQgYW5kIFZpZXcgRGF0YSoqCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRX0KZGYgPC0gcmVhZF9jc3YoImRhdGEvY2xlYW5lZF9kYXRhLmNzdiIpCmhlYWQoZGYpCmBgYAoKIyMgKipBbmFseXNpcyoqCiMjIyAqKjEuIFdoYXQgaXMgSGlzIFdpbiBQZXJjZW50YWdlIE92ZXJhbGw/KioKYGBge3J9CiMgY291bnQgb2Ygd2luLCBkcmF3LCBsb3NzCm92ZXJhbGxfd2luIDwtIGRmICU+JQogIGdyb3VwX2J5KFJlc3VsdCkgJT4lCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKQoKIyB2YXJzIGZvciBpbmxpbmUgY29kZQpuZ2FtZSA8LSBzdW1tYXJpc2UoZGYsIG4oKSkgJT4lIGFzLmNoYXJhY3RlcigpCndpbnMgPC0gb3ZlcmFsbF93aW5bMywgMl0gJT4lIGFzLmNoYXJhY3RlcigpCmxvc3MgPC0gb3ZlcmFsbF93aW5bMiwgMl0gJT4lIGFzLmNoYXJhY3RlcigpCmRyYXcgPC0gb3ZlcmFsbF93aW5bMSwgMl0gJT4lIGFzLmNoYXJhY3RlcigpCndyIDwtIHJvdW5kKGFzLm51bWVyaWMod2lucykgLyBhcy5udW1lcmljKG5nYW1lKSAqIDEwMCwgMikKCiMgcGxvdApvdmVyYWxsX3dpbiAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFJlc3VsdCwgLUNvdW50KSwgeSA9IENvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb21wYXJpc29uIG9mIG51bWJlciBvZiB3aW5zLCBsb3NzZXMsIGFuZCBkcmF3cyIsCiAgICB4ID0gIlJlc3VsdCIKICApICsKICB0aGVtZV9saWdodCgpCmBgYApIaXMgd2luIHBlcmNlbnRhZ2UgaXMgYHIgd3JgICUuIE91dCBvZiBgciBuZ2FtZWAgZ2FtZXMsIGByIHdpbnNgIGFyZSB3aW5zLCBgciBsb3NzYCBhcmUgbG9zc2VzLAphbmQgYHIgZHJhd2AgYXJlIGRyYXdzLiAgTW9zdCBvZiBoaXMgZ2FtZXMgZW5kIGluIGVpdGhlciBhIHdpbiBvciBhIGRyYXcuIAoKCiMjIyAqKjIuIFdoYXQgaXMgSGlzIFdpbiBQZXJjZW50YWdlIEdyb3VwZWQgYnkgQ29sb3I/KioKYGBge3J9CiMgcmF0aW8gb2Ygd2luLCBkcmF3LCBsb3NzIGJ5IGNvbG9yCndpbnJhdGUgPC0gZGYgJT4lCiAgZ3JvdXBfYnkoQ29sb3IsIFJlc3VsdCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IGNvdW50IC8gc3VtKGNvdW50KSAqIDEwMCkgJT4lCiAgc2VsZWN0KC1jb3VudCkgCgojIHZhcnMgZm9yIGlubGluZSBjb2RlCndfd3IgPC0gcm91bmQod2lucmF0ZVs2LCAzXSwgMikgJT4lIGFzLmNoYXJhY3RlcigpCmJfd3IgPC0gcm91bmQod2lucmF0ZVszLCAzXSwgMikgJT4lIGFzLmNoYXJhY3RlcigpCgojIHBsb3QKd2lucmF0ZSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBDb2xvciwgeSA9IFBlcmNlbnRhZ2UsIGZpbGwgPSBSZXN1bHQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuNikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlJhdGlvIG9mIFdpbnMsIExvc3NlcyAmIERyYXdzIEdyb3VwZWQgYnkgQ29sb3IiLAogICAgeSA9ICJXaW4gOiBMb3NzIDogRHJhdyIKICApICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpICsKICB0aGVtZV9saWdodCgpCmBgYApIaXMgd2luLXJhdGUgYXMgd2hpdGUgaXMgYHIgd193cmAgJSwgd2hpY2ggaXMgaGlnaGVyIHRoYW4gaGlzIHdpbi1yYXRlIGFzIGJsYWNrIGByIGJfd3JgICUuIApXaW4gdG8gbG9zcyB0byBkcmF3IHJhdGlvIGlzIHJvdWdobHkgdGhlIHNhbWUgYXMgd2hpdGUgb3IgYmxhY2suCgoKIyMjICoqMy4gV2hpY2ggT3BlbmluZ3MgRG9lcyBIZSBQbGF5IHRoZSBNb3N0IE92ZXJhbGw/KioKYGBge3J9CiMgb3BlbmluZ3MgYW5kIHRoZWlyIGdhbWUgY291bnQKb3ZlcmFsbF9vcCA8LSBkZiAlPiUKICBncm91cF9ieShPcGVuaW5nKSAlPiUKICBzdW1tYXJpc2UoTl9nYW1lcyA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKE5fZ2FtZXMpKQoKIyB0b3AgMTAgbW9zdCBwbGF5ZWQgb3BlbmluZ3MKaGVhZChvdmVyYWxsX29wLCAxMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihPcGVuaW5nLCBOX2dhbWVzKSwgeSA9IE5fZ2FtZXMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJNb3N0IFBsYXllZCBPcGVuaW5ncyBPdmVyYWxsIiwKICAgIHggPSAiT3BlbmluZyIsCiAgICB5ID0gIk51bWJlciBvZiBHYW1lcyIKICApICsKICB0aGVtZV9saWdodCgpCmBgYAoKIyMjICoqNC4gV2hpY2ggT3BlbmluZ3MgRG9lcyBIZSBQbGF5IHRoZSBNb3N0IEdyb3VwZWQgYnkgQ29sb3I/KioKYGBge3J9CiMgdG9wIDEwIG1vc3QgcGxheWVkIG9wZW5pbmdzIGdyb3VwZWQgYnkgY29sb3IKdG9wX2J5X2NvbG9yIDwtIGRmICU+JQogIGdyb3VwX2J5KENvbG9yLCBPcGVuaW5nKSAlPiUKICBzdW1tYXJpc2UoTl9nYW1lcyA9IG4oKSkgJT4lCiAgdG9wX24obiA9IDEwLCB3dCA9IE5fZ2FtZXMpCgojIHRvcCAxMCBtb3N0IHBsYXllZCBvcGVuaW5ncyBieSB3aGl0ZQp3aGl0ZSA8LSBoZWFkKHRvcF9ieV9jb2xvciwgMTApICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoT3BlbmluZywgTl9nYW1lcyksIHkgPSBOX2dhbWVzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTW9zdCBQbGF5ZWQgT3BlbmluZ3MgYXMgV2hpdGUiLAogICAgeCA9ICJPcGVuaW5ncyIsCiAgICB5ID0gIk51bWJlciBvZiBHYW1lcyIKICApICsKICB0aGVtZV9saWdodCgpCgoKIyB0b3AgMTAgbW9zdCBwbGF5ZWQgb3BlbmluZ3MgYnkgYmxhY2sKYmxhY2sgPC0gdGFpbCh0b3BfYnlfY29sb3IsIDEwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKE9wZW5pbmcsIE5fZ2FtZXMpLCB5ID0gTl9nYW1lcykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIk1vc3QgUGxheWVkIE9wZW5pbmdzIGFzIEJsYWNrIiwKICAgIHggPSAiT3BlbmluZ3MiLAogICAgeSA9ICJOdW1iZXIgb2YgR2FtZXMiCiAgKSArCiAgdGhlbWVfbGlnaHQoKQoKZ3JpZC5hcnJhbmdlKHdoaXRlLCBibGFjaykKYGBgCkl0IGxvb2tzIGxpa2UgdGhlIG1vc3QgcGxheWVkIG9wZW5pbmcgaXMgdGhlIHNpY2lsaWFuIGRlZmVuc2UgZm9yIGJvdGggd2hpdGUgYW5kIGJsYWNrLiBUaGlzIG1pZ2h0IGhhcHBlbiAKYmVjYXVzZSB0aGVyZSBhcmUgbWFueSB2YXJpYXRpb25zIG9mIHRoZSBzaWNpbGlhbiBkZWZlbnNlLCBidXQgYWxsIG9mIHRoZW0gYXJlIGdyb3VwZWQgdG9nZXRoZXIgaW4gdGhlIGRhdGEuCgoKIyMjICoqNS4gRG9lcyBIZSBMb3NlIE1vcmUgQWdhaW5zdCBIaWdoZXIgUmF0ZWQgT3Bwb25lbnRzPyoqCmBgYHtyfQojIHJlc3VsdHMgYWdhaW5zdC9ub3QtYWdhaW5zdCBoaWdoZXIgcmF0ZWQgb3Bwb25lbnRzCnZzX2hpZ2hlciA8LWRmICU+JQogIG11dGF0ZShWc19oaWdoZXIgPSBpZl9lbHNlKE9wcG9uZW50X3JhdGluZyA+IFJhdGluZywgInllcyIsIm5vIikpICU+JQogIGdyb3VwX2J5KFZzX2hpZ2hlciwgUmVzdWx0KSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIG11dGF0ZShQZXJjZW50YWdlID0gY291bnQgLyBzdW0oY291bnQpICogMTAwKSAlPiUKICBzZWxlY3QoLWNvdW50KSAlPiUKICBhcnJhbmdlKGRlc2MoVnNfaGlnaGVyKSkKCiMgdmFycyBmb3IgaW5saW5lIGNvZGUKaGlnaGRyYXcgPC0gcm91bmQodnNfaGlnaGVyWzEsIDNdLCAyKSAlPiUgYXMuY2hhcmFjdGVyKCkKbG93d2luIDwtIHJvdW5kKHZzX2hpZ2hlcls2LCAzXSwgMikgJT4lIGFzLmNoYXJhY3RlcigpCgojcGxvdAp2c19oaWdoZXIgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVnNfaGlnaGVyLCB5ID0gUGVyY2VudGFnZSwgZmlsbCA9IFJlc3VsdCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjYpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJSYXRpbyBvZiBHYW1lIFJlc3VsdHMgQWdhaW5zdCAmIG5vdCBBZ2FpbnN0IEhpZ2hlci1SYXRlZCBPcHBvbmVudHMiLAogICAgeCA9ICJBZ2FpbnN0IEhpZ2hlci1SYXRlZCBPcHBvbmVudHM/IiwKICAgIHkgPSAiV2luIDogTG9zcyA6IERyYXciCiAgKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKSArCiAgdGhlbWVfbGlnaHQoKQpgYGAKQWdhaW5zdCBoaWdoZXItcmF0ZWQgb3Bwb25lbnRzLCBuZWFybHkgaGFsZiBvZiBoaXMgZ2FtZXMgZW5kIGluIGEgZHJhdy4gTW9yZSBzcGVjaWZpY2FsbHkgCmByIGhpZ2hkcmF3YCAlLiBIaXMgd2luLXJhdGUgaXMgb25seSBzbGlnaHRseSBoaWdoZXIgdGhhbiBoaXMgbG9zZSByYXRlLiBPbiB0aGUgb3RoZXIgaGFuZCwgCmByIGxvd3dpbmAgJSBvZiBoaXMgZ2FtZXMgYWdhaW5zdCBsb3dlci1yYXRlZCBvcHBvbmVudHMgYXJlIHdpbnMuCgoKIyMjICoqNi4gV2hhdCBpcyB0aGUgQXZlcmFnZSBNb3ZlIENvdW50IGluIGhpcyBHYW1lcz8qKgpgYGB7cn0KIyBhdmcgbnVtYmVyIG9mIG1vdmVzCmF2Z19tdiA8LSByb3VuZChtZWFuKGRmJE1vdmVzKSkgJT4lIGFzLmNoYXJhY3RlcigpCgojIG1vdmUgY291bnQgZGlzdHJpYnV0aW9uCmRmICU+JQogIGdncGxvdChhZXMoeCA9IE1vdmVzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgTnVtYmVyIG9mIE1vdmVzIGluIGEgR2FtZSIsCiAgICB4ID0gIk51bWJlciBvZiBNb3ZlcyIsCiAgICB5ID0gIkNvdW50IgogICkgKwogIHRoZW1lX2xpZ2h0KCkKYGBgClRoZSBhdmVyYWdlIG51bWJlciBvZiBtb3ZlcyBvZiBoaXMgZ2FtZXMgaXMgYHIgYXZnX212YCBtb3Zlcy4KCgojIyMgKio3LiBEb2VzIHRoZSBOdW1iZXIgb2YgTW92ZXMgRWZmZWN0IEdhbWUgUmVzdWx0cz8qKgpgYGB7cn0KIyBhdmcgbW92ZXMgZm9yIHdpbi9kcmF3L2xvc3MgcGxvdApkZiAlPiUKICBncm91cF9ieShSZXN1bHQpICU+JQogIHN1bW1hcmlzZShNZWFuX21vdmVzID0gbWVhbihNb3ZlcykpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoUmVzdWx0LCBNZWFuX21vdmVzKSwgeSA9IE1lYW5fbW92ZXMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC42KSArCiAgbGFicygKICAgIHRpdGxlID0gIkF2ZXJhZ2UgbW92ZSBjb3VudHMgb2YgZGlmZmVyZW50IGdhbWUgcmVzdWx0cyIsCiAgICB4ID0gIlJlc3VsdHMiLAogICAgeSA9ICJBdmVyYWdlIG1vdmUgY291bnQiCiAgKSArCiAgdGhlbWVfbGlnaHQoKQpgYGAKVGhlIGF2ZXJhZ2UgbW92ZSBjb3VudCBpcyByb3VnaGx5IHRoZSBzYW1lIGZvciB3aW5zLCBsb3NzZXMsIGFuZCBkcmF3cy4gTnVtYmVyIG9mIG1vdmVzIGlzIAp1bmxpa2VseSB0byBlZmZlY3QgZ2FtZSByZXN1bHRzLgoKCiMjIyAqKjguIFdoaWNoIHllYXIgZGlkIGhlIHBlcmZvcm0gdGhlIGJlc3QgaW4/KioKYGBge3J9CiMgaGlnaGVzdCByYXRpbmcgb2YgZWFjaCB5ZWFyIDIwMDMtMjAyMApkZiAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBmaWx0ZXIoWWVhciA+IDIwMDIpICU+JQogIHN1bW1hcmlzZShoaWdoZXN0X3J0ID0gbWF4KFJhdGluZywgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IGhpZ2hlc3RfcnQpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwMiwgMjAyMCwgMikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiWWVhcmx5IEhpZ2hlc3QgUmF0aW5nIGZyb20gMjAwMyB0byBtaWQgMjAyMCIsCiAgICB5ID0gIlJhdGluZyIKICApICsKICB0aGVtZV9saWdodCgpCgptYXhfcnQgPC0gbWF4KGRmJFJhdGluZykgJT4lIGFzLmNoYXJhY3RlcigpCmBgYApUaGlzIGNoYXJ0IHN0YXJ0cyBmcm9tIDIwMDMsIHRoZSB5ZWFyIGhlIGJlY2FtZSBhIEdNLiBIaXMgaGlnaGVzdCByYXRpbmcgd2FzIGByIG1heF9ydGAgYmFjayBpbiAyMDE1LgoKCiMjIyAqKjkuIFdobyBkb2VzIGhlIHBsYXkgd2l0aCBtb3N0IG9mdGVuPyoqCmBgYHtyfQojIHRvcCAxMCBtb3N0IHBsYXllZCBvcHBvbmVudHMKcmVnX29wcCA8LSBkZiAlPiUKICBncm91cF9ieShPcHBvbmVudCkgJT4lCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhuKSkgJT4lCiAgaGVhZCgxMCkKCiMgdG9wIDEwIGJhcmNoYXJ0CnJlZ19vcHAgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihPcHBvbmVudCwgbiksIHkgPSBuKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCAxMCBQbGF5ZXJzIEhlIFBsYXlzIHdpdGggTW9zdCBPZnRlbiIsCiAgICB4ID0gIk9wcG9uZW50IiwKICAgIHkgPSAiTnVtYmVyIG9mIGdhbWVzIHBsYXllZCIKICApICsKICB0aGVtZV9saWdodCgpCmBgYAoKIyMjICoqMTAuIFdoYXQgYXJlIEhpa2FydSdzIEdhbWUgUmVzdWx0cyBMaWtlIEFnYWluc3QgVGhlbT8qKgpgYGB7cn0KIyB3L2QvbCByYXRpbyAKZGYgJT4lCiAgZ3JvdXBfYnkoT3Bwb25lbnQsIFJlc3VsdCkgJT4lCiAgZmlsdGVyKE9wcG9uZW50ICVpbiUgcmVnX29wcCRPcHBvbmVudCkgJT4lCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQogIGdncGxvdChhZXMoeCA9IE9wcG9uZW50LCB5ID0gbiwgZmlsbCA9IFJlc3VsdCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iixwb3NpdGlvbiA9ICJmaWxsIiwgd2lkdGggPSAwLjYpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJSZXN1bHRzIEFnYWluc3QgUGxheWVycyBIZSBQbGF5cyBXaXRoIE1vc3QgT2Z0ZW4iLAogICAgeCA9ICJPcHBvbmVudCIsCiAgICB5ID0gIldpbiA6IExvc3MgOiBEcmF3IgogICkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSkgKwogIHRoZW1lX2xpZ2h0KCkKYGBgCkFnYWluc3QgdGhlIHBsYXllcnMgaGUgcGxheXMgd2l0aCBtb3N0IG9mdGVuLCB0aGUgcmVzdWx0IGlzIHVzdWFsbHkgYSBkcmF3LiBIaXMgd2luLXJhdGVzIGFyZSAKaGlnaGVyIHRoYW4gaGlzIGxvc2UtcmF0ZXMgZXhjZXB0IGFnYWluc3QgTWFnbnVzIENhcmxzZW4sIHRoZSB3b3JsZCBjaGFtcGlvbi4KCgojIyMgKioxMS4gRG9lcyB0aGUgT3BlbmluZyBQbGF5ZWQgRWZmZWN0IHRoZSBHYW1lIFJlc3VsdD8qKgojIyMjICoqUGVyZm9ybWluZyBhIENvY2hyYW4tTWFlbnRlbC1IYWVuc3plbCBUZXN0KioKYmVmb3JlIGRvaW5nIHRoZSB0ZXN0LCBJIGZpbHRlcmVkIHRoZSBkYXRhIHRvIGluY2x1ZGUgb25seSBvcGVuaW5ncyB0aGF0IHdlcmUgcGxheWVkICAKYXRsZWFzdCAyMCB0aW1lcy4gVGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIAp0aGUgb3BlbmluZyBwbGF5ZWQsIHRoZSBwaWVjZSBjb2xvciwgYW5kIHRoZSBnYW1lIHJlc3VsdC4gVGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgCmlzIHRoYXQgdGhlcmUgaXMgYSByZWxhdGlvbnNoaXAuIEFscGhhIHZhbHVlIGlzIDAuMDUuCmBgYHtyfQojIG9wZW5pbmdzIHdpdGggZ2FtZSBudW1iZXIgPiAyMApmcmVxX29wIDwtIGRmICU+JQogIGdyb3VwX2J5KE9wZW5pbmcpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgZmlsdGVyKGNvdW50ID4gMjApCgojIGNvbG9ycywgb3BlbmluZ3MsIHJlc3VsdHMgCm9wX3JlcyA8LSBkZiAlPiUKICBzZWxlY3QoQ29sb3IsIE9wZW5pbmcsIFJlc3VsdCkgJT4lCiAgZmlsdGVyKE9wZW5pbmcgJWluJSBmcmVxX29wJE9wZW5pbmcpCgojIGNvY2hyYW4tbWFudGVsLWhhZW5zemVsIHRlcyBvbiBvcF9yZXMKdGIgPC0gdGFibGUob3BfcmVzJENvbG9yLCBvcF9yZXMkT3BlbmluZywgb3BfcmVzJFJlc3VsdCkKbWFudGVsaGFlbi50ZXN0KHRiKQpgYGAKVGhlIHAtdmFsdWUgaXMgc2lnbmlmaWNhbnRseSBsb3dlciB0aGFuIHRoZSBhbHBoYSB2YWx1ZS4gVGhlIG51bGwgaHlwb3RoZXNpcyBpcyByZWplY3RlZC4KCiMjIyAqKjEyLiBXaGljaCBPcGVuaW5ncyBIYXZlIHRoZSBIaWdoZXN0IFdpbi1SYXRlIE92ZXJhbGw/KioKYGBge3J9CiMgdG9wIDEwIG9wIG92ZXJhbApkZiAlPiUKICBmaWx0ZXIoT3BlbmluZyAlaW4lIG9wX3JlcyRPcGVuaW5nKSAlPiUKICBncm91cF9ieShPcGVuaW5nLCBSZXN1bHQpICU+JQogIHN1bW1hcmlzZShDb3VudCA9IG4oKSkgJT4lCiAgbXV0YXRlKFdpbnJhdGUgPSByb3VuZChDb3VudCAvIHN1bShDb3VudCkgKiAxMDAsIDIpKSAlPiUKICBmaWx0ZXIoUmVzdWx0ID09ICJXaW4iKSAlPiUKICBzZWxlY3QoLUNvdW50LCAtUmVzdWx0KSAlPiUKICBhcnJhbmdlKGRlc2MoV2lucmF0ZSkpICU+JQogIGhlYWQoMTApICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoT3BlbmluZywgV2lucmF0ZSksIHkgPSBXaW5yYXRlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiSWRlbnRpdHkiLCB3aWR0aCA9IDAuNikgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUb3AgMTAgV2luLVJhdGVzIG9mIE9wZW5pbmdzIE92ZXJhbGwiLAogICAgeCA9ICJPcGVuaW5nIiwKICAgIHkgPSAiV2luLXJhdGUgaW4gcGVyY2VudGFnZXMoJSkiCiAgKSArCiAgdGhlbWVfbGlnaHQoKQpgYGAKCiMjIyAqKjEyLiBXaGljaCBPcGVuaW5ncyBIYXZlIHRoZSBIaWdoZXN0IFdpbi1SYXRlIEdyb3VwZWQgYnkgQ29sb3I/KioKYGBge3J9CiMgdG9wIDEwIHdoaXRlIG9wCm9wdyA8LSBkZiAlPiUKICBmaWx0ZXIoT3BlbmluZyAlaW4lIG9wX3JlcyRPcGVuaW5nKSAlPiUKICBncm91cF9ieShDb2xvciwgT3BlbmluZywgUmVzdWx0KSAlPiUKICBzdW1tYXJpc2UoQ291bnQgPSBuKCkpICU+JQogIG11dGF0ZShXaW5yYXRlID0gcm91bmQoQ291bnQgLyBzdW0oQ291bnQpICogMTAwLCAyKSkgJT4lCiAgZmlsdGVyKFJlc3VsdCA9PSAiV2luIiAmIENvbG9yID09ICJXaGl0ZSIpICU+JQogIHNlbGVjdCgtQ291bnQsIC1SZXN1bHQpICU+JQogIGFycmFuZ2UoZGVzYyhXaW5yYXRlKSkgJT4lCiAgaGVhZCgxMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihPcGVuaW5nLCBXaW5yYXRlKSwgeSA9IFdpbnJhdGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJJZGVudGl0eSIsIHdpZHRoID0gMC42KSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCAxMCBXaW4tcmF0ZXMgb2YgT3BlbmluZ3MgUGxheWVkIGFzIFdoaXRlIiwKICAgIHggPSAiT3BlbmluZyIsCiAgICB5ID0gIldpbi1SYXRlIGluIFBlcmNlbnRhZ2VzKCUpIgogICkgKwogIHRoZW1lX2xpZ2h0KCkKCgojIHRvcCAxMCBibGFjayBvcApvcGIgPC0gZGYgJT4lCiAgZmlsdGVyKE9wZW5pbmcgJWluJSBvcF9yZXMkT3BlbmluZykgJT4lCiAgZ3JvdXBfYnkoQ29sb3IsIE9wZW5pbmcsIFJlc3VsdCkgJT4lCiAgc3VtbWFyaXNlKENvdW50ID0gbigpKSAlPiUKICBtdXRhdGUoV2lucmF0ZSA9IHJvdW5kKENvdW50IC8gc3VtKENvdW50KSAqIDEwMCwgMikpICU+JQogIGZpbHRlcihSZXN1bHQgPT0gIldpbiIgJiBDb2xvciA9PSAiQmxhY2siKSAlPiUKICBzZWxlY3QoLUNvdW50LCAtUmVzdWx0KSAlPiUKICBhcnJhbmdlKGRlc2MoV2lucmF0ZSkpICU+JQogIGhlYWQoMTApICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoT3BlbmluZywgV2lucmF0ZSksIHkgPSBXaW5yYXRlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiSWRlbnRpdHkiLCB3aWR0aCA9IDAuNikgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUb3AgMTAgV2luLXJhdGVzIG9mIE9wZW5pbmdzIFBsYXllZCBhcyBCbGFjayIsCiAgICB4ID0gIk9wZW5pbmciLAogICAgeSA9ICJXaW4tUmF0ZSBpbiBQZXJjZW50YWdlcyglKSIKICApICsKICB0aGVtZV9saWdodCgpCgpncmlkLmFycmFuZ2Uob3B3LCBvcGIpCmBgYAoK