Introduction
For starters, this report was made using the coding language known as
R, with the objective of finding out which variables determine
the success of a movie. To seek to find this answers, we used the csv
file known as movies_metadata.csv. This csv file was
obtained from Kaggle (https://www.kaggle.com/datasets/rounakbanik/the-movies-dataset/data),
and it contains a registry of over 45,000 movies, 270,000 users and over
26 million ratings. This is important, since we are looking to find
concrete answers to our question, and so using a big amount of data will
make our results more accurate.
Objectives and Variables
As previously mentioned, the main objective is to determine what
makes (or doesn’t make) a movie successful. To do this, we looked at the
variables within this dataset. These variables are the following: adult,
belongs_to_collection, budget, genres homepage, id, imdb_id,
original_language, original_title, overview, popularity, poster_path,
production_companies, production_countries, release_date, revenue,
runtime, spoken_languages, status, tagline, title video, vote_average
and vote_count. These variables range from descriptions to numerical
values, so we had to assign them a different value and judge them
differently from each other. Obviously, to determine the success of a
movie, we did not necessarily need to utilize all of these variables,
and so to do this, a cleaning process had to be made.
Cleaning Process
For this cleaning process, we had to elaborate codes with the
objective of filtering out data that is either incorrect, invalid or
simply unnecessary for our analysis. To ensure that our data is as
well-arranged as possible, I began by ordering the columns by
importance, in the manner that I thought would be easiest to understand
for the reader. Because of this, the first 2 columns are the name of the
movie, and the identification number. After this, I continued by
checking for NA values. This refers to values that weren’t recorded
properly, and so they make the analysis extremely complicated. Because
of this, I deleted these values. Next, I checked for duplicate rows, and
logically deleted the copies, to make sure that there is only one row
for each movie. Then I continued by cleaning the columns individually:
Adult: All values were assigned to either True or False. Runtime:
Deleted rows that had impossible runtimes. (Ex. 0 or 1984920 minutes.)
Vote_Average: Gave the average rating to rows with a value of 0.
Collection: Deleted the parts of the column that I deemed unnecessary
(Ex. Parentheses and Collection IDs) Genres, Companies, Countries,
Languages: I separated the different values assigned to the movie into
different columns, as well as graphed the top 20 of each category.
Poster_Path, Tagline, Video: I deleted these columns since I deemed them
unnecessary. The remaining columns were left untouched, since I
considered that they were both clean, and relevant to the analysis I was
trying to do.
//////////
# Checking for NAs
columns_to_check <- c("budget", "genres", "homepage", "id", "imdb_id", "original_language",
"original_title", "overview", "popularity", "poster_path",
"production_companies", "production_countries", "release_date",
"revenue", "runtime", "spoken_languages", "status",
"title", "video", "vote_average", "vote_count", "adult")
missing_rows <- which(!complete.cases(movies[, columns_to_check]))
num_missing_rows <- length(missing_rows)
print(paste("Number of missing rows:", num_missing_rows))
## [1] "Number of missing rows: 263"
print("Indices of missing rows:")
## [1] "Indices of missing rows:"
print(missing_rows)
## [1] 635 636 645 803 864 2141 13563 13577 13661 13758 14770 14891
## [13] 15246 15385 15734 16902 17318 17491 17952 18039 18573 18673 18917 18969
## [25] 19316 19372 19730 19731 19875 20167 20380 20643 20712 20827 21103 21251
## [37] 21985 22314 22347 22425 22664 22819 23039 23227 23419 23421 23830 24231
## [49] 25204 25505 25508 25512 25515 25562 25631 25678 25912 25938 26075 27881
## [61] 27968 28133 28246 28274 28277 28416 28658 28801 28952 28965 29228 29265
## [73] 29301 29308 29309 29310 29312 29449 29451 29503 29504 30357 30380 30386
## [85] 30783 30790 30828 30945 31011 31057 31230 31359 31416 31533 31544 31545
## [97] 31557 31581 31588 31589 32004 32065 32156 32177 32424 32498 32499 32509
## [109] 32637 33004 33529 33532 34398 34447 34527 34558 34606 34672 34703 34860
## [121] 35036 35164 35217 35314 35492 35518 35587 35588 35653 35661 35691 35982
## [133] 36218 36348 36352 36403 36422 36461 36592 36858 36864 36900 37077 37085
## [145] 37151 37157 37186 37210 37215 37242 37275 37405 37451 37472 37488 37491
## [157] 37641 37642 37754 37755 37814 38101 38182 38360 38402 38415 39144 39271
## [169] 39302 39365 39367 39497 39568 39678 39721 39723 39852 39971 39972 40152
## [181] 40204 40207 40379 40577 40726 40776 40887 41046 41068 41069 41079 41368
## [193] 41369 41371 41373 41377 41379 41400 41659 41696 41699 41719 41833 41888
## [205] 41922 41923 42069 42150 42151 42198 42199 42258 42290 42298 42321 42345
## [217] 42574 42776 42848 43107 43111 43129 43203 43393 43470 43471 43477 43481
## [229] 43487 43488 43533 43597 43674 43682 43942 43950 43964 43986 44017 44066
## [241] 44121 44152 44383 44395 44424 44560 44568 44574 44593 44784 44878 44912
## [253] 44960 44989 45016 45055 45063 45232 45247 45311 45314 45378 45411
# Cleaning NAs
movies_clean <- movies[complete.cases(movies[, columns_to_check]), ]
print("Dimensions of cleaned dataframe:")
## [1] "Dimensions of cleaned dataframe:"
print(dim(movies_clean))
## [1] 45203 24
//////////
/////////
movies_clean$adult <- ifelse(movies_clean$adult != "True" & movies_clean$adult != "False", "False", movies_clean$adult)
//////////
//////////
//////////
//////////
Statistical and Analytical Techniques
After concluding the cleaning process, I began to graph the data into
charts and plots. The first 4 graphs I made were the ones I mentioned
previously. They contain the 20 most common Genres, Companies, Countries
and Languages. These graphs are extremely simple, but I considered them
to be essential to the analysis, since they represent the majority of
the population. Values that are smaller tend to be much less
significant, and so the most popular values in these columns are of the
utmost importance. These are the graphs I obtained:
barplot(top_20_studios, main = "Top 20 Most Common Studios", xlab = "Studios", ylab = "Count", las = 2, col = "forestgreen")

# New countries (Top 20 countries graph)
country_counts <- table(movies_clean$production_countries)
new_countries <- str_split_fixed(movies_clean$production_countries, "\\},", n = Inf)
new_countries <- new_countries[, 1:7]
new_countries <- as.data.frame(new_countries)
new_countries <- new_countries %>%
mutate(country1 = str_extract(V1, "'name':\\s+'([[:alnum:]\\s]+)'"),
country2 = str_extract(V2, "'name':\\s+'([[:alnum:]\\s]+)'"),
country3 = str_extract(V3, "'name':\\s+'([[:alnum:]\\s]+)'"),
country4 = str_extract(V4, "'name':\\s+'([[:alnum:]\\s]+)'"),
country5 = str_extract(V5, "'name':\\s+'([[:alnum:]\\s]+)'"),
country6 = str_extract(V6, "'name':\\s+'([[:alnum:]\\s]+)'"),
country7 = str_extract(V7, "'name':\\s+'([[:alnum:]\\s]+)'"))
new_countries$country1 <- str_remove(new_countries$country1, "'name':\\s+")
new_countries$country2 <- str_remove(new_countries$country2, "'name':\\s+")
new_countries$country3 <- str_remove(new_countries$country3, "'name':\\s+")
new_countries$country4 <- str_remove(new_countries$country4, "'name':\\s+")
new_countries$country5 <- str_remove(new_countries$country5, "'name':\\s+")
new_countries$country6 <- str_remove(new_countries$country6, "'name':\\s+")
new_countries$country7 <- str_remove(new_countries$country7, "'name':\\s+")
all_countries <- c(new_countries$country1, new_countries$country2, new_countries$country3,
new_countries$country4, new_countries$country5, new_countries$country6,
new_countries$country7)
country_counts <- table(all_countries)
country_counts <- sort(country_counts, decreasing = TRUE)
top_20_countries <- head(country_counts, 20)
print("Counts of Each Country:")
## [1] "Counts of Each Country:"
print(top_20_countries)
## all_countries
## 'United States of America' 'United Kingdom'
## 21128 4084
## 'France' 'Germany'
## 3915 2211
## 'Italy' 'Canada'
## 2132 1762
## 'Japan' 'Spain'
## 1642 944
## 'Russia' 'India'
## 907 826
## 'Hong Kong' 'Sweden'
## 595 579
## 'Australia' 'South Korea'
## 570 493
## 'Belgium' 'Denmark'
## 443 384
## 'China' 'Netherlands'
## 372 372
## 'Finland' 'Mexico'
## 371 325
barplot(top_20_countries, main = "Top 20 Most Common Countries", xlab = "Countries", ylab = "Count", las = 2, col = "red")

# New languages (Top 20 languages graph)
new_languages <- str_split_fixed(movies_clean$spoken_languages, "\\},", n = Inf)
new_languages <- new_languages[, 1:7]
new_languages <- as.data.frame(new_languages)
new_languages <- new_languages %>%
mutate(language1 = str_extract(V1, "'name':\\s+'([[:alnum:]\\s]+)'"),
language2 = str_extract(V2, "'name':\\s+'([[:alnum:]\\s]+)'"),
language3 = str_extract(V3, "'name':\\s+'([[:alnum:]\\s]+)'"),
language4 = str_extract(V4, "'name':\\s+'([[:alnum:]\\s]+)'"),
language5 = str_extract(V5, "'name':\\s+'([[:alnum:]\\s]+)'"),
language6 = str_extract(V6, "'name':\\s+'([[:alnum:]\\s]+)'"),
language7 = str_extract(V7, "'name':\\s+'([[:alnum:]\\s]+)'"))
new_languages$language1 <- str_remove(new_languages$language1, "'name':\\s+")
new_languages$language2 <- str_remove(new_languages$language2, "'name':\\s+")
new_languages$language3 <- str_remove(new_languages$language3, "'name':\\s+")
new_languages$language4 <- str_remove(new_languages$language4, "'name':\\s+")
new_languages$language5 <- str_remove(new_languages$language5, "'name':\\s+")
new_languages$language6 <- str_remove(new_languages$language6, "'name':\\s+")
new_languages$language7 <- str_remove(new_languages$language7, "'name':\\s+")
all_languages <- c(new_languages$language1, new_languages$language2, new_languages$language3,
new_languages$language4, new_languages$language5, new_languages$language6,
new_languages$language7)
language_counts <- table(all_languages)
language_counts <- sort(language_counts, decreasing = TRUE)
top_20_languages <- head(language_counts, 20)
print("Counts of Each Language:")
## [1] "Counts of Each Language:"
print(top_20_languages)
## all_languages
## 'English' 'Français' 'Deutsch' 'Español' 'Italiano'
## 28716 4173 2590 2387 2338
## '日本語' 'Pусский' '普通话' 'Português' 'svenska'
## 1755 1547 788 584 553
## 'Polski' 'suomi' 'Magyar' 'العربية' 'Nederlands'
## 520 360 359 340 333
## 'No Language' 'Dansk' 'Český' 'Türkçe' 'עִבְרִית'
## 319 301 283 238 214
barplot(top_20_languages, main = "Top 20 Most Common Spoken Languages", xlab = "Languages", ylab = "Count", las = 2, col = "skyblue")

Next, I made a table that gives you the name of the different
countries and obtains both the average revenue and runtime for each. I
considered that these values are also important, since different
countries tend to have different preferences when it comes to the
duration of films, and well as the fact that they have different amounts
of resources, which tends to have an impact on how much a movie earns in
sales. This is how this table looks like:
# Runtime and revenue data
all_countries <- c(new_countries$country1, new_countries$country2, new_countries$country3,
new_countries$country4, new_countries$country5, new_countries$country6,
new_countries$country7)
movie_country <- data.frame(movie_id = rep(movies_clean$id, each = 7), country = all_countries)
movie_country_revenue_runtime <- left_join(movie_country, movies_clean, by = c("movie_id" = "id"))
country_stats <- movie_country_revenue_runtime %>%
group_by(country) %>%
summarize(average_revenue = mean(revenue, na.rm = TRUE),
average_runtime = mean(runtime, na.rm = TRUE),
average_budget = mean(budget, na.rm = TRUE))
## Warning: There were 159 warnings in `summarize()`.
## The first warning was:
## ℹ In argument: `average_budget = mean(budget, na.rm = TRUE)`.
## ℹ In group 1: `country = "'Afghanistan'"`.
## Caused by warning in `mean.default()`:
## ! argument is not numeric or logical: returning NA
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 158 remaining warnings.
print(country_stats)
## # A tibble: 159 × 4
## country average_revenue average_runtime average_budget
## <chr> <dbl> <dbl> <dbl>
## 1 'Afghanistan' 18780959. 113. NA
## 2 'Albania' 0 95.3 NA
## 3 'Algeria' 65245073. 91.5 NA
## 4 'Angola' 41241269 90.3 NA
## 5 'Antarctica' 0 95 NA
## 6 'Argentina' 20087200. 104. NA
## 7 'Armenia' 37011790. 107. NA
## 8 'Aruba' 483333. 103. NA
## 9 'Australia' 30705248. 106. NA
## 10 'Austria' 17337497. 104. NA
## # ℹ 149 more rows
After obtaining this table, I graphed it in a scatter plot, where we
can see the top 20 countries by both revenue and runtime, as well as the
bottom 20 countries. These are the graphs:
# Highest runtime and revenues scatterplots
top_20_countries <- head(country_stats[order(country_stats$average_revenue, decreasing = TRUE),], 20)
ggplot(top_20_countries, aes(x = country, y = average_revenue)) +
geom_point() +
labs(title = "Top 20 Countries: Average Revenue",
x = "Country", y = "Average Revenue") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

top_20_countries <- head(country_stats[order(country_stats$average_runtime, decreasing = TRUE),], 20)
ggplot(top_20_countries, aes(x = country, y = average_runtime)) +
geom_point() +
labs(title = "Top 20 Countries: Average Runtime",
x = "Country", y = "Average Runtime") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

Finally, I obtained the average rating by the different studios, by
combining all of the results obtained from the different movies. To do
this, I made a filter to only include studios with at least 10 movies.
This helps us only look at important studios, since some studios might
only have 1 or 2 movies, which would increase the range of error in the
analysis. After obtaining this average, I graphed the top 20 highest and
lowest studios. This is how the graphs look like:
# Top 20 best and worst rated studios (at least 10 movies)
studio_ratings_filtered <- studio_ratings_filtered %>%
filter(!is.na(average_vote_average))
top_studios <- head(studio_ratings_filtered, 20)
bottom_studios <- tail(studio_ratings_filtered, 20)
ggplot(top_studios, aes(x = average_vote_average, y = reorder(studio, average_vote_average))) +
geom_bar(stat = "identity", fill = "darkblue") +
labs(title = "Top 20 Studios by Average Ratings (with at least 10 movies)",
x = "Average Vote Average", y = "Studio") +
theme(axis.text.y = element_text(angle = 0, hjust = 1))

ggplot(bottom_studios, aes(x = average_vote_average, y = reorder(studio, average_vote_average))) +
geom_bar(stat = "identity", fill = "orange") +
labs(title = "Bottom 20 Studios by Average Ratings (with at least 10 movies)",
x = "Average Vote Average", y = "Studio") +
theme(axis.text.y = element_text(angle = 0, hjust = 1))

Findings and Results
After these graphs and charts, we can finally view our findings. The
first finding we can see, is that the genre with the most movies is
Drama. Based on this, we can assume 2 things. First, that studios keep
making Drama-oriented movies because there is demand for this genre.
Based on this, we can assume that Drama is the most successful genre,
considering that there are over 18 thousand movies that have this genre
as one of their main identifiers.
For our next finding, we can see which studios are the most
successful. The top 3 studios in terms of movies made are Paramount, Fox
and Universal, which are extremely well known at a global level. The
interesting detail is that these 3 studios are all from the United
States, and not only that. Out of the top 10 studios with the most
movies made, 9 are from the US. This leads to the conclusion that movies
made in this country tend to have higher success rates than others. We
can see this graphically, since in the “Most Common Countries” graph,
the United States has over 10 times as many movies as the second place
(United Kingdom).
This same argument goes on towards the next graph. We can see that
the English language is the most popular by an incredibly wide margin.
This is not only due to the fact that the USA is the country with the
most movies made, but also that English tends to be considered the
“World’s Language”, and so people from all over the world seem to be
attracted towards movies that have English as one of their options.
The final observation that can be made is related to the last graphs.
Most of the lower ranked studios are either not proper studios, or based
in countries that have a smaller amount of resources to make their
movies. On the other hand, most of the studios with the highest average
scores hail from the United States of America.
Conclusions and Recommendations
After this thorough analysis, I have arrived at the conclusion that
the most important factor in a movies success is it’s country of
production. Of course, this is mainly oriented towards the United
States, which can be explained by the fact that they have the highest
amount of studios out of any country by far. Another factor that can be
attributed to this is that American studios tend to have a higher amount
of popularity. Take Universal Studios for example. This studio is so
popular, that it has pretty much transcended movie-making, to the point
that it even has a theme park based around it.
The other conclusion that i’ve reached is that for a movie to be
successful, it has to at least have a translation to the English
language. As we can clearly see, over 85% of movies have the option to
be watched in English. To me, this is a key factor. This is due to the
fact that it is the most popular language in the world, and so adapting
a movie to this language could very well take a movie from being a local
hit, to a worldwide phenomenom.
LS0tCnRpdGxlOiAiPHNwYW4gc3R5bGU9J2NvbG9yOiBicm93bjsnPkV2aWRlbmNpYSAyPC9zcGFuPiIKYXV0aG9yOiAiUGFibG8gU2FuY2hvIC0gQTAxNzIyMjM2IgpkYXRlOiAiMjAyNC0wNS0wMyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUgCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBkYXJrCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKZWRpdG9yX3M6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQotLS0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChldmFsID0gVFJVRSkKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5JbnRyb2R1Y3Rpb248L3NwYW4+ICAKCkZvciBzdGFydGVycywgdGhpcyByZXBvcnQgd2FzIG1hZGUgdXNpbmcgdGhlIGNvZGluZyBsYW5ndWFnZSBrbm93biBhcyAqUiosIHdpdGggdGhlIG9iamVjdGl2ZSBvZiBmaW5kaW5nIG91dCB3aGljaCB2YXJpYWJsZXMgZGV0ZXJtaW5lIHRoZSBzdWNjZXNzIG9mIGEgbW92aWUuIFRvIHNlZWsgdG8gZmluZCB0aGlzIGFuc3dlcnMsIHdlIHVzZWQgdGhlIGNzdiBmaWxlIGtub3duIGFzICoqbW92aWVzX21ldGFkYXRhLmNzdioqLiBUaGlzIGNzdiBmaWxlIHdhcyBvYnRhaW5lZCBmcm9tIEthZ2dsZSAoaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9yb3VuYWtiYW5pay90aGUtbW92aWVzLWRhdGFzZXQvZGF0YSksIGFuZCBpdCBjb250YWlucyBhIHJlZ2lzdHJ5IG9mIG92ZXIgNDUsMDAwIG1vdmllcywgMjcwLDAwMCB1c2VycyBhbmQgb3ZlciAyNiBtaWxsaW9uIHJhdGluZ3MuIFRoaXMgaXMgaW1wb3J0YW50LCBzaW5jZSB3ZSBhcmUgbG9va2luZyB0byBmaW5kIGNvbmNyZXRlIGFuc3dlcnMgdG8gb3VyIHF1ZXN0aW9uLCBhbmQgc28gdXNpbmcgYSBiaWcgYW1vdW50IG9mIGRhdGEgd2lsbCBtYWtlIG91ciByZXN1bHRzIG1vcmUgYWNjdXJhdGUuIAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+T2JqZWN0aXZlcyBhbmQgVmFyaWFibGVzPC9zcGFuPiAKCkFzIHByZXZpb3VzbHkgbWVudGlvbmVkLCB0aGUgbWFpbiBvYmplY3RpdmUgaXMgdG8gZGV0ZXJtaW5lIHdoYXQgbWFrZXMgKG9yIGRvZXNu4oCZdCBtYWtlKSBhIG1vdmllIHN1Y2Nlc3NmdWwuIFRvIGRvIHRoaXMsIHdlIGxvb2tlZCBhdCB0aGUgdmFyaWFibGVzIHdpdGhpbiB0aGlzIGRhdGFzZXQuIFRoZXNlIHZhcmlhYmxlcyBhcmUgdGhlIGZvbGxvd2luZzogYWR1bHQsIGJlbG9uZ3NfdG9fY29sbGVjdGlvbiwgYnVkZ2V0LCBnZW5yZXMJaG9tZXBhZ2UsIGlkLCBpbWRiX2lkLCBvcmlnaW5hbF9sYW5ndWFnZSwgb3JpZ2luYWxfdGl0bGUsIG92ZXJ2aWV3LCBwb3B1bGFyaXR5LCBwb3N0ZXJfcGF0aCwgcHJvZHVjdGlvbl9jb21wYW5pZXMsIHByb2R1Y3Rpb25fY291bnRyaWVzLCByZWxlYXNlX2RhdGUsIHJldmVudWUsIHJ1bnRpbWUsIHNwb2tlbl9sYW5ndWFnZXMsIHN0YXR1cywgdGFnbGluZSwgdGl0bGUJdmlkZW8sIHZvdGVfYXZlcmFnZSBhbmQgdm90ZV9jb3VudC4gVGhlc2UgdmFyaWFibGVzIHJhbmdlIGZyb20gZGVzY3JpcHRpb25zIHRvIG51bWVyaWNhbCB2YWx1ZXMsIHNvIHdlIGhhZCB0byBhc3NpZ24gdGhlbSBhIGRpZmZlcmVudCB2YWx1ZSBhbmQganVkZ2UgdGhlbSBkaWZmZXJlbnRseSBmcm9tIGVhY2ggb3RoZXIuIE9idmlvdXNseSwgdG8gZGV0ZXJtaW5lIHRoZSBzdWNjZXNzIG9mIGEgbW92aWUsIHdlIGRpZCBub3QgbmVjZXNzYXJpbHkgbmVlZCB0byB1dGlsaXplIGFsbCBvZiB0aGVzZSB2YXJpYWJsZXMsIGFuZCBzbyB0byBkbyB0aGlzLCBhIGNsZWFuaW5nIHByb2Nlc3MgaGFkIHRvIGJlIG1hZGUuCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5DbGVhbmluZyBQcm9jZXNzPC9zcGFuPiAKCkZvciB0aGlzIGNsZWFuaW5nIHByb2Nlc3MsIHdlIGhhZCB0byBlbGFib3JhdGUgY29kZXMgd2l0aCB0aGUgb2JqZWN0aXZlIG9mIGZpbHRlcmluZyBvdXQgZGF0YSB0aGF0IGlzIGVpdGhlciBpbmNvcnJlY3QsIGludmFsaWQgb3Igc2ltcGx5IHVubmVjZXNzYXJ5IGZvciBvdXIgYW5hbHlzaXMuIFRvIGVuc3VyZSB0aGF0IG91ciBkYXRhIGlzIGFzIHdlbGwtYXJyYW5nZWQgYXMgcG9zc2libGUsIEkgYmVnYW4gYnkgb3JkZXJpbmcgdGhlIGNvbHVtbnMgYnkgaW1wb3J0YW5jZSwgaW4gdGhlIG1hbm5lciB0aGF0IEkgdGhvdWdodCB3b3VsZCBiZSBlYXNpZXN0IHRvIHVuZGVyc3RhbmQgZm9yIHRoZSByZWFkZXIuIEJlY2F1c2Ugb2YgdGhpcywgdGhlIGZpcnN0IDIgY29sdW1ucyBhcmUgdGhlIG5hbWUgb2YgdGhlIG1vdmllLCBhbmQgdGhlIGlkZW50aWZpY2F0aW9uIG51bWJlci4gQWZ0ZXIgdGhpcywgSSBjb250aW51ZWQgYnkgY2hlY2tpbmcgZm9yIE5BIHZhbHVlcy4gVGhpcyByZWZlcnMgdG8gdmFsdWVzIHRoYXQgd2VyZW7igJl0IHJlY29yZGVkIHByb3Blcmx5LCBhbmQgc28gdGhleSBtYWtlIHRoZSBhbmFseXNpcyBleHRyZW1lbHkgY29tcGxpY2F0ZWQuIEJlY2F1c2Ugb2YgdGhpcywgSSBkZWxldGVkIHRoZXNlIHZhbHVlcy4gTmV4dCwgSSBjaGVja2VkIGZvciBkdXBsaWNhdGUgcm93cywgYW5kIGxvZ2ljYWxseSBkZWxldGVkIHRoZSBjb3BpZXMsIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZXJlIGlzIG9ubHkgb25lIHJvdyBmb3IgZWFjaCBtb3ZpZS4KVGhlbiBJIGNvbnRpbnVlZCBieSBjbGVhbmluZyB0aGUgY29sdW1ucyBpbmRpdmlkdWFsbHk6CkFkdWx0OiBBbGwgdmFsdWVzIHdlcmUgYXNzaWduZWQgdG8gZWl0aGVyIFRydWUgb3IgRmFsc2UuClJ1bnRpbWU6IERlbGV0ZWQgcm93cyB0aGF0IGhhZCBpbXBvc3NpYmxlIHJ1bnRpbWVzLiAoRXguIDAgb3IgMTk4NDkyMCBtaW51dGVzLikKVm90ZV9BdmVyYWdlOiBHYXZlIHRoZSBhdmVyYWdlIHJhdGluZyB0byByb3dzIHdpdGggYSB2YWx1ZSBvZiAwLgpDb2xsZWN0aW9uOiBEZWxldGVkIHRoZSBwYXJ0cyBvZiB0aGUgY29sdW1uIHRoYXQgSSBkZWVtZWQgdW5uZWNlc3NhcnkgKEV4LiBQYXJlbnRoZXNlcyBhbmQgQ29sbGVjdGlvbiBJRHMpCkdlbnJlcywgQ29tcGFuaWVzLCBDb3VudHJpZXMsIExhbmd1YWdlczogSSBzZXBhcmF0ZWQgdGhlIGRpZmZlcmVudCB2YWx1ZXMgYXNzaWduZWQgdG8gdGhlIG1vdmllIGludG8gZGlmZmVyZW50IGNvbHVtbnMsIGFzIHdlbGwgYXMgZ3JhcGhlZCB0aGUgdG9wIDIwIG9mIGVhY2ggY2F0ZWdvcnkuClBvc3Rlcl9QYXRoLCBUYWdsaW5lLCBWaWRlbzogSSBkZWxldGVkIHRoZXNlIGNvbHVtbnMgc2luY2UgSSBkZWVtZWQgdGhlbSB1bm5lY2Vzc2FyeS4KVGhlIHJlbWFpbmluZyBjb2x1bW5zIHdlcmUgbGVmdCB1bnRvdWNoZWQsIHNpbmNlIEkgY29uc2lkZXJlZCB0aGF0IHRoZXkgd2VyZSBib3RoIGNsZWFuLCBhbmQgcmVsZXZhbnQgdG8gdGhlIGFuYWx5c2lzIEkgd2FzIHRyeWluZyB0byBkby4KCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KbW92aWVzIDwtIHJlYWQuY3N2KCIvVXNlcnMvcGFibG9zYW5jaG8vRGVza3RvcC9tb3ZpZXNfbWV0YWRhdGEuY3N2IikKYGBgCgpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoImRwbHlyIikKbGlicmFyeSh2aXNkYXQpCmxpYnJhcnkoZHBseXIpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShkcGx5cikKbGlicmFyeShmdXp6eWpvaW4pCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KIyBSZWFycmFuZ2UgY29sdW1ucyB0byBtYWtlIHRoZSBmaXJzdCAzIHRoZSBvbmVzIG5lZWRlZCB0byBpZGVudGlmeSB0aGUgbW92aWUKbW92aWVzIDwtIG1vdmllcyAlPiUKICBzZWxlY3QodGl0bGUsIGlkLCBpbWRiX2lkLCBldmVyeXRoaW5nKCkpCiAgCmhlYWQobW92aWVzKQpgYGAKCi8vLy8vLy8vLy8KYGBge3J9CiMgQ2hlY2tpbmcgZm9yIE5Bcwpjb2x1bW5zX3RvX2NoZWNrIDwtIGMoImJ1ZGdldCIsICJnZW5yZXMiLCAiaG9tZXBhZ2UiLCAiaWQiLCAiaW1kYl9pZCIsICJvcmlnaW5hbF9sYW5ndWFnZSIsIAogICAgICAgICAgICAgICAgICAgICAgIm9yaWdpbmFsX3RpdGxlIiwgIm92ZXJ2aWV3IiwgInBvcHVsYXJpdHkiLCAicG9zdGVyX3BhdGgiLCAKICAgICAgICAgICAgICAgICAgICAgICJwcm9kdWN0aW9uX2NvbXBhbmllcyIsICJwcm9kdWN0aW9uX2NvdW50cmllcyIsICJyZWxlYXNlX2RhdGUiLCAKICAgICAgICAgICAgICAgICAgICAgICJyZXZlbnVlIiwgInJ1bnRpbWUiLCAic3Bva2VuX2xhbmd1YWdlcyIsICJzdGF0dXMiLAogICAgICAgICAgICAgICAgICAgICAgInRpdGxlIiwgInZpZGVvIiwgInZvdGVfYXZlcmFnZSIsICJ2b3RlX2NvdW50IiwgImFkdWx0IikKCm1pc3Npbmdfcm93cyA8LSB3aGljaCghY29tcGxldGUuY2FzZXMobW92aWVzWywgY29sdW1uc190b19jaGVja10pKQoKbnVtX21pc3Npbmdfcm93cyA8LSBsZW5ndGgobWlzc2luZ19yb3dzKQoKcHJpbnQocGFzdGUoIk51bWJlciBvZiBtaXNzaW5nIHJvd3M6IiwgbnVtX21pc3Npbmdfcm93cykpCnByaW50KCJJbmRpY2VzIG9mIG1pc3Npbmcgcm93czoiKQpwcmludChtaXNzaW5nX3Jvd3MpCmBgYAoKYGBge3J9CiMgQ2xlYW5pbmcgTkFzCm1vdmllc19jbGVhbiA8LSBtb3ZpZXNbY29tcGxldGUuY2FzZXMobW92aWVzWywgY29sdW1uc190b19jaGVja10pLCBdCgpwcmludCgiRGltZW5zaW9ucyBvZiBjbGVhbmVkIGRhdGFmcmFtZToiKQpwcmludChkaW0obW92aWVzX2NsZWFuKSkKYGBgCgovLy8vLy8vLy8vCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KCm1vdmllc19jbGVhbl91bmlxdWUgPC0gZGlzdGluY3QobW92aWVzX2NsZWFuLCBpZCwgLmtlZXBfYWxsID0gVFJVRSkKCnByaW50KHBhc3RlKCJOdW1iZXIgb2Ygcm93cyBiZWZvcmUgcmVtb3ZpbmcgZHVwbGljYXRlczoiLCBucm93KG1vdmllc19jbGVhbikpKQpwcmludChwYXN0ZSgiTnVtYmVyIG9mIHJvd3MgYWZ0ZXIgcmVtb3ZpbmcgZHVwbGljYXRlczoiLCBucm93KG1vdmllc19jbGVhbl91bmlxdWUpKSkKCm1vdmllc19jbGVhbiA8LSBtb3ZpZXNfY2xlYW5fdW5pcXVlCgpgYGAKCgovLy8vLy8vLy8KYGBge3IgaW5jbHVkZSA9IEZBTFNFfQojIENsZWFuaW5nIGFkdWx0IGNvbHVtbgp1bmlxdWVfYWR1bHQgPC0gdGFibGUobW92aWVzX2NsZWFuJGFkdWx0KQp1bmlxdWVfYWR1bHQKYGBgCgpgYGB7cn0KbW92aWVzX2NsZWFuJGFkdWx0IDwtIGlmZWxzZShtb3ZpZXNfY2xlYW4kYWR1bHQgIT0gIlRydWUiICYgbW92aWVzX2NsZWFuJGFkdWx0ICE9ICJGYWxzZSIsICJGYWxzZSIsIG1vdmllc19jbGVhbiRhZHVsdCkKYGBgCgovLy8vLy8vLy8vCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KdG9wXzEwX3J1bnRpbWUgPC0gaGVhZChtb3ZpZXNfY2xlYW5bb3JkZXIobW92aWVzX2NsZWFuJHJ1bnRpbWUsIGRlY3JlYXNpbmcgPSBUUlVFKSwgXSwgMTApCgoKYm90dG9tXzEwX3J1bnRpbWUgPC0gaGVhZChtb3ZpZXNfY2xlYW5bb3JkZXIobW92aWVzX2NsZWFuJHJ1bnRpbWUpLCBdLCAxMCkKCnByaW50KCJIaWdoZXN0IFJ1bnRpbWVzOiIpCnByaW50KHRvcF8xMF9ydW50aW1lKQoKcHJpbnQoIkxvd2VzdCBSdW50aW1lczoiKQpwcmludChib3R0b21fMTBfcnVudGltZSkKYGBgCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KI0NsZWFuaW5nIHJ1bnRpbWUgY29sdW1uCmF2ZXJhZ2VfcnVudGltZSA8LSBtZWFuKG1vdmllc19jbGVhbiRydW50aW1lW21vdmllc19jbGVhbiRydW50aW1lICE9IDAgJiAhaXMubmEobW92aWVzX2NsZWFuJHJ1bnRpbWUpXSwgbmEucm0gPSBUUlVFKQoKbW92aWVzX2NsZWFuJHJ1bnRpbWUgPC0gaWZlbHNlKG1vdmllc19jbGVhbiRydW50aW1lID09IDAgfCBpcy5uYShtb3ZpZXNfY2xlYW4kcnVudGltZSksIGF2ZXJhZ2VfcnVudGltZSwgbW92aWVzX2NsZWFuJHJ1bnRpbWUpCgpwcmludChwYXN0ZSgiVmFsdWVzIEJlZm9yZToiLCBhdmVyYWdlX3J1bnRpbWUpKQoKCnJlcGxhY2VkX2NvdW50IDwtIHN1bShtb3ZpZXNfY2xlYW4kcnVudGltZSA9PSBhdmVyYWdlX3J1bnRpbWUpCnByaW50KHBhc3RlKCJWYWx1ZXMgUmVwbGFjZWQ6IiwgcmVwbGFjZWRfY291bnQpKQpgYGAKLy8vLy8vLy8vLwpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CiMgQ2xlYW5pbmcgdm90ZSBhdmVyYWdlIGNvbHVtbgphdmVyYWdlX3ZvdGVfYXZlcmFnZSA8LSBtZWFuKG1vdmllc19jbGVhbiR2b3RlX2F2ZXJhZ2VbbW92aWVzX2NsZWFuJHZvdGVfYXZlcmFnZSAhPSAwICYgIWlzLm5hKG1vdmllc19jbGVhbiR2b3RlX2F2ZXJhZ2UpXSwgbmEucm0gPSBUUlVFKQoKCm1vdmllc19jbGVhbiR2b3RlX2F2ZXJhZ2UgPC0gaWZlbHNlKG1vdmllc19jbGVhbiR2b3RlX2F2ZXJhZ2UgPT0gMCB8IGlzLm5hKG1vdmllc19jbGVhbiR2b3RlX2F2ZXJhZ2UpLCBhdmVyYWdlX3ZvdGVfYXZlcmFnZSwgbW92aWVzX2NsZWFuJHZvdGVfYXZlcmFnZSkKCgpwcmludChwYXN0ZSgiVmFsdWVzIEJlZm9yZToiLCBhdmVyYWdlX3ZvdGVfYXZlcmFnZSkpCgoKcmVwbGFjZWRfY291bnQgPC0gc3VtKG1vdmllc19jbGVhbiR2b3RlX2F2ZXJhZ2UgPT0gYXZlcmFnZV92b3RlX2F2ZXJhZ2UpCnByaW50KHBhc3RlKCJWYWx1ZXMgUmVwbGFjZWQ6IiwgcmVwbGFjZWRfY291bnQpKQpgYGAKCgovLy8vLy8vLy8vCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KIyBDbGVhbmluZyBjb2xsZWN0aW9uIGNvbHVtbgpjb2xsZWN0aW9uX25hbWVzIDwtIHN0cl9leHRyYWN0KG1vdmllc19jbGVhbiRiZWxvbmdzX3RvX2NvbGxlY3Rpb24sICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKQoKY29sbGVjdGlvbl9uYW1lcyA8LSBjb2xsZWN0aW9uX25hbWVzWyFpcy5uYShjb2xsZWN0aW9uX25hbWVzKV0KCmNvbGxlY3Rpb25fY291bnRzIDwtIHRhYmxlKGNvbGxlY3Rpb25fbmFtZXMpCgpjb2xsZWN0aW9uX2NvdW50cyA8LSBzb3J0KGNvbGxlY3Rpb25fY291bnRzLCBkZWNyZWFzaW5nID0gVFJVRSkKCnRvcF8xMF9jb2xsZWN0aW9ucyA8LSBoZWFkKGNvbGxlY3Rpb25fY291bnRzLCAxMCkKcHJpbnQodG9wXzEwX2NvbGxlY3Rpb25zKQpgYGAKCi8vLy8vLy8vLy8KCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0KIyBOZXcgR2VucmVzCm1vdmllc19jbGVhbiRnZW5yZXNfc3RyaW5nIDwtIGFzLmNoYXJhY3Rlcihtb3ZpZXNfY2xlYW4kZ2VucmVzKQoKbGlicmFyeSgic3RyaW5nciIpCm5ld19nZW5yZXMgPC0gc3RyX3NwbGl0X2ZpeGVkKG1vdmllc19jbGVhbiRnZW5yZXNfc3RyaW5nLCAiOiIsIG4gPSBJbmYpCgpuZXdfZ2VucmVzIDwtIG5ld19nZW5yZXNbLDE6N10KCm5ld19nZW5yZXMgPC0gbmV3X2dlbnJlc1ssIGMoMyw1LDcpXQoKc3VtbWFyeShuZXdfZ2VucmVzKQoKbmV3X2dlbnJlcyA8LSBhcy5kYXRhLmZyYW1lKG5ld19nZW5yZXMpCgojaHR0cHM6Ly9zdGF0LmV0aHouY2gvUi1tYW51YWwvUi1kZXZlbC9saWJyYXJ5L2Jhc2UvaHRtbC9yZWdleC5odG1sCgpuZXdfZ2VucmVzIDwtIG5ld19nZW5yZXMgJT4lIAogIG11dGF0ZShnZW5yZTEgPSBzdHJfcmVwbGFjZV9hbGwobmV3X2dlbnJlcyRWMSwgIltbOnB1bmN0Ol1dIiwgIiAiKSkKCm5ld19nZW5yZXMgPC0gbmV3X2dlbnJlcyAlPiUgCiAgbXV0YXRlKGdlbnJlMiA9IHN0cl9yZXBsYWNlX2FsbChuZXdfZ2VucmVzJFYyLCAiW1s6cHVuY3Q6XV0iLCAiICIpKQoKbmV3X2dlbnJlcyA8LSBuZXdfZ2VucmVzICU+JSAKICBtdXRhdGUoZ2VucmUzID0gc3RyX3JlcGxhY2VfYWxsKG5ld19nZW5yZXMkVjMsICJbWzpwdW5jdDpdXSIsICIgIikpCgoKbmV3X2dlbnJlcyRnZW5yZTEgPC0gc3RyX3JlbW92ZShuZXdfZ2VucmVzJGdlbnJlMSwiaWQiKQpuZXdfZ2VucmVzJGdlbnJlMiA8LSBzdHJfcmVtb3ZlKG5ld19nZW5yZXMkZ2VucmUyLCJpZCIpCm5ld19nZW5yZXMkZ2VucmUzIDwtIHN0cl9yZW1vdmUobmV3X2dlbnJlcyRnZW5yZTMsImlkIikKCmdlbnJlc19jbGVhbiA8LSBuZXdfZ2VucmVzWyw0OjZdCgpzdW1tYXJ5KGdlbnJlc19jbGVhbikKYGBgCgoKYGBge3IgaW5jbHVkZSA9IEZBTFNFfQpnZW5yZXNfY2xlYW4kZ2VucmUxIDwtIHN0cl90cmltKGdlbnJlc19jbGVhbiRnZW5yZTEsICJib3RoIikKZ2VucmVzX2NsZWFuJGdlbnJlMiA8LSBzdHJfdHJpbShnZW5yZXNfY2xlYW4kZ2VucmUyLCAiYm90aCIpCmdlbnJlc19jbGVhbiRnZW5yZTMgPC0gc3RyX3RyaW0oZ2VucmVzX2NsZWFuJGdlbnJlMywgImJvdGgiKQoKZ2VucmVzX2NsZWFuJGdlbnJlMSA8LSBhcy5mYWN0b3IoZ2VucmVzX2NsZWFuJGdlbnJlMSkKZ2VucmVzX2NsZWFuJGdlbnJlMiA8LSBhcy5mYWN0b3IoZ2VucmVzX2NsZWFuJGdlbnJlMikKZ2VucmVzX2NsZWFuJGdlbnJlMyA8LSBhcy5mYWN0b3IoZ2VucmVzX2NsZWFuJGdlbnJlMykKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5TdGF0aXN0aWNhbCBhbmQgQW5hbHl0aWNhbCBUZWNobmlxdWVzPC9zcGFuPiAKCkFmdGVyIGNvbmNsdWRpbmcgdGhlIGNsZWFuaW5nIHByb2Nlc3MsIEkgYmVnYW4gdG8gZ3JhcGggdGhlIGRhdGEgaW50byBjaGFydHMgYW5kIHBsb3RzLiBUaGUgZmlyc3QgNCBncmFwaHMgSSBtYWRlIHdlcmUgdGhlIG9uZXMgSSBtZW50aW9uZWQgcHJldmlvdXNseS4gVGhleSBjb250YWluIHRoZSAyMCBtb3N0IGNvbW1vbiBHZW5yZXMsIENvbXBhbmllcywgQ291bnRyaWVzIGFuZCBMYW5ndWFnZXMuIFRoZXNlIGdyYXBocyBhcmUgZXh0cmVtZWx5IHNpbXBsZSwgYnV0IEkgY29uc2lkZXJlZCB0aGVtIHRvIGJlIGVzc2VudGlhbCB0byB0aGUgYW5hbHlzaXMsIHNpbmNlIHRoZXkgcmVwcmVzZW50IHRoZSBtYWpvcml0eSBvZiB0aGUgcG9wdWxhdGlvbi4gVmFsdWVzIHRoYXQgYXJlIHNtYWxsZXIgdGVuZCB0byBiZSBtdWNoIGxlc3Mgc2lnbmlmaWNhbnQsIGFuZCBzbyB0aGUgbW9zdCBwb3B1bGFyIHZhbHVlcyBpbiB0aGVzZSBjb2x1bW5zIGFyZSBvZiB0aGUgdXRtb3N0IGltcG9ydGFuY2UuIFRoZXNlIGFyZSB0aGUgZ3JhcGhzIEkgb2J0YWluZWQ6CgpgYGB7ciBpbmNsdWRlID0gRkFMU0V9CiMgTmV3IGNvbXBhbmllcyAoMjAgbW9zdCBwb3B1bGFyIGNvbXBhbmllcyBncmFwaCkKbmV3X2NvbXBhbmllcyA8LSBzdHJfc3BsaXRfZml4ZWQobW92aWVzX2NsZWFuJHByb2R1Y3Rpb25fY29tcGFuaWVzLCAiXFx9LCIsIG4gPSBJbmYpCgoKbmV3X2NvbXBhbmllcyA8LSBuZXdfY29tcGFuaWVzWywgMToyMV0KCm5ld19jb21wYW5pZXMgPC0gYXMuZGF0YS5mcmFtZShuZXdfY29tcGFuaWVzKQpuZXdfY29tcGFuaWVzIDwtIG5ld19jb21wYW5pZXMgJT4lIAogIG11dGF0ZShjb21wYW55MSA9IHN0cl9leHRyYWN0KFYxLCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnkyID0gc3RyX2V4dHJhY3QoVjIsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTMgPSBzdHJfZXh0cmFjdChWMywgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb21wYW55NCA9IHN0cl9leHRyYWN0KFY0LCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnk1ID0gc3RyX2V4dHJhY3QoVjUsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTYgPSBzdHJfZXh0cmFjdChWNiwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb21wYW55NyA9IHN0cl9leHRyYWN0KFY3LCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnk4ID0gc3RyX2V4dHJhY3QoVjgsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTkgPSBzdHJfZXh0cmFjdChWOSwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb21wYW55MTAgPSBzdHJfZXh0cmFjdChWMTAsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTExID0gc3RyX2V4dHJhY3QoVjExLCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnkxMiA9IHN0cl9leHRyYWN0KFYxMiwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb21wYW55MTMgPSBzdHJfZXh0cmFjdChWMTMsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTE0ID0gc3RyX2V4dHJhY3QoVjE0LCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnkxNSA9IHN0cl9leHRyYWN0KFYxNSwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb21wYW55MTYgPSBzdHJfZXh0cmFjdChWMTYsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTE3ID0gc3RyX2V4dHJhY3QoVjE3LCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnkxOCA9IHN0cl9leHRyYWN0KFYxOCwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb21wYW55MTkgPSBzdHJfZXh0cmFjdChWMTksICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY29tcGFueTIwID0gc3RyX2V4dHJhY3QoVjIwLCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvbXBhbnkyMSA9IHN0cl9leHRyYWN0KFYyMSwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpKQoKCm5ld19jb21wYW5pZXMkY29tcGFueTEgPC0gc3RyX3JlbW92ZShuZXdfY29tcGFuaWVzJGNvbXBhbnkxLCAiJ25hbWUnOlxccysiKQpuZXdfY29tcGFuaWVzJGNvbXBhbnkyIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MiwgIiduYW1lJzpcXHMrIikKbmV3X2NvbXBhbmllcyRjb21wYW55MyA8LSBzdHJfcmVtb3ZlKG5ld19jb21wYW5pZXMkY29tcGFueTMsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTQgPC0gc3RyX3JlbW92ZShuZXdfY29tcGFuaWVzJGNvbXBhbnk0LCAiJ25hbWUnOlxccysiKQpuZXdfY29tcGFuaWVzJGNvbXBhbnk1IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55NSwgIiduYW1lJzpcXHMrIikKbmV3X2NvbXBhbmllcyRjb21wYW55NiA8LSBzdHJfcmVtb3ZlKG5ld19jb21wYW5pZXMkY29tcGFueTYsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTcgPC0gc3RyX3JlbW92ZShuZXdfY29tcGFuaWVzJGNvbXBhbnk3LCAiJ25hbWUnOlxccysiKQpuZXdfY29tcGFuaWVzJGNvbXBhbnk4IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55OCwgIiduYW1lJzpcXHMrIikKbmV3X2NvbXBhbmllcyRjb21wYW55OSA8LSBzdHJfcmVtb3ZlKG5ld19jb21wYW5pZXMkY29tcGFueTksICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTEwIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTAsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTExIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTEsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTEyIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTIsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTEzIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTMsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTE0IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTQsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTE1IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTUsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTE2IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTYsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTE3IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTcsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTE4IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTgsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTE5IDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MTksICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTIwIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MjAsICInbmFtZSc6XFxzKyIpCm5ld19jb21wYW5pZXMkY29tcGFueTIxIDwtIHN0cl9yZW1vdmUobmV3X2NvbXBhbmllcyRjb21wYW55MjEsICInbmFtZSc6XFxzKyIpCgoKYWxsX2NvbXBhbmllcyA8LSBjKG5ld19jb21wYW5pZXMkY29tcGFueTEsIG5ld19jb21wYW5pZXMkY29tcGFueTIsIG5ld19jb21wYW5pZXMkY29tcGFueTMsIG5ld19jb21wYW5pZXMkY29tcGFueTQsIG5ld19jb21wYW5pZXMkY29tcGFueTUsIG5ld19jb21wYW5pZXMkY29tcGFueTYsIG5ld19jb21wYW5pZXMkY29tcGFueTcsIG5ld19jb21wYW5pZXMkY29tcGFueTgsIG5ld19jb21wYW5pZXMkY29tcGFueTksIG5ld19jb21wYW5pZXMkY29tcGFueTEwLCBuZXdfY29tcGFuaWVzJGNvbXBhbnkxMSwgbmV3X2NvbXBhbmllcyRjb21wYW55MTIsIG5ld19jb21wYW5pZXMkY29tcGFueTEzLCBuZXdfY29tcGFuaWVzJGNvbXBhbnkxNCwgbmV3X2NvbXBhbmllcyRjb21wYW55MTUsIG5ld19jb21wYW5pZXMkY29tcGFueTE2LCBuZXdfY29tcGFuaWVzJGNvbXBhbnkxNywgbmV3X2NvbXBhbmllcyRjb21wYW55MTgsIG5ld19jb21wYW5pZXMkY29tcGFueTE5LCBuZXdfY29tcGFuaWVzJGNvbXBhbnkyMCwgbmV3X2NvbXBhbmllcyRjb21wYW55MjEpCgoKY29tcGFueV9jb3VudHMgPC0gdGFibGUoYWxsX2NvbXBhbmllcykKCgpjb21wYW55X2NvdW50cyA8LSBzb3J0KGNvbXBhbnlfY291bnRzLCBkZWNyZWFzaW5nID0gVFJVRSkKCgp0b3BfMjBfc3R1ZGlvcyA8LSBoZWFkKGNvbXBhbnlfY291bnRzLCAyMCkKCnByaW50KCJDb3VudHMgb2YgRWFjaCBTdHVkaW86IikKcHJpbnQodG9wXzIwX3N0dWRpb3MpCmBgYAoKYGBge3J9CmJhcnBsb3QodG9wXzIwX3N0dWRpb3MsIG1haW4gPSAiVG9wIDIwIE1vc3QgQ29tbW9uIFN0dWRpb3MiLCB4bGFiID0gIlN0dWRpb3MiLCB5bGFiID0gIkNvdW50IiwgbGFzID0gMiwgY29sID0gImZvcmVzdGdyZWVuIikKYGBgCmBgYHtyfQojIE5ldyBjb3VudHJpZXMgKFRvcCAyMCBjb3VudHJpZXMgZ3JhcGgpCmNvdW50cnlfY291bnRzIDwtIHRhYmxlKG1vdmllc19jbGVhbiRwcm9kdWN0aW9uX2NvdW50cmllcykKCgpuZXdfY291bnRyaWVzIDwtIHN0cl9zcGxpdF9maXhlZChtb3ZpZXNfY2xlYW4kcHJvZHVjdGlvbl9jb3VudHJpZXMsICJcXH0sIiwgbiA9IEluZikKCgpuZXdfY291bnRyaWVzIDwtIG5ld19jb3VudHJpZXNbLCAxOjddCgoKbmV3X2NvdW50cmllcyA8LSBhcy5kYXRhLmZyYW1lKG5ld19jb3VudHJpZXMpCm5ld19jb3VudHJpZXMgPC0gbmV3X2NvdW50cmllcyAlPiUgCiAgbXV0YXRlKGNvdW50cnkxID0gc3RyX2V4dHJhY3QoVjEsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY291bnRyeTIgPSBzdHJfZXh0cmFjdChWMiwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb3VudHJ5MyA9IHN0cl9leHRyYWN0KFYzLCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvdW50cnk0ID0gc3RyX2V4dHJhY3QoVjQsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSwKICAgICAgICAgY291bnRyeTUgPSBzdHJfZXh0cmFjdChWNSwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBjb3VudHJ5NiA9IHN0cl9leHRyYWN0KFY2LCAiJ25hbWUnOlxccysnKFtbOmFsbnVtOl1cXHNdKyknIiksCiAgICAgICAgIGNvdW50cnk3ID0gc3RyX2V4dHJhY3QoVjcsICInbmFtZSc6XFxzKycoW1s6YWxudW06XVxcc10rKSciKSkKCgpuZXdfY291bnRyaWVzJGNvdW50cnkxIDwtIHN0cl9yZW1vdmUobmV3X2NvdW50cmllcyRjb3VudHJ5MSwgIiduYW1lJzpcXHMrIikKbmV3X2NvdW50cmllcyRjb3VudHJ5MiA8LSBzdHJfcmVtb3ZlKG5ld19jb3VudHJpZXMkY291bnRyeTIsICInbmFtZSc6XFxzKyIpCm5ld19jb3VudHJpZXMkY291bnRyeTMgPC0gc3RyX3JlbW92ZShuZXdfY291bnRyaWVzJGNvdW50cnkzLCAiJ25hbWUnOlxccysiKQpuZXdfY291bnRyaWVzJGNvdW50cnk0IDwtIHN0cl9yZW1vdmUobmV3X2NvdW50cmllcyRjb3VudHJ5NCwgIiduYW1lJzpcXHMrIikKbmV3X2NvdW50cmllcyRjb3VudHJ5NSA8LSBzdHJfcmVtb3ZlKG5ld19jb3VudHJpZXMkY291bnRyeTUsICInbmFtZSc6XFxzKyIpCm5ld19jb3VudHJpZXMkY291bnRyeTYgPC0gc3RyX3JlbW92ZShuZXdfY291bnRyaWVzJGNvdW50cnk2LCAiJ25hbWUnOlxccysiKQpuZXdfY291bnRyaWVzJGNvdW50cnk3IDwtIHN0cl9yZW1vdmUobmV3X2NvdW50cmllcyRjb3VudHJ5NywgIiduYW1lJzpcXHMrIikKCmFsbF9jb3VudHJpZXMgPC0gYyhuZXdfY291bnRyaWVzJGNvdW50cnkxLCBuZXdfY291bnRyaWVzJGNvdW50cnkyLCBuZXdfY291bnRyaWVzJGNvdW50cnkzLAogICAgICAgICAgICAgICAgICAgbmV3X2NvdW50cmllcyRjb3VudHJ5NCwgbmV3X2NvdW50cmllcyRjb3VudHJ5NSwgbmV3X2NvdW50cmllcyRjb3VudHJ5NiwKICAgICAgICAgICAgICAgICAgIG5ld19jb3VudHJpZXMkY291bnRyeTcpCgoKY291bnRyeV9jb3VudHMgPC0gdGFibGUoYWxsX2NvdW50cmllcykKCgpjb3VudHJ5X2NvdW50cyA8LSBzb3J0KGNvdW50cnlfY291bnRzLCBkZWNyZWFzaW5nID0gVFJVRSkKCgp0b3BfMjBfY291bnRyaWVzIDwtIGhlYWQoY291bnRyeV9jb3VudHMsIDIwKQoKcHJpbnQoIkNvdW50cyBvZiBFYWNoIENvdW50cnk6IikKcHJpbnQodG9wXzIwX2NvdW50cmllcykKCgpiYXJwbG90KHRvcF8yMF9jb3VudHJpZXMsIG1haW4gPSAiVG9wIDIwIE1vc3QgQ29tbW9uIENvdW50cmllcyIsIHhsYWIgPSAiQ291bnRyaWVzIiwgeWxhYiA9ICJDb3VudCIsIGxhcyA9IDIsIGNvbCA9ICJyZWQiKQpgYGAKYGBge3J9CiMgTmV3IGxhbmd1YWdlcyAoVG9wIDIwIGxhbmd1YWdlcyBncmFwaCkKbmV3X2xhbmd1YWdlcyA8LSBzdHJfc3BsaXRfZml4ZWQobW92aWVzX2NsZWFuJHNwb2tlbl9sYW5ndWFnZXMsICJcXH0sIiwgbiA9IEluZikKCm5ld19sYW5ndWFnZXMgPC0gbmV3X2xhbmd1YWdlc1ssIDE6N10KCm5ld19sYW5ndWFnZXMgPC0gYXMuZGF0YS5mcmFtZShuZXdfbGFuZ3VhZ2VzKQpuZXdfbGFuZ3VhZ2VzIDwtIG5ld19sYW5ndWFnZXMgJT4lIAogIG11dGF0ZShsYW5ndWFnZTEgPSBzdHJfZXh0cmFjdChWMSwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBsYW5ndWFnZTIgPSBzdHJfZXh0cmFjdChWMiwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBsYW5ndWFnZTMgPSBzdHJfZXh0cmFjdChWMywgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBsYW5ndWFnZTQgPSBzdHJfZXh0cmFjdChWNCwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBsYW5ndWFnZTUgPSBzdHJfZXh0cmFjdChWNSwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBsYW5ndWFnZTYgPSBzdHJfZXh0cmFjdChWNiwgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpLAogICAgICAgICBsYW5ndWFnZTcgPSBzdHJfZXh0cmFjdChWNywgIiduYW1lJzpcXHMrJyhbWzphbG51bTpdXFxzXSspJyIpKQoKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTEgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlMSwgIiduYW1lJzpcXHMrIikKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTIgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlMiwgIiduYW1lJzpcXHMrIikKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTMgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlMywgIiduYW1lJzpcXHMrIikKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTQgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlNCwgIiduYW1lJzpcXHMrIikKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTUgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlNSwgIiduYW1lJzpcXHMrIikKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTYgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlNiwgIiduYW1lJzpcXHMrIikKbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTcgPC0gc3RyX3JlbW92ZShuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlNywgIiduYW1lJzpcXHMrIikKCmFsbF9sYW5ndWFnZXMgPC0gYyhuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlMSwgbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTIsIG5ld19sYW5ndWFnZXMkbGFuZ3VhZ2UzLAogICAgICAgICAgICAgICAgICAgbmV3X2xhbmd1YWdlcyRsYW5ndWFnZTQsIG5ld19sYW5ndWFnZXMkbGFuZ3VhZ2U1LCBuZXdfbGFuZ3VhZ2VzJGxhbmd1YWdlNiwKICAgICAgICAgICAgICAgICAgIG5ld19sYW5ndWFnZXMkbGFuZ3VhZ2U3KQoKbGFuZ3VhZ2VfY291bnRzIDwtIHRhYmxlKGFsbF9sYW5ndWFnZXMpCgoKbGFuZ3VhZ2VfY291bnRzIDwtIHNvcnQobGFuZ3VhZ2VfY291bnRzLCBkZWNyZWFzaW5nID0gVFJVRSkKCgp0b3BfMjBfbGFuZ3VhZ2VzIDwtIGhlYWQobGFuZ3VhZ2VfY291bnRzLCAyMCkKCnByaW50KCJDb3VudHMgb2YgRWFjaCBMYW5ndWFnZToiKQpwcmludCh0b3BfMjBfbGFuZ3VhZ2VzKQoKCmJhcnBsb3QodG9wXzIwX2xhbmd1YWdlcywgbWFpbiA9ICJUb3AgMjAgTW9zdCBDb21tb24gU3Bva2VuIExhbmd1YWdlcyIsIHhsYWIgPSAiTGFuZ3VhZ2VzIiwgeWxhYiA9ICJDb3VudCIsIGxhcyA9IDIsIGNvbCA9ICJza3libHVlIikKYGBgCgpOZXh0LCBJIG1hZGUgYSB0YWJsZSB0aGF0IGdpdmVzIHlvdSB0aGUgbmFtZSBvZiB0aGUgZGlmZmVyZW50IGNvdW50cmllcyBhbmQgb2J0YWlucyBib3RoIHRoZSBhdmVyYWdlIHJldmVudWUgYW5kIHJ1bnRpbWUgZm9yIGVhY2guIEkgY29uc2lkZXJlZCB0aGF0IHRoZXNlIHZhbHVlcyBhcmUgYWxzbyBpbXBvcnRhbnQsIHNpbmNlIGRpZmZlcmVudCBjb3VudHJpZXMgdGVuZCB0byBoYXZlIGRpZmZlcmVudCBwcmVmZXJlbmNlcyB3aGVuIGl0IGNvbWVzIHRvIHRoZSBkdXJhdGlvbiBvZiBmaWxtcywgYW5kIHdlbGwgYXMgdGhlIGZhY3QgdGhhdCB0aGV5IGhhdmUgZGlmZmVyZW50IGFtb3VudHMgb2YgcmVzb3VyY2VzLCB3aGljaCB0ZW5kcyB0byBoYXZlIGFuIGltcGFjdCBvbiBob3cgbXVjaCBhIG1vdmllIGVhcm5zIGluIHNhbGVzLiBUaGlzIGlzIGhvdyB0aGlzIHRhYmxlIGxvb2tzIGxpa2U6CgpgYGB7cn0KIyBSdW50aW1lIGFuZCByZXZlbnVlIGRhdGEKYWxsX2NvdW50cmllcyA8LSBjKG5ld19jb3VudHJpZXMkY291bnRyeTEsIG5ld19jb3VudHJpZXMkY291bnRyeTIsIG5ld19jb3VudHJpZXMkY291bnRyeTMsCiAgICAgICAgICAgICAgICAgICBuZXdfY291bnRyaWVzJGNvdW50cnk0LCBuZXdfY291bnRyaWVzJGNvdW50cnk1LCBuZXdfY291bnRyaWVzJGNvdW50cnk2LAogICAgICAgICAgICAgICAgICAgbmV3X2NvdW50cmllcyRjb3VudHJ5NykKCgptb3ZpZV9jb3VudHJ5IDwtIGRhdGEuZnJhbWUobW92aWVfaWQgPSByZXAobW92aWVzX2NsZWFuJGlkLCBlYWNoID0gNyksIGNvdW50cnkgPSBhbGxfY291bnRyaWVzKQoKCm1vdmllX2NvdW50cnlfcmV2ZW51ZV9ydW50aW1lIDwtIGxlZnRfam9pbihtb3ZpZV9jb3VudHJ5LCBtb3ZpZXNfY2xlYW4sIGJ5ID0gYygibW92aWVfaWQiID0gImlkIikpCgoKY291bnRyeV9zdGF0cyA8LSBtb3ZpZV9jb3VudHJ5X3JldmVudWVfcnVudGltZSAlPiUKICBncm91cF9ieShjb3VudHJ5KSAlPiUKICBzdW1tYXJpemUoYXZlcmFnZV9yZXZlbnVlID0gbWVhbihyZXZlbnVlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBhdmVyYWdlX3J1bnRpbWUgPSBtZWFuKHJ1bnRpbWUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIGF2ZXJhZ2VfYnVkZ2V0ID0gbWVhbihidWRnZXQsIG5hLnJtID0gVFJVRSkpCgoKcHJpbnQoY291bnRyeV9zdGF0cykKYGBgCgpBZnRlciBvYnRhaW5pbmcgdGhpcyB0YWJsZSwgSSBncmFwaGVkIGl0IGluIGEgc2NhdHRlciBwbG90LCB3aGVyZSB3ZSBjYW4gc2VlIHRoZSB0b3AgMjAgY291bnRyaWVzIGJ5IGJvdGggcmV2ZW51ZSBhbmQgcnVudGltZSwgYXMgd2VsbCBhcyB0aGUgYm90dG9tIDIwIGNvdW50cmllcy4gVGhlc2UgYXJlIHRoZSBncmFwaHM6CgpgYGB7cn0KIyBIaWdoZXN0IHJ1bnRpbWUgYW5kIHJldmVudWVzIHNjYXR0ZXJwbG90cwp0b3BfMjBfY291bnRyaWVzIDwtIGhlYWQoY291bnRyeV9zdGF0c1tvcmRlcihjb3VudHJ5X3N0YXRzJGF2ZXJhZ2VfcmV2ZW51ZSwgZGVjcmVhc2luZyA9IFRSVUUpLF0sIDIwKQoKCmdncGxvdCh0b3BfMjBfY291bnRyaWVzLCBhZXMoeCA9IGNvdW50cnksIHkgPSBhdmVyYWdlX3JldmVudWUpKSArCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHRpdGxlID0gIlRvcCAyMCBDb3VudHJpZXM6IEF2ZXJhZ2UgUmV2ZW51ZSIsCiAgICAgICB4ID0gIkNvdW50cnkiLCB5ID0gIkF2ZXJhZ2UgUmV2ZW51ZSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCgoKdG9wXzIwX2NvdW50cmllcyA8LSBoZWFkKGNvdW50cnlfc3RhdHNbb3JkZXIoY291bnRyeV9zdGF0cyRhdmVyYWdlX3J1bnRpbWUsIGRlY3JlYXNpbmcgPSBUUlVFKSxdLCAyMCkKCgpnZ3Bsb3QodG9wXzIwX2NvdW50cmllcywgYWVzKHggPSBjb3VudHJ5LCB5ID0gYXZlcmFnZV9ydW50aW1lKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgMjAgQ291bnRyaWVzOiBBdmVyYWdlIFJ1bnRpbWUiLAogICAgICAgeCA9ICJDb3VudHJ5IiwgeSA9ICJBdmVyYWdlIFJ1bnRpbWUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQoKCmBgYAoKRmluYWxseSwgSSBvYnRhaW5lZCB0aGUgYXZlcmFnZSByYXRpbmcgYnkgdGhlIGRpZmZlcmVudCBzdHVkaW9zLCBieSBjb21iaW5pbmcgYWxsIG9mIHRoZSByZXN1bHRzIG9idGFpbmVkIGZyb20gdGhlIGRpZmZlcmVudCBtb3ZpZXMuIFRvIGRvIHRoaXMsIEkgbWFkZSBhIGZpbHRlciB0byBvbmx5IGluY2x1ZGUgc3R1ZGlvcyB3aXRoIGF0IGxlYXN0IDEwIG1vdmllcy4gVGhpcyBoZWxwcyB1cyBvbmx5IGxvb2sgYXQgaW1wb3J0YW50IHN0dWRpb3MsIHNpbmNlIHNvbWUgc3R1ZGlvcyBtaWdodCBvbmx5IGhhdmUgMSBvciAyIG1vdmllcywgd2hpY2ggd291bGQgaW5jcmVhc2UgdGhlIHJhbmdlIG9mIGVycm9yIGluIHRoZSBhbmFseXNpcy4gQWZ0ZXIgb2J0YWluaW5nIHRoaXMgYXZlcmFnZSwgSSBncmFwaGVkIHRoZSB0b3AgMjAgaGlnaGVzdCBhbmQgbG93ZXN0IHN0dWRpb3MuIFRoaXMgaXMgaG93IHRoZSBncmFwaHMgbG9vayBsaWtlOiAKYGBge3IgaW5jbHVkZSA9IEZBTFNFfQptb3ZpZV9zdHVkaW8gPC0gZGF0YS5mcmFtZShtb3ZpZV9pZCA9IHJlcChtb3ZpZXNfY2xlYW4kaWQsIGVhY2ggPSAzKSwgc3R1ZGlvID0gYWxsX2NvbXBhbmllcykKCgptb3ZpZV9zdHVkaW9fcmF0aW5ncyA8LSBsZWZ0X2pvaW4obW92aWVfc3R1ZGlvLCBtb3ZpZXNfY2xlYW4sIGJ5ID0gYygibW92aWVfaWQiID0gImlkIikpCgoKc3R1ZGlvX3JhdGluZ3MgPC0gbW92aWVfc3R1ZGlvX3JhdGluZ3MgJT4lCiAgZ3JvdXBfYnkoc3R1ZGlvKSAlPiUKICBzdW1tYXJpemUoYXZlcmFnZV92b3RlX2F2ZXJhZ2UgPSBtZWFuKHZvdGVfYXZlcmFnZSwgbmEucm0gPSBUUlVFKSkKCgpzdHVkaW9fcmF0aW5ncyA8LSBzdHVkaW9fcmF0aW5nc1tvcmRlcihzdHVkaW9fcmF0aW5ncyRhdmVyYWdlX3ZvdGVfYXZlcmFnZSwgZGVjcmVhc2luZyA9IFRSVUUpLCBdCgoKcHJpbnQoIkF2ZXJhZ2UgUmF0aW5ncyBieSBTdHVkaW86IikKcHJpbnQoc3R1ZGlvX3JhdGluZ3MpCgpzdHVkaW9fbW92aWVfY291bnRzIDwtIG1vdmllX3N0dWRpb19yYXRpbmdzICU+JQogIGdyb3VwX2J5KHN0dWRpbykgJT4lCiAgc3VtbWFyaXplKG51bV9tb3ZpZXMgPSBuX2Rpc3RpbmN0KG1vdmllX2lkKSkKCgpzdHVkaW9fbW92aWVfY291bnRzIDwtIHN0dWRpb19tb3ZpZV9jb3VudHMgJT4lCiAgZmlsdGVyKG51bV9tb3ZpZXMgPj0gMTApCgoKc3R1ZGlvX3JhdGluZ3NfZmlsdGVyZWQgPC0gbGVmdF9qb2luKHN0dWRpb19tb3ZpZV9jb3VudHMsIHN0dWRpb19yYXRpbmdzLCBieSA9ICJzdHVkaW8iKQoKCnN0dWRpb19yYXRpbmdzX2ZpbHRlcmVkIDwtIHN0dWRpb19yYXRpbmdzX2ZpbHRlcmVkW29yZGVyKHN0dWRpb19yYXRpbmdzX2ZpbHRlcmVkJGF2ZXJhZ2Vfdm90ZV9hdmVyYWdlLCBkZWNyZWFzaW5nID0gVFJVRSksIF0KCgpwcmludCgiQXZlcmFnZSBSYXRpbmdzIGJ5IFN0dWRpbyAod2l0aCBhdCBsZWFzdCAxMCBtb3ZpZXMgbWFkZSk6IikKcHJpbnQoc3R1ZGlvX3JhdGluZ3NfZmlsdGVyZWQpCgpgYGAKYGBge3J9CiMgVG9wIDIwIGJlc3QgYW5kIHdvcnN0IHJhdGVkIHN0dWRpb3MgKGF0IGxlYXN0IDEwIG1vdmllcykKc3R1ZGlvX3JhdGluZ3NfZmlsdGVyZWQgPC0gc3R1ZGlvX3JhdGluZ3NfZmlsdGVyZWQgJT4lCiAgZmlsdGVyKCFpcy5uYShhdmVyYWdlX3ZvdGVfYXZlcmFnZSkpCgp0b3Bfc3R1ZGlvcyA8LSBoZWFkKHN0dWRpb19yYXRpbmdzX2ZpbHRlcmVkLCAyMCkKYm90dG9tX3N0dWRpb3MgPC0gdGFpbChzdHVkaW9fcmF0aW5nc19maWx0ZXJlZCwgMjApCgpnZ3Bsb3QodG9wX3N0dWRpb3MsIGFlcyh4ID0gYXZlcmFnZV92b3RlX2F2ZXJhZ2UsIHkgPSByZW9yZGVyKHN0dWRpbywgYXZlcmFnZV92b3RlX2F2ZXJhZ2UpKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gImRhcmtibHVlIikgKwogIGxhYnModGl0bGUgPSAiVG9wIDIwIFN0dWRpb3MgYnkgQXZlcmFnZSBSYXRpbmdzICh3aXRoIGF0IGxlYXN0IDEwIG1vdmllcykiLAogICAgICAgeCA9ICJBdmVyYWdlIFZvdGUgQXZlcmFnZSIsIHkgPSAiU3R1ZGlvIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxKSkKCgpnZ3Bsb3QoYm90dG9tX3N0dWRpb3MsIGFlcyh4ID0gYXZlcmFnZV92b3RlX2F2ZXJhZ2UsIHkgPSByZW9yZGVyKHN0dWRpbywgYXZlcmFnZV92b3RlX2F2ZXJhZ2UpKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIm9yYW5nZSIpICsKICBsYWJzKHRpdGxlID0gIkJvdHRvbSAyMCBTdHVkaW9zIGJ5IEF2ZXJhZ2UgUmF0aW5ncyAod2l0aCBhdCBsZWFzdCAxMCBtb3ZpZXMpIiwKICAgICAgIHggPSAiQXZlcmFnZSBWb3RlIEF2ZXJhZ2UiLCB5ID0gIlN0dWRpbyIpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMSkpCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGdyZWVuOyI+RmluZGluZ3MgYW5kIFJlc3VsdHM8L3NwYW4+IAoKQWZ0ZXIgdGhlc2UgZ3JhcGhzIGFuZCBjaGFydHMsIHdlIGNhbiBmaW5hbGx5IHZpZXcgb3VyIGZpbmRpbmdzLiBUaGUgZmlyc3QgZmluZGluZyB3ZSBjYW4gc2VlLCBpcyB0aGF0IHRoZSBnZW5yZSB3aXRoIHRoZSBtb3N0IG1vdmllcyBpcyBEcmFtYS4gQmFzZWQgb24gdGhpcywgd2UgY2FuIGFzc3VtZSAyIHRoaW5ncy4gRmlyc3QsIHRoYXQgc3R1ZGlvcyBrZWVwIG1ha2luZyBEcmFtYS1vcmllbnRlZCBtb3ZpZXMgYmVjYXVzZSB0aGVyZSBpcyBkZW1hbmQgZm9yIHRoaXMgZ2VucmUuIEJhc2VkIG9uIHRoaXMsIHdlIGNhbiBhc3N1bWUgdGhhdCBEcmFtYSBpcyB0aGUgbW9zdCBzdWNjZXNzZnVsIGdlbnJlLCBjb25zaWRlcmluZyB0aGF0IHRoZXJlIGFyZSBvdmVyIDE4IHRob3VzYW5kIG1vdmllcyB0aGF0IGhhdmUgdGhpcyBnZW5yZSBhcyBvbmUgb2YgdGhlaXIgbWFpbiBpZGVudGlmaWVycy4KCkZvciBvdXIgbmV4dCBmaW5kaW5nLCB3ZSBjYW4gc2VlIHdoaWNoIHN0dWRpb3MgYXJlIHRoZSBtb3N0IHN1Y2Nlc3NmdWwuIFRoZSB0b3AgMyBzdHVkaW9zIGluIHRlcm1zIG9mIG1vdmllcyBtYWRlIGFyZSBQYXJhbW91bnQsIEZveCBhbmQgVW5pdmVyc2FsLCB3aGljaCBhcmUgZXh0cmVtZWx5IHdlbGwga25vd24gYXQgYSBnbG9iYWwgbGV2ZWwuIFRoZSBpbnRlcmVzdGluZyBkZXRhaWwgaXMgdGhhdCB0aGVzZSAzIHN0dWRpb3MgYXJlIGFsbCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzLCBhbmQgbm90IG9ubHkgdGhhdC4gT3V0IG9mIHRoZSB0b3AgMTAgc3R1ZGlvcyB3aXRoIHRoZSBtb3N0IG1vdmllcyBtYWRlLCA5IGFyZSBmcm9tIHRoZSBVUy4gVGhpcyBsZWFkcyB0byB0aGUgY29uY2x1c2lvbiB0aGF0IG1vdmllcyBtYWRlIGluIHRoaXMgY291bnRyeSB0ZW5kIHRvIGhhdmUgaGlnaGVyIHN1Y2Nlc3MgcmF0ZXMgdGhhbiBvdGhlcnMuIFdlIGNhbiBzZWUgdGhpcyBncmFwaGljYWxseSwgc2luY2UgaW4gdGhlIOKAnE1vc3QgQ29tbW9uIENvdW50cmllc+KAnSBncmFwaCwgdGhlIFVuaXRlZCBTdGF0ZXMgaGFzIG92ZXIgMTAgdGltZXMgYXMgbWFueSBtb3ZpZXMgYXMgdGhlIHNlY29uZCBwbGFjZSAoVW5pdGVkIEtpbmdkb20pLgoKVGhpcyBzYW1lIGFyZ3VtZW50IGdvZXMgb24gdG93YXJkcyB0aGUgbmV4dCBncmFwaC4gV2UgY2FuIHNlZSB0aGF0IHRoZSBFbmdsaXNoIGxhbmd1YWdlIGlzIHRoZSBtb3N0IHBvcHVsYXIgYnkgYW4gaW5jcmVkaWJseSB3aWRlIG1hcmdpbi4gVGhpcyBpcyBub3Qgb25seSBkdWUgdG8gdGhlIGZhY3QgdGhhdCB0aGUgVVNBIGlzIHRoZSBjb3VudHJ5IHdpdGggdGhlIG1vc3QgbW92aWVzIG1hZGUsIGJ1dCBhbHNvIHRoYXQgRW5nbGlzaCB0ZW5kcyB0byBiZSBjb25zaWRlcmVkIHRoZSDigJxXb3JsZOKAmXMgTGFuZ3VhZ2XigJ0sIGFuZCBzbyBwZW9wbGUgZnJvbSBhbGwgb3ZlciB0aGUgd29ybGQgc2VlbSB0byBiZSBhdHRyYWN0ZWQgdG93YXJkcyBtb3ZpZXMgdGhhdCBoYXZlIEVuZ2xpc2ggYXMgb25lIG9mIHRoZWlyIG9wdGlvbnMuCgpUaGUgZmluYWwgb2JzZXJ2YXRpb24gdGhhdCBjYW4gYmUgbWFkZSBpcyByZWxhdGVkIHRvIHRoZSBsYXN0IGdyYXBocy4gTW9zdCBvZiB0aGUgbG93ZXIgcmFua2VkIHN0dWRpb3MgYXJlIGVpdGhlciBub3QgcHJvcGVyIHN0dWRpb3MsIG9yIGJhc2VkIGluIGNvdW50cmllcyB0aGF0IGhhdmUgYSBzbWFsbGVyIGFtb3VudCBvZiByZXNvdXJjZXMgdG8gbWFrZSB0aGVpciBtb3ZpZXMuIE9uIHRoZSBvdGhlciBoYW5kLCBtb3N0IG9mIHRoZSBzdHVkaW9zIHdpdGggdGhlIGhpZ2hlc3QgYXZlcmFnZSBzY29yZXMgaGFpbCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EuCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogZ3JlZW47Ij5Db25jbHVzaW9ucyBhbmQgUmVjb21tZW5kYXRpb25zPC9zcGFuPiAKCkFmdGVyIHRoaXMgdGhvcm91Z2ggYW5hbHlzaXMsIEkgaGF2ZSBhcnJpdmVkIGF0IHRoZSBjb25jbHVzaW9uIHRoYXQgdGhlIG1vc3QgaW1wb3J0YW50IGZhY3RvciBpbiBhIG1vdmllcyBzdWNjZXNzIGlzIGl0J3MgY291bnRyeSBvZiBwcm9kdWN0aW9uLiBPZiBjb3Vyc2UsIHRoaXMgaXMgbWFpbmx5IG9yaWVudGVkIHRvd2FyZHMgdGhlIFVuaXRlZCBTdGF0ZXMsIHdoaWNoIGNhbiBiZSBleHBsYWluZWQgYnkgdGhlIGZhY3QgdGhhdCB0aGV5IGhhdmUgdGhlIGhpZ2hlc3QgYW1vdW50IG9mIHN0dWRpb3Mgb3V0IG9mIGFueSBjb3VudHJ5IGJ5IGZhci4gQW5vdGhlciBmYWN0b3IgdGhhdCBjYW4gYmUgYXR0cmlidXRlZCB0byB0aGlzIGlzIHRoYXQgQW1lcmljYW4gc3R1ZGlvcyB0ZW5kIHRvIGhhdmUgYSBoaWdoZXIgYW1vdW50IG9mIHBvcHVsYXJpdHkuIFRha2UgVW5pdmVyc2FsIFN0dWRpb3MgZm9yIGV4YW1wbGUuIFRoaXMgc3R1ZGlvIGlzIHNvIHBvcHVsYXIsIHRoYXQgaXQgaGFzIHByZXR0eSBtdWNoIHRyYW5zY2VuZGVkIG1vdmllLW1ha2luZywgdG8gdGhlIHBvaW50IHRoYXQgaXQgZXZlbiBoYXMgYSB0aGVtZSBwYXJrIGJhc2VkIGFyb3VuZCBpdC4KClRoZSBvdGhlciBjb25jbHVzaW9uIHRoYXQgaSd2ZSByZWFjaGVkIGlzIHRoYXQgZm9yIGEgbW92aWUgdG8gYmUgc3VjY2Vzc2Z1bCwgaXQgaGFzIHRvIGF0IGxlYXN0IGhhdmUgYSB0cmFuc2xhdGlvbiB0byB0aGUgRW5nbGlzaCBsYW5ndWFnZS4gQXMgd2UgY2FuIGNsZWFybHkgc2VlLCBvdmVyIDg1JSBvZiBtb3ZpZXMgaGF2ZSB0aGUgb3B0aW9uIHRvIGJlIHdhdGNoZWQgaW4gRW5nbGlzaC4gVG8gbWUsIHRoaXMgaXMgYSBrZXkgZmFjdG9yLiBUaGlzIGlzIGR1ZSB0byB0aGUgZmFjdCB0aGF0IGl0IGlzIHRoZSBtb3N0IHBvcHVsYXIgbGFuZ3VhZ2UgaW4gdGhlIHdvcmxkLCBhbmQgc28gYWRhcHRpbmcgYSBtb3ZpZSB0byB0aGlzIGxhbmd1YWdlIGNvdWxkIHZlcnkgd2VsbCB0YWtlIGEgbW92aWUgZnJvbSBiZWluZyBhIGxvY2FsIGhpdCwgdG8gYSB3b3JsZHdpZGUgcGhlbm9tZW5vbS4KCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBncmVlbjsiPlJlZmVyZW5jZTwvc3Bhbj4gCgpNb3ZpZXMgTWV0YWRhdGEgRGF0YXNldDogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9yb3VuYWtiYW5pay90aGUtbW92aWVzLWRhdGFzZXQvZGF0YQ==