# Import the required libraries
library(tidyverse)
library(dplyr)
# Import the data from the file
data <- read.csv("~/Documents/Rdocs/matches.csv", stringsAsFactors = TRUE)
# Structure of the data
str(data)
'data.frame': 1095 obs. of 20 variables:
$ id : int 335982 335983 335984 335985 335986 335987 335988 335989 335990 335991 ...
$ season : Factor w/ 17 levels "2007/08","2009",..: 1 1 1 1 1 1 1 1 1 1 ...
$ city : Factor w/ 36 levels "Abu Dhabi","Ahmedabad",..: 3 8 11 27 24 19 17 9 17 8 ...
$ date : Factor w/ 823 levels "2008-04-18","2008-04-19",..: 1 2 2 3 3 4 5 6 7 8 ...
$ match_type : Factor w/ 8 levels "3rd Place Play-Off",..: 5 5 5 5 5 5 5 5 5 5 ...
$ player_of_match: Factor w/ 291 levels "A Chandila","A Kumble",..: 38 151 152 175 58 263 278 158 288 114 ...
$ venue : Factor w/ 58 levels "Arun Jaitley Stadium",..: 24 41 17 56 15 47 43 28 43 41 ...
$ team1 : Factor w/ 19 levels "Chennai Super Kings",..: 17 7 4 11 9 14 2 1 2 7 ...
$ team2 : Factor w/ 19 levels "Chennai Super Kings",..: 9 1 14 17 2 7 4 11 14 11 ...
$ toss_winner : Factor w/ 19 levels "Chennai Super Kings",..: 17 1 14 11 2 7 2 11 14 11 ...
$ toss_decision : Factor w/ 2 levels "bat","field": 2 1 1 1 1 1 1 2 2 2 ...
$ winner : Factor w/ 19 levels "Chennai Super Kings",..: 9 1 4 17 9 14 4 1 14 7 ...
$ result : Factor w/ 4 levels "no result","runs",..: 2 2 4 4 4 4 4 2 4 2 ...
$ result_margin : int 140 33 9 5 5 6 9 6 3 66 ...
$ target_runs : int 223 241 130 166 111 167 143 209 215 183 ...
$ target_overs : num 20 20 20 20 20 20 20 20 20 20 ...
$ super_over : Factor w/ 2 levels "N","Y": 1 1 1 1 1 1 1 1 1 1 ...
$ method : Factor w/ 1 level "D/L": NA NA NA NA NA NA NA NA NA NA ...
$ umpire1 : Factor w/ 62 levels "A Deshmukh","A Nand Kishore",..: 8 35 6 52 11 6 25 19 8 6 ...
$ umpire2 : Factor w/ 62 levels "A Deshmukh","A Nand Kishore",..: 42 53 16 15 25 41 5 16 31 5 ...
Head of the data
# it gives first few rows of the data
head(data)
1. Grouping the data
a) Group by match type and season
# Lets group the data by match types and seasons.And calculate the average result margin,target overs and runs across the seasons in various match types.
match_type_season_summary <- data |>
group_by(match_type,season) |>
summarise(
Avg_result_margin = mean(result_margin),
Avg_target_overs = mean(target_overs),
Median_target_runs = median(target_runs)
)
`summarise()` has grouped output by 'match_type'. You can override using the `.groups` argument.
Lets create a visualization for better understanding.
# Here I am checking the average result margin of matches over seasons by match type.
match_type_season_densitymap <- ggplot(match_type_season_summary, aes(x = season, y = match_type, fill = Avg_result_margin)) +
geom_tile() +
scale_fill_gradient(low = "lightblue", high = "darkblue") +
labs(title = "Average Result Margin of matches over seasons by match_type",
x = "season",
y = "match_type",
fill = "Avg_result_margin") +
theme_minimal()
# Display the densitymap
print(match_type_season_densitymap)

Matches played in finals have been close encounters as the average
result margin is low compared to that of eliminators.
We can see that there are 2 close range matches and 2 moderate
matches in eliminator, but in finals only one match has high average
result margin.
b) Group by city and result
# Lets group the data by city and result. And check in which city , most of the matches are won by runs
city_result_summary <- data |>
group_by(city, result) |>
summarise(
Avg_result_margin = mean(result_margin),
Avg_target_overs = mean(target_overs),
Median_target_runs = median(target_runs)
)
`summarise()` has grouped output by 'city'. You can override using the `.groups` argument.
Lets create a visualization for better understanding.
# lets create a bubble graph for cities by results with Average result margin and Median target runs
city_result_graph <- ggplot(city_result_summary, aes(x = Avg_result_margin, y = Median_target_runs, size = Avg_target_overs, color = result)) +
geom_point(alpha = 0.7) +
scale_size_continuous(range = c(3, 5)) +
labs(title = "Cities by results with Average result margin and Median target runs",
x = "Avg_result_margin ",
y = "Median_target_runs",
size = "Avg_target_overs",
color = "Genre") +
theme_minimal()
print(city_result_graph)
Warning: Removed 14 rows containing missing values or values outside the scale range (`geom_point()`).

We can say that there are more matches won by wickets in close range
matches for various cities than to that of runs.
We can also say that there are more matches with median target runs
around 150 end up winning by runs in various cities.
c) Group by result margin and result
result_margin_result_summary <- data |>
mutate(result_margin_range = cut(result_margin,breaks = c(0, 50, 100, 150, 200, Inf), labels = c("0-50", "50-100", "100-150", "150-200", "200-300"))) |>
group_by(result_margin_range, result) |>
summarise(
Avg_target_runs = mean(target_runs),
Avg_target_overs = mean(target_overs)
)
`summarise()` has grouped output by 'result_margin_range'. You can override using the `.groups` argument.
Lets calculate average target runs for result margin by result
#lets use bar graph for visualization
result_margin_result_bar <- ggplot(result_margin_result_summary, aes(x = result_margin_range, y = Avg_target_runs, fill = result)) +
geom_bar(stat = "identity") +
labs(title = "Average target runs for result margin by result",
x = "result_margin_range ",
y = " Avg_target_runs",
fill = "result") +
theme_minimal()
# Display the stacked bar chart
print(result_margin_result_bar)
Warning: Removed 1 row containing missing values or values outside the scale range (`geom_bar()`).

From this, we can conclude that, most of the matches which are won
by runs have average target runs of 200.
Matches that were won by wickets are close range encounters as the
result margin is low.
Lowest Probabilities
lowest_probability <- data |>
group_by(season) |>
summarise(Probability = n() / nrow(data)) |>
arrange(Probability) |>
slice(1)
# Attach lowest probabilitity to the data
data <- data |>
mutate(Lowest_Probability = ifelse(season %in% lowest_probability$season, "Lowest Probability", "Normal"))
# Lets view the data to select two categorical values and find the probability for combination of them.
head(data)
Lets find probability of specific combinations.
But first lets check missing values of season and result values in
dataset to avoid ambiguity.
existing_combinations <- unique(select(data, season, result))
# Create a dataframe of all possible combinations of Genre and Year
all_combinations <- expand.grid(season = unique(data$season), result = unique(data$result))
# Find missing combinations
missing_combinations <- anti_join(all_combinations, existing_combinations)
Joining with `by = join_by(season, result)`
print(missing_combinations)
There are 21 missing values in this combination. Lets take
season-result pair and find their occurance.
# Lets create a group of season by result
combination_count <- data |>
group_by(season, result) |>
summarise(Count = n())
`summarise()` has grouped output by 'season'. You can override using the `.groups` argument.
# Lets arrange it to find the combinations.
combination_count <- combination_count |>
arrange(desc(Count))
print(combination_count)
Now we can find which combinations occur frequently and rarely.
From this we can say that, in 2012 there are 40 matches won by
wickets.And in 2015 there are only 24 matches won by wickets.

The most frequent combinations are 2023-runs and 2012-wickets.
Similarly, we can find lowest probable combination.
From this graph, we can also say that the lowest probable set is
2016-runs.
If we try to find a combination 2012-tie, we could not retrieve the
data.This may be because of multiple issues like the below.
Data collection Errors, Data Entry Errors, Logical constraints Ex:
non existance of that pair in real world.
In our case it is either of these issues.
LS0tCnRpdGxlOiAiQWhsYWRfV2VlazMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQojIEltcG9ydCB0aGUgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRwbHlyKQpgYGAKCmBgYHtyfQojIEltcG9ydCB0aGUgZGF0YSBmcm9tIHRoZSBmaWxlCmRhdGEgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1Jkb2NzL21hdGNoZXMuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IFRSVUUpCmBgYAoKYGBge3J9CiMgU3RydWN0dXJlIG9mIHRoZSBkYXRhCnN0cihkYXRhKQpgYGAKIyBIZWFkIG9mIHRoZSBkYXRhIApgYGB7cn0KIyBpdCBnaXZlcyBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZGF0YQpoZWFkKGRhdGEpCmBgYAoKIyAxLiBHcm91cGluZyB0aGUgZGF0YQojIyBhKSBHcm91cCBieSBtYXRjaCB0eXBlIGFuZCBzZWFzb24KCmBgYHtyfQojIExldHMgZ3JvdXAgdGhlIGRhdGEgYnkgbWF0Y2ggdHlwZXMgYW5kIHNlYXNvbnMuQW5kIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSByZXN1bHQgbWFyZ2luLHRhcmdldCBvdmVycyBhbmQgcnVucyBhY3Jvc3MgdGhlIHNlYXNvbnMgaW4gdmFyaW91cyBtYXRjaCB0eXBlcy4KbWF0Y2hfdHlwZV9zZWFzb25fc3VtbWFyeSA8LSBkYXRhIHw+CiAgZ3JvdXBfYnkobWF0Y2hfdHlwZSxzZWFzb24pIHw+CiAgc3VtbWFyaXNlKAogICAgQXZnX3Jlc3VsdF9tYXJnaW4gPSBtZWFuKHJlc3VsdF9tYXJnaW4pLAogICAgQXZnX3RhcmdldF9vdmVycyA9IG1lYW4odGFyZ2V0X292ZXJzKSwKICAgIE1lZGlhbl90YXJnZXRfcnVucyA9IG1lZGlhbih0YXJnZXRfcnVucykKICApCmBgYAoKIyMjIExldHMgY3JlYXRlIGEgdmlzdWFsaXphdGlvbiBmb3IgYmV0dGVyIHVuZGVyc3RhbmRpbmcuCgpgYGB7cn0KIyBIZXJlIEkgYW0gY2hlY2tpbmcgdGhlIGF2ZXJhZ2UgcmVzdWx0IG1hcmdpbiBvZiBtYXRjaGVzIG92ZXIgc2Vhc29ucyBieSBtYXRjaCB0eXBlLgptYXRjaF90eXBlX3NlYXNvbl9kZW5zaXR5bWFwIDwtIGdncGxvdChtYXRjaF90eXBlX3NlYXNvbl9zdW1tYXJ5LCBhZXMoeCA9IHNlYXNvbiwgeSA9IG1hdGNoX3R5cGUsIGZpbGwgPSBBdmdfcmVzdWx0X21hcmdpbikpICsKICBnZW9tX3RpbGUoKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAibGlnaHRibHVlIiwgaGlnaCA9ICJkYXJrYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgUmVzdWx0IE1hcmdpbiBvZiBtYXRjaGVzIG92ZXIgc2Vhc29ucyBieSBtYXRjaF90eXBlIiwKICAgICAgIHggPSAic2Vhc29uIiwKICAgICAgIHkgPSAibWF0Y2hfdHlwZSIsCiAgICAgICBmaWxsID0gIkF2Z19yZXN1bHRfbWFyZ2luIikgKwogIHRoZW1lX21pbmltYWwoKQoKIyBEaXNwbGF5IHRoZSBkZW5zaXR5bWFwCnByaW50KG1hdGNoX3R5cGVfc2Vhc29uX2RlbnNpdHltYXApCgpgYGAKCiMjIyBNYXRjaGVzIHBsYXllZCBpbiBmaW5hbHMgaGF2ZSBiZWVuIGNsb3NlIGVuY291bnRlcnMgYXMgdGhlIGF2ZXJhZ2UgcmVzdWx0IG1hcmdpbiBpcyBsb3cgY29tcGFyZWQgdG8gdGhhdCBvZiBlbGltaW5hdG9ycy4KIyMjIFdlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgMiBjbG9zZSByYW5nZSBtYXRjaGVzIGFuZCAyIG1vZGVyYXRlIG1hdGNoZXMgaW4gZWxpbWluYXRvciwgYnV0IGluIGZpbmFscyBvbmx5IG9uZSBtYXRjaCBoYXMgaGlnaCBhdmVyYWdlIHJlc3VsdCBtYXJnaW4uCgoKIyMgYikgR3JvdXAgYnkgY2l0eSBhbmQgcmVzdWx0CgpgYGB7cn0KIyBMZXRzIGdyb3VwIHRoZSBkYXRhIGJ5IGNpdHkgYW5kIHJlc3VsdC4gQW5kIGNoZWNrIGluIHdoaWNoIGNpdHkgLCBtb3N0IG9mIHRoZSBtYXRjaGVzIGFyZSB3b24gYnkgcnVucwpjaXR5X3Jlc3VsdF9zdW1tYXJ5IDwtIGRhdGEgfD4KICBncm91cF9ieShjaXR5LCByZXN1bHQpIHw+CiAgc3VtbWFyaXNlKAogICAgQXZnX3Jlc3VsdF9tYXJnaW4gPSBtZWFuKHJlc3VsdF9tYXJnaW4pLAogICAgQXZnX3RhcmdldF9vdmVycyA9IG1lYW4odGFyZ2V0X292ZXJzKSwKICAgIE1lZGlhbl90YXJnZXRfcnVucyA9IG1lZGlhbih0YXJnZXRfcnVucykKICApCmBgYAojIyMgTGV0cyBjcmVhdGUgYSB2aXN1YWxpemF0aW9uIGZvciBiZXR0ZXIgdW5kZXJzdGFuZGluZy4KCgpgYGB7cn0KIyBsZXRzIGNyZWF0ZSBhIGJ1YmJsZSBncmFwaCBmb3IgY2l0aWVzIGJ5IHJlc3VsdHMgd2l0aCBBdmVyYWdlIHJlc3VsdCBtYXJnaW4gYW5kIE1lZGlhbiB0YXJnZXQgcnVucwpjaXR5X3Jlc3VsdF9ncmFwaCA8LSBnZ3Bsb3QoY2l0eV9yZXN1bHRfc3VtbWFyeSwgYWVzKHggPSBBdmdfcmVzdWx0X21hcmdpbiwgeSA9IE1lZGlhbl90YXJnZXRfcnVucywgc2l6ZSA9IEF2Z190YXJnZXRfb3ZlcnMsIGNvbG9yID0gcmVzdWx0KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjcpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDMsIDUpKSArCiAgbGFicyh0aXRsZSA9ICJDaXRpZXMgYnkgcmVzdWx0cyB3aXRoIEF2ZXJhZ2UgcmVzdWx0IG1hcmdpbiBhbmQgTWVkaWFuIHRhcmdldCBydW5zIiwKICAgICAgIHggPSAiQXZnX3Jlc3VsdF9tYXJnaW4gIiwKICAgICAgIHkgPSAiTWVkaWFuX3RhcmdldF9ydW5zIiwKICAgICAgIHNpemUgPSAiQXZnX3RhcmdldF9vdmVycyIsCiAgICAgICBjb2xvciA9ICJHZW5yZSIpICsKICB0aGVtZV9taW5pbWFsKCkKCnByaW50KGNpdHlfcmVzdWx0X2dyYXBoKQpgYGAKCiMjIyBXZSBjYW4gc2F5IHRoYXQgdGhlcmUgYXJlIG1vcmUgbWF0Y2hlcyB3b24gYnkgd2lja2V0cyBpbiBjbG9zZSByYW5nZSBtYXRjaGVzIGZvciB2YXJpb3VzIGNpdGllcyB0aGFuIHRvIHRoYXQgb2YgcnVucy4KIyMjIFdlIGNhbiBhbHNvIHNheSB0aGF0IHRoZXJlIGFyZSBtb3JlIG1hdGNoZXMgd2l0aCBtZWRpYW4gdGFyZ2V0IHJ1bnMgYXJvdW5kIDE1MCBlbmQgdXAgd2lubmluZyBieSBydW5zIGluIHZhcmlvdXMgY2l0aWVzLgoKIyMgYykgR3JvdXAgYnkgcmVzdWx0IG1hcmdpbiBhbmQgcmVzdWx0CmBgYHtyfQpyZXN1bHRfbWFyZ2luX3Jlc3VsdF9zdW1tYXJ5IDwtIGRhdGEgfD4KICBtdXRhdGUocmVzdWx0X21hcmdpbl9yYW5nZSA9IGN1dChyZXN1bHRfbWFyZ2luLGJyZWFrcyA9IGMoMCwgNTAsIDEwMCwgMTUwLCAyMDAsIEluZiksIGxhYmVscyA9IGMoIjAtNTAiLCAiNTAtMTAwIiwgIjEwMC0xNTAiLCAiMTUwLTIwMCIsICIyMDAtMzAwIikpKSB8PgogIGdyb3VwX2J5KHJlc3VsdF9tYXJnaW5fcmFuZ2UsIHJlc3VsdCkgfD4KICBzdW1tYXJpc2UoCiAgICBBdmdfdGFyZ2V0X3J1bnMgPSBtZWFuKHRhcmdldF9ydW5zKSwKICAgIEF2Z190YXJnZXRfb3ZlcnMgPSBtZWFuKHRhcmdldF9vdmVycykKICApCmBgYAojIyMgTGV0cyBjYWxjdWxhdGUgYXZlcmFnZSB0YXJnZXQgcnVucyBmb3IgcmVzdWx0IG1hcmdpbiBieSByZXN1bHQKYGBge3J9CiNsZXRzIHVzZSBiYXIgZ3JhcGggZm9yIHZpc3VhbGl6YXRpb24KcmVzdWx0X21hcmdpbl9yZXN1bHRfYmFyIDwtIGdncGxvdChyZXN1bHRfbWFyZ2luX3Jlc3VsdF9zdW1tYXJ5LCBhZXMoeCA9IHJlc3VsdF9tYXJnaW5fcmFuZ2UsIHkgPSBBdmdfdGFyZ2V0X3J1bnMsIGZpbGwgPSByZXN1bHQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgdGFyZ2V0IHJ1bnMgZm9yIHJlc3VsdCBtYXJnaW4gYnkgcmVzdWx0IiwKICAgICAgIHggPSAicmVzdWx0X21hcmdpbl9yYW5nZSAiLAogICAgICAgeSA9ICIgQXZnX3RhcmdldF9ydW5zIiwKICAgICAgIGZpbGwgPSAicmVzdWx0IikgKwogIHRoZW1lX21pbmltYWwoKQoKIyBEaXNwbGF5IHRoZSBzdGFja2VkIGJhciBjaGFydApwcmludChyZXN1bHRfbWFyZ2luX3Jlc3VsdF9iYXIpCmBgYAoKIyMjIEZyb20gdGhpcywgd2UgY2FuIGNvbmNsdWRlIHRoYXQsIG1vc3Qgb2YgdGhlIG1hdGNoZXMgd2hpY2ggYXJlIHdvbiBieSBydW5zIGhhdmUgYXZlcmFnZSB0YXJnZXQgcnVucyBvZiAyMDAuIAojIyMgTWF0Y2hlcyB0aGF0IHdlcmUgd29uIGJ5IHdpY2tldHMgYXJlIGNsb3NlIHJhbmdlIGVuY291bnRlcnMgYXMgdGhlIHJlc3VsdCBtYXJnaW4gaXMgbG93LgoKCiMgTG93ZXN0IFByb2JhYmlsaXRpZXMKYGBge3J9Cmxvd2VzdF9wcm9iYWJpbGl0eSA8LSBkYXRhIHw+CiAgZ3JvdXBfYnkoc2Vhc29uKSB8PgogIHN1bW1hcmlzZShQcm9iYWJpbGl0eSA9IG4oKSAvIG5yb3coZGF0YSkpIHw+CiAgYXJyYW5nZShQcm9iYWJpbGl0eSkgfD4KICBzbGljZSgxKQojIEF0dGFjaCBsb3dlc3QgcHJvYmFiaWxpdGl0eSB0byB0aGUgZGF0YQpkYXRhIDwtIGRhdGEgfD4KICBtdXRhdGUoTG93ZXN0X1Byb2JhYmlsaXR5ID0gaWZlbHNlKHNlYXNvbiAlaW4lIGxvd2VzdF9wcm9iYWJpbGl0eSRzZWFzb24sICJMb3dlc3QgUHJvYmFiaWxpdHkiLCAiTm9ybWFsIikpCgojIExldHMgdmlldyB0aGUgZGF0YSB0byBzZWxlY3QgdHdvIGNhdGVnb3JpY2FsIHZhbHVlcyBhbmQgZmluZCB0aGUgcHJvYmFiaWxpdHkgZm9yIGNvbWJpbmF0aW9uIG9mIHRoZW0uCmhlYWQoZGF0YSkKYGBgCgojIyBMZXRzIGZpbmQgcHJvYmFiaWxpdHkgb2Ygc3BlY2lmaWMgY29tYmluYXRpb25zLgojIyMgQnV0IGZpcnN0IGxldHMgY2hlY2sgbWlzc2luZyB2YWx1ZXMgb2Ygc2Vhc29uIGFuZCByZXN1bHQgdmFsdWVzIGluIGRhdGFzZXQgdG8gYXZvaWQgYW1iaWd1aXR5LgoKYGBge3J9CmV4aXN0aW5nX2NvbWJpbmF0aW9ucyA8LSB1bmlxdWUoc2VsZWN0KGRhdGEsIHNlYXNvbiwgcmVzdWx0KSkKCiMgQ3JlYXRlIGEgZGF0YWZyYW1lIG9mIGFsbCBwb3NzaWJsZSBjb21iaW5hdGlvbnMgb2YgR2VucmUgYW5kIFllYXIKYWxsX2NvbWJpbmF0aW9ucyA8LSBleHBhbmQuZ3JpZChzZWFzb24gPSB1bmlxdWUoZGF0YSRzZWFzb24pLCByZXN1bHQgPSB1bmlxdWUoZGF0YSRyZXN1bHQpKQoKIyBGaW5kIG1pc3NpbmcgY29tYmluYXRpb25zCm1pc3NpbmdfY29tYmluYXRpb25zIDwtIGFudGlfam9pbihhbGxfY29tYmluYXRpb25zLCBleGlzdGluZ19jb21iaW5hdGlvbnMpCgpwcmludChtaXNzaW5nX2NvbWJpbmF0aW9ucykKYGBgCgojIyMgVGhlcmUgYXJlIDIxIG1pc3NpbmcgdmFsdWVzIGluIHRoaXMgY29tYmluYXRpb24uIExldHMgdGFrZSBzZWFzb24tcmVzdWx0IHBhaXIgYW5kIGZpbmQgdGhlaXIgb2NjdXJhbmNlLgoKYGBge3J9CiMgTGV0cyBjcmVhdGUgYSBncm91cCBvZiBzZWFzb24gYnkgcmVzdWx0CmNvbWJpbmF0aW9uX2NvdW50IDwtIGRhdGEgfD4KICBncm91cF9ieShzZWFzb24sIHJlc3VsdCkgfD4KICBzdW1tYXJpc2UoQ291bnQgPSBuKCkpCmBgYAoKYGBge3J9CiMgTGV0cyBhcnJhbmdlIGl0IHRvIGZpbmQgdGhlIGNvbWJpbmF0aW9ucy4KY29tYmluYXRpb25fY291bnQgPC0gY29tYmluYXRpb25fY291bnQgfD4KICBhcnJhbmdlKGRlc2MoQ291bnQpKQoKcHJpbnQoY29tYmluYXRpb25fY291bnQpCmBgYAoKIyMgTm93IHdlIGNhbiBmaW5kIHdoaWNoIGNvbWJpbmF0aW9ucyBvY2N1ciBmcmVxdWVudGx5IGFuZCByYXJlbHkuCiMjIEZyb20gdGhpcyB3ZSBjYW4gc2F5IHRoYXQsIGluIDIwMTIgdGhlcmUgYXJlIDQwIG1hdGNoZXMgd29uIGJ5IHdpY2tldHMuQW5kIGluIDIwMTUgdGhlcmUgYXJlIG9ubHkgMjQgbWF0Y2hlcyB3b24gYnkgd2lja2V0cy4KCmBgYHtyfQojTGV0cyB2aXN1YWxpemUgdG8gZ2V0IGNsZWFyIHBpY3R1cmUuCm1vc3RfY29tbW9uX2NvbWJpbmF0aW9ucyA8LSBjb21iaW5hdGlvbl9jb3VudCB8PgogIHNsaWNlX21heChvcmRlcl9ieSA9IENvdW50LCBuID0gNTApIAoKbW9zdF9jb21tb25fY29tYmluYXRpb25zX3Bsb3QgPC0gZ2dwbG90KG1vc3RfY29tbW9uX2NvbWJpbmF0aW9ucywgYWVzKHggPSBmY3RfcmVvcmRlcihwYXN0ZShzZWFzb24sIHJlc3VsdCksIENvdW50KSwgeSA9IENvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgTW9zdCBDb21tb24gQ29tYmluYXRpb25zIiwKICAgICAgIHggPSAiU2Vhc29uLVJlc3VsdCBDb21iaW5hdGlvbiIsCiAgICAgICB5ID0gIkZyZXF1ZW5jeSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEsIHZqdXN0ID0gMSkpCgpwcmludChtb3N0X2NvbW1vbl9jb21iaW5hdGlvbnNfcGxvdCkKYGBgCiMjIFRoZSBtb3N0IGZyZXF1ZW50IGNvbWJpbmF0aW9ucyBhcmUgMjAyMy1ydW5zIGFuZCAyMDEyLXdpY2tldHMuCiMjIFNpbWlsYXJseSwgd2UgY2FuIGZpbmQgbG93ZXN0IHByb2JhYmxlIGNvbWJpbmF0aW9uLgojIyBGcm9tIHRoaXMgZ3JhcGgsIHdlIGNhbiBhbHNvIHNheSB0aGF0IHRoZSBsb3dlc3QgcHJvYmFibGUgc2V0IGlzIDIwMTYtcnVucy4KCiMjIyBJZiB3ZSB0cnkgdG8gZmluZCBhIGNvbWJpbmF0aW9uIDIwMTItdGllLCB3ZSBjb3VsZCBub3QgcmV0cmlldmUgdGhlIGRhdGEuVGhpcyBtYXkgYmUgYmVjYXVzZSBvZiBtdWx0aXBsZSBpc3N1ZXMgbGlrZSB0aGUgYmVsb3cuCiMjIyBEYXRhIGNvbGxlY3Rpb24gRXJyb3JzLCBEYXRhIEVudHJ5IEVycm9ycywgTG9naWNhbCBjb25zdHJhaW50cyBFeDogbm9uIGV4aXN0YW5jZSBvZiB0aGF0IHBhaXIgaW4gcmVhbCB3b3JsZC4gCiMjIyBJbiBvdXIgY2FzZSBpdCBpcyBlaXRoZXIgb2YgdGhlc2UgaXNzdWVzLgoK