A Comparative Analysis Between Aladdin Versions Using Text Processing

The activity corresponds to comparing two movie scripts, one is from Aladdin from 1992 and the other is from Aladdin from 2019. The first is an animated version, so the task is to analyze how much the new script has been modernized and if it is still remaining faithful to his predecessor.

Necessary Libraries

library(tm)
library(pdftools)
library(SnowballC)
library(wordcloud)
library(RColorBrewer)
library(syuzhet)
library(ggplot2)
library(stringr)
library(text)
library(textdata)
library(tidytext)
library(dplyr)
library(tidyr)
library(zoo)
library(gridExtra)

Step 1: Read and Prepare the Corpus

For the 1992 script (plain text):

text_1992 <- readLines("Aladdin_1992.txt")
corp_1992 <- Corpus(VectorSource(text_1992))

For the 2019 script (PDF or plain text):

# text_2019 <- pdf_text("Aladdin_2019.pdf")
text_2019 <- readLines("Aladdin_2019.txt")
corp_2019 <- Corpus(VectorSource(text_2019))

Step 2: Data Cleaning

Now, cleaning the corpus by converting to lowercase, removing punctuation, numbers, common stopwords, and applying stemming is necessary for further analysis.

removeQuotationMarks <- content_transformer(function(x) gsub("\"", "", x))

cleanTextEnhanced <- content_transformer(function(x) {
  x <- gsub("[\"“”‘’]", "", x) # Remove all types of quotation marks including smart quotes
  x <- gsub("[[:punct:]]", "", x) # Remove all other punctuation
  x <- gsub("\\s+", " ", x) # Replace multiple spaces with a single space
  x <- trimws(x) # Trim leading and trailing whitespace
  return(x)
})

# Apply cleaning steps to corp_1992
corp_1992_clean <- tm_map(corp_1992, content_transformer(tolower))
corp_1992_clean <- tm_map(corp_1992_clean, removePunctuation, ucp = TRUE)
corp_1992_clean <- tm_map(corp_1992_clean, removeNumbers)
corp_1992_clean <- tm_map(corp_1992_clean, removeWords, stopwords("english"))

# Apply cleaning steps to corp_2019
corp_2019_clean <- tm_map(corp_2019, content_transformer(tolower))
corp_2019_clean <- tm_map(corp_2019_clean, removePunctuation, ucp = TRUE)
corp_2019_clean <- tm_map(corp_2019_clean, removeNumbers)
corp_2019_clean <- tm_map(corp_2019_clean, removeWords, stopwords("english"))

Combination of both into a single corpus for comparative analysis

corp_combined <- c(corp_1992_clean, corp_2019_clean)

Step 3: Text Analysis

Term-Document Matrix

We generate a term-document matrix to analyze word frequency

# Term-Document Matrix for the 1992 version
dtm_1992 <- TermDocumentMatrix(corp_1992_clean)

# Term-Document Matrix for the 2019 version
dtm_2019 <- TermDocumentMatrix(corp_2019_clean)

# Term-Document Matrix for Combined versions
dtm <- TermDocumentMatrix(corp_combined)
dtm_matrix <- as.matrix(dtm)

Frequency of Words

We find the most frequent terms across both scripts and their counts

freq_terms <- findFreqTerms(dtm, lowfreq = 20)
freq_matrix <- dtm_matrix[freq_terms, ]
apply(freq_matrix, 1, sum)
##       "",      "abu  "aladdin    "genie     "iago    "jafar  "jasmine   "sultan 
##      1236        47       396       168        68       156       178        71 
##       abu     abu",   agrabah     ahead   aladdin aladdin",  aladdins       ali 
##       126        22        25        21       144        33        22        58 
##     ali",    around      away      back    begins       boy       can      cant 
##        23        24        30        81        23        27        63        43 
##    carpet      cave      come     comes      dont      find      free    friend 
##        84        27        44        30        94        24        20        25 
##     genie   genie",    genies       get     gonna      good       got     gotta 
##       106        23        20        74        31        38        62        31 
##     grabs    guards      hand      head       hes       hey      iago       ill 
##        26        26        21        40        49        33        38        23 
##       ive     jafar   jasmine      just      know      lamp    lamp",      last 
##        20        88        71        79        52        64        31        20 
##       let      lets      like    little      look     looks      love     magic 
##        21        21        94        41        51        59        23        25 
##      make       man      need     never       new       now      okay       one 
##        50        39        26        63        36        69        35        77 
##    palace    people    please    prince  princess     pulls     rajah    really 
##        24        30        20       105        54        36        26        21 
##     right       say    second       see      sees     sorry      stop    street 
##        62        35        20        69        34        20        24        27 
##    sultan      take      tell     thank     thats    theres     think     three 
##        62        40        31        20        55        20        55        25 
##      time       top       try     turns       two      want       way      well 
##        32        20        23        40        27        24        40        52 
##     whole      will      wish     world       yes     youre 
##        29        74        66        25        43        58

Association Analysis

Analyze words that commonly co-occur with a specific word, such as “genie”

associations <- findAssocs(dtm, "genie", 0.3)

# Extracting the associations for 'geni' and sorting them in decreasing order
geni_associations <- associations$geni
geni_associations_sorted <- sort(geni_associations, decreasing = TRUE)

# Getting the top 10 associations
top_10_associations <- head(geni_associations_sorted, 10)

# Print the top 10 associations
print(top_10_associations)
##   "iago  "jafar along", another   apple    arms     bow   boy",   brand   bread 
##       1       1       1       1       1       1       1       1       1       1

If wanted to see all of the associations

# findAssocs(dtm, "genie", 0.3)

Frecuent Terms

# Find frequent terms in the 1992 version
ft_1992 <- findFreqTerms(dtm_1992, lowfreq = 90)

# Find frequent terms in the 2019 version
ft_2019 <- findFreqTerms(dtm_2019, lowfreq = 10)

# Extract frequencies for the 1992 version
freq_matrix_1992 <- as.matrix(dtm_1992[ft_1992, ])
freqs_1992 <- rowSums(freq_matrix_1992)

# Extract frequencies for the 2019 version
freq_matrix_2019 <- as.matrix(dtm_2019[ft_2019, ])
freqs_2019 <- rowSums(freq_matrix_2019)

# Combine into a data frame for comparison
# This will include only terms that were identified as frequent in at least one of the versions
freq_comparison <- merge(data.frame(Term = names(freqs_1992), Aladdin_1992 = freqs_1992),
                         data.frame(Term = names(freqs_2019), Aladdin_2019 = freqs_2019),
                         by = "Term", all = TRUE)

# Replace NA with 0 for terms not present in one of the versions
freq_comparison[is.na(freq_comparison)] <- 0

# Ordering by one of the frequencies for better visualization
freq_comparison <- freq_comparison[order(-freq_comparison$Aladdin_1992),]

# View the comparison
print(freq_comparison)
##           Term Aladdin_1992 Aladdin_2019
## 4      aladdin          381          193
## 42       jafar          197           66
## 45     jasmine          194           74
## 1          abu          166           29
## 28       genie          164          133
## 95      sultan          110           43
## 39        iago           93           20
## 2      agrabah            0           17
## 3        ahead            0           12
## 5          ali            0           45
## 6       anders            0           10
## 7      arabian            0           11
## 8         away            0           11
## 9         baba            0           15
## 10        back            0           17
## 11      better            0           10
## 12         boy            0           14
## 13    bracelet            0           11
## 14         can            0           43
## 15        cant            0           24
## 16      carpet            0           14
## 17        cave            0           11
## 18        come            0           22
## 19       dalia            0           15
## 20        done            0           12
## 21        dont            0           60
## 22      enough            0           12
## 23        ever            0           11
## 24       every            0           12
## 25        find            0           11
## 26        free            0           12
## 27      friend            0           18
## 29         get            0           39
## 30       gonna            0           16
## 31        good            0           17
## 32         got            0           30
## 33       gotta            0           14
## 34      guards            0           12
## 35       hakim            0           14
## 36        help            0           10
## 37         hes            0           32
## 38         hey            0           19
## 40         ill            0           10
## 41         ive            0           11
## 43       jamal            0           11
## 44        jams            0           13
## 46        jump            0           13
## 47        just            0           42
## 48         kid            0           13
## 49        know            0           41
## 50        lamp            0           38
## 51         let            0           13
## 52        life            0           12
## 53        like            0           52
## 54      little            0           20
## 55        look            0           19
## 56        love            0           12
## 57       magic            0           14
## 58        make            0           25
## 59         man            0           13
## 60       marry            0           12
## 61      master            0           13
## 62        mean            0           12
## 63      monkey            0           19
## 64        much            0           10
## 65         nay            0           11
## 66        need            0           18
## 67       never            0           37
## 68         new            0           14
## 69     nothing            0           13
## 70         now            0           40
## 71        okay            0           32
## 72         one            0           47
## 73      palace            0           10
## 74      people            0           24
## 75       place            0           12
## 76      please            0           17
## 77       power            0           10
## 78    powerful            0           11
## 79      prince            0           77
## 80    princess            0           29
## 81      really            0           11
## 82       right            0           43
## 83        said            0           15
## 84         say            0           25
## 85      second            0           13
## 86         see            0           31
## 87        seen            0           10
## 88    sherabad            0           11
## 89   something            0           10
## 90       sorry            0           10
## 91  speechless            0           10
## 92       steal            0           11
## 93        stop            0           14
## 94      street            0           10
## 96        take            0           25
## 97        tell            0           16
## 98       thank            0           14
## 99       thats            0           34
## 100     theres            0           13
## 101      thief            0           14
## 102      think            0           40
## 103    thought            0           10
## 104      three            0           15
## 105       time            0           18
## 106        try            0           14
## 107       want            0           11
## 108        way            0           21
## 109       well            0           26
## 110      whats            0           10
## 111      whole            0           13
## 112       will            0           47
## 113       wish            0           45
## 114       wont            0           16
## 115      world            0           17
## 116      years            0           10
## 117        yes            0           26
## 118      youre            0           34

Step 4: Word Cloud Analysis

color_palette <- colorRampPalette(c("#63238E", "#EEB405"))

# Convert the term-document matrix to a matrix
dtm_matrix <- as.matrix(TermDocumentMatrix(corp_combined))

# Calculate word frequencies
word_freqs <- sort(rowSums(dtm_matrix), decreasing = TRUE)

# Remove words that start or end with quotation marks from the frequency list
word_freqs <- word_freqs[!grepl('^"|"$', names(word_freqs))]

# Generate the word cloud, now excluding words with quotation marks
wordcloud(names(word_freqs), word_freqs, max.words = 20, colors = color_palette(4))

Step 5: Sentiment Analysis

# Cargar el guion de 1992
text_1992 <- readLines("Aladdin_1992.txt")
corp_1992 <- Corpus(VectorSource(text_1992))

# Cargar el guion de 2019
text_2019 <- readLines("Aladdin_2019.txt")  
corp_2019 <- Corpus(VectorSource(text_2019))

Sentiment for 1992 Version

corp_1992 <- tm_map(corp_1992, content_transformer(tolower))
corp_1992 <- tm_map(corp_1992, removePunctuation)
corp_1992 <- tm_map(corp_1992, removeNumbers)
corp_1992 <- tm_map(corp_1992, removeWords, stopwords("english"))
corp_1992 <- tm_map(corp_1992, stripWhitespace)

# Convert the corpus to plain text
text_1992_clean <- sapply(corp_1992, as.character)

# Sentiment analysis
emociones_df <- get_nrc_sentiment(text_1992_clean)

# Plotting emotion distribution
emotions_sums <- colSums(prop.table(emociones_df[, 1:8]))
barplot(emotions_sums, main = "Distribution of Emotions", ylab = "Proportion", las = 2)

# Calculate sentiment values using syuzhet
sentiment_values <- get_sentiment(text_1992_clean, method = "syuzhet")

# Generate the Syuzhet plot
plot_data <- data.frame(scores = sentiment_values, index = 1:length(sentiment_values))
ggplot(plot_data, aes(x = index, y = scores)) + 
  geom_line() + 
  geom_smooth(span = 0.05, method = "loess", colour = "blue", se = FALSE) +
  geom_smooth(span = 0.1, method = "loess", colour = "red", se = FALSE) +
  labs(title = "Syuzhet Plot", x = "Full Narrative Time", y = "Scaled Sentiment") + 
  theme_minimal()

# Generate the simplified macro shape plot
dct_values_1992 <- get_dct_transform(sentiment_values, low_pass_size = 5, x_reverse_len = length(sentiment_values))
plot_data_dct <- data.frame(scores = dct_values_1992, index = 1:length(dct_values_1992))
ggplot(plot_data_dct, aes(x = index, y = scores)) + 
  geom_line(colour = "red") +
  labs(title = "Simplified Macro Shape", x = "Normalized Narrative Time", y = "Scaled Sentiment") +
  theme_minimal()

Sentiment for 2019 Version

corp_2019 <- tm_map(corp_2019, content_transformer(tolower))
corp_2019 <- tm_map(corp_2019, removePunctuation)
corp_2019 <- tm_map(corp_2019, removeNumbers)
corp_2019 <- tm_map(corp_2019, removeWords, stopwords("english"))
corp_2019 <- tm_map(corp_2019, stripWhitespace)

# Convert the corpus to plain text
text_2019_clean <- sapply(corp_2019, as.character)

# Sentiment analysis
emociones_df <- get_nrc_sentiment(text_2019_clean)

# Plotting emotion distribution
emotions_sums_2019 <- colSums(prop.table(emociones_df[, 1:8]))
barplot(emotions_sums_2019, main = "Distribution of Emotions", ylab = "Proportion", las = 2)

# Calculate sentiment values using syuzhet
sentiment_values <- get_sentiment(text_2019_clean, method = "syuzhet")

# Generate the Syuzhet plot
plot_data <- data.frame(scores = sentiment_values, index = 1:length(sentiment_values))
ggplot(plot_data, aes(x = index, y = scores)) + 
  geom_line() + 
  geom_smooth(span = 0.05, method = "loess", colour = "blue", se = FALSE) +
  geom_smooth(span = 0.1, method = "loess", colour = "red", se = FALSE) +
  labs(title = "Syuzhet Plot", x = "Full Narrative Time", y = "Scaled Sentiment") + 
  theme_minimal()

# Generate the simplified macro shape plot
dct_values_2019 <- get_dct_transform(sentiment_values, low_pass_size = 5, x_reverse_len = length(sentiment_values))
plot_data_dct <- data.frame(scores = dct_values_2019, index = 1:length(dct_values_2019))
ggplot(plot_data_dct, aes(x = index, y = scores)) + 
  geom_line(colour = "red") +
  labs(title = "Simplified Macro Shape", x = "Normalized Narrative Time", y = "Scaled Sentiment") +
  theme_minimal()

Combined Aladdin Analysis

# Bar plot for emotion distribution for both versions
emotions_df_combined <- rbind(data.frame(Emotion = names(emotions_sums), Proportion = emotions_sums, Version = "1992"),
                              data.frame(Emotion = names(emotions_sums_2019), Proportion = emotions_sums_2019, Version = "2019"))

# Plotting combined bar plot
ggplot(emotions_df_combined, aes(x = Emotion, y = Proportion, fill = Version)) + 
  geom_bar(stat = "identity", position = position_dodge(width = 0.7)) +
  scale_fill_manual(values = c("1992" = "#EEB405", "2019" = "#63238E")) +
  labs(title = "Emotion Distribution in Aladdin 1992 vs. 2019", y = "Proportion", x = "Emotion") +
  theme_minimal()

# Plotting simplified sentiment trend for 1992 version
plot_1992 <- ggplot(data = data.frame(Index = 1:length(dct_values_1992), Score = dct_values_1992), 
                    aes(x = Index, y = Score)) +
              geom_line(color = "#EEB405") +
              labs(title = "Simplified Sentiment Trend in Aladdin 1992", x = "Narrative Time", y = "Sentiment Score") +
              theme_minimal()

# Plotting simplified sentiment trend for 2019 version
plot_2019 <- ggplot(data = data.frame(Index = 1:length(dct_values_2019), Score = dct_values_2019), 
                    aes(x = Index, y = Score)) +
              geom_line(color = "#63238E") +
              labs(title = "Simplified Sentiment Trend in Aladdin 2019", x = "Narrative Time", y = "Sentiment Score") +
              theme_minimal()

# Determine the length of the longer plot
max_length <- max(length(dct_values_1992), length(dct_values_2019))

# Set up the grid
grid.arrange(plot_1992, plot_2019, ncol = 1)

Comparative Analysis Highlights

  • Length and Repetition: The script from Aladdin (1992) exhibits a greater length, resulting in a more frequent repetition of certain words and character names. This trend suggests a richer dialogue and more numerous musical sequences in the animated classic.

  • Adaptation and Innovation: The 2019 rendition of Aladdin diverges subtly from its predecessor, not only by condensing the script but also by introducing new dialogues and songs absent in the original. This variation indicates an effort to modernize the story while maintaining its core essence.

  • Key Characters: The names “Aladdin” and “Abu” are amongst the most repeated, underscoring their central role in the narrative. Their prominence across both versions highlights their significance as the main protagonist and his companion, respectively.

  • Character Associations: The character “Genie” is notably linked with “carpet,” reflecting their interactions within the narrative. The association analysis also connects Genie with terms like “afraid” and “along,” likely emerging from dialogues involving Aladdin or Abu, pointing to the depth of their relationships.

  • Sentiment Analysis: Despite differing lengths, both scripts show a similar sentiment trajectory, peaking with positive emotions towards the climax. Notably, the 2019 script exhibits fewer negative sentiments compared to the 1992 version, which emphasized such emotions early on. This shift suggests a modern adaptation’s preference for gradually building positive moments, illustrating a nuanced change in storytelling approach.

  • Emotional Dynamics: The overall balance of emotions between the two versions remains remarkably consistent, indicating that the fundamental tone of the story has been preserved across adaptations.

Analysis Scope

What Will Be Analyzed?

Inclusion Criteria: - All of the text in the script, including characters, notes, songs, etc. - Title and or subtitles included are also being analyze.

Exclusion Criteria: - Stop words, punctuation and capital letters are being transformed or eliminated.

Why or Why Not?

The elimination of punctuation, stop words and capital letter do not search to bias the analysis but in the contrary make it easier and prevent exceeding from the necessary data from which important insights can be obtained.

LS0tCnRpdGxlOiAiQWxhZGRpbiBDb21wYXJpc29uIC0gVGV4dCBQcm9jZXNzaW5nIgphdXRob3I6ICJEYXZpZCBEb21pbmd1ZXogLSBBMDE1NzA5NzUiCmRhdGU6ICIyMDI0LTAzLTI4IgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgY29kZV9kb3dubG9hZDogVFJVRQogICAgdGhlbWU6IGNvc21vCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiBzZW50ZW5jZQotLS0KCiMgQSBDb21wYXJhdGl2ZSBBbmFseXNpcyBCZXR3ZWVuIEFsYWRkaW4gVmVyc2lvbnMgVXNpbmcgVGV4dCBQcm9jZXNzaW5nClRoZSBhY3Rpdml0eSBjb3JyZXNwb25kcyB0byBjb21wYXJpbmcgdHdvIG1vdmllIHNjcmlwdHMsIG9uZSBpcyBmcm9tIEFsYWRkaW4gZnJvbSAxOTkyIGFuZCB0aGUgb3RoZXIgaXMgZnJvbSBBbGFkZGluIGZyb20gMjAxOS4gVGhlIGZpcnN0IGlzIGFuIGFuaW1hdGVkIHZlcnNpb24sIHNvIHRoZSB0YXNrIGlzIHRvIGFuYWx5emUgaG93IG11Y2ggdGhlIG5ldyBzY3JpcHQgaGFzIGJlZW4gbW9kZXJuaXplZCBhbmQgaWYgaXQgaXMgc3RpbGwgcmVtYWluaW5nIGZhaXRoZnVsIHRvIGhpcyBwcmVkZWNlc3Nvci4KCiMjIE5lY2Vzc2FyeSBMaWJyYXJpZXMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0bSkKbGlicmFyeShwZGZ0b29scykKbGlicmFyeShTbm93YmFsbEMpCmxpYnJhcnkod29yZGNsb3VkKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShzeXV6aGV0KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0ZXh0KQpsaWJyYXJ5KHRleHRkYXRhKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHpvbykKbGlicmFyeShncmlkRXh0cmEpCmBgYAoKIyMgU3RlcCAxOiBSZWFkIGFuZCBQcmVwYXJlIHRoZSBDb3JwdXMKCkZvciB0aGUgMTk5MiBzY3JpcHQgKHBsYWluIHRleHQpOgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0ZXh0XzE5OTIgPC0gcmVhZExpbmVzKCJBbGFkZGluXzE5OTIudHh0IikKY29ycF8xOTkyIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dF8xOTkyKSkKYGBgCgpGb3IgdGhlIDIwMTkgc2NyaXB0IChQREYgb3IgcGxhaW4gdGV4dCk6CmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgdGV4dF8yMDE5IDwtIHBkZl90ZXh0KCJBbGFkZGluXzIwMTkucGRmIikKdGV4dF8yMDE5IDwtIHJlYWRMaW5lcygiQWxhZGRpbl8yMDE5LnR4dCIpCmNvcnBfMjAxOSA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHRfMjAxOSkpCmBgYAoKIyMgU3RlcCAyOiBEYXRhIENsZWFuaW5nCk5vdywgY2xlYW5pbmcgdGhlIGNvcnB1cyBieSBjb252ZXJ0aW5nIHRvIGxvd2VyY2FzZSwgcmVtb3ZpbmcgcHVuY3R1YXRpb24sIG51bWJlcnMsIGNvbW1vbiBzdG9wd29yZHMsIGFuZCBhcHBseWluZyBzdGVtbWluZyBpcyBuZWNlc3NhcnkgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpyZW1vdmVRdW90YXRpb25NYXJrcyA8LSBjb250ZW50X3RyYW5zZm9ybWVyKGZ1bmN0aW9uKHgpIGdzdWIoIlwiIiwgIiIsIHgpKQoKY2xlYW5UZXh0RW5oYW5jZWQgPC0gY29udGVudF90cmFuc2Zvcm1lcihmdW5jdGlvbih4KSB7CiAgeCA8LSBnc3ViKCJbXCLigJzigJ3igJjigJldIiwgIiIsIHgpICMgUmVtb3ZlIGFsbCB0eXBlcyBvZiBxdW90YXRpb24gbWFya3MgaW5jbHVkaW5nIHNtYXJ0IHF1b3RlcwogIHggPC0gZ3N1YigiW1s6cHVuY3Q6XV0iLCAiIiwgeCkgIyBSZW1vdmUgYWxsIG90aGVyIHB1bmN0dWF0aW9uCiAgeCA8LSBnc3ViKCJcXHMrIiwgIiAiLCB4KSAjIFJlcGxhY2UgbXVsdGlwbGUgc3BhY2VzIHdpdGggYSBzaW5nbGUgc3BhY2UKICB4IDwtIHRyaW13cyh4KSAjIFRyaW0gbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZQogIHJldHVybih4KQp9KQoKIyBBcHBseSBjbGVhbmluZyBzdGVwcyB0byBjb3JwXzE5OTIKY29ycF8xOTkyX2NsZWFuIDwtIHRtX21hcChjb3JwXzE5OTIsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpCmNvcnBfMTk5Ml9jbGVhbiA8LSB0bV9tYXAoY29ycF8xOTkyX2NsZWFuLCByZW1vdmVQdW5jdHVhdGlvbiwgdWNwID0gVFJVRSkKY29ycF8xOTkyX2NsZWFuIDwtIHRtX21hcChjb3JwXzE5OTJfY2xlYW4sIHJlbW92ZU51bWJlcnMpCmNvcnBfMTk5Ml9jbGVhbiA8LSB0bV9tYXAoY29ycF8xOTkyX2NsZWFuLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCgojIEFwcGx5IGNsZWFuaW5nIHN0ZXBzIHRvIGNvcnBfMjAxOQpjb3JwXzIwMTlfY2xlYW4gPC0gdG1fbWFwKGNvcnBfMjAxOSwgY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKY29ycF8yMDE5X2NsZWFuIDwtIHRtX21hcChjb3JwXzIwMTlfY2xlYW4sIHJlbW92ZVB1bmN0dWF0aW9uLCB1Y3AgPSBUUlVFKQpjb3JwXzIwMTlfY2xlYW4gPC0gdG1fbWFwKGNvcnBfMjAxOV9jbGVhbiwgcmVtb3ZlTnVtYmVycykKY29ycF8yMDE5X2NsZWFuIDwtIHRtX21hcChjb3JwXzIwMTlfY2xlYW4sIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkKYGBgCgpDb21iaW5hdGlvbiBvZiBib3RoIGludG8gYSBzaW5nbGUgY29ycHVzIGZvciBjb21wYXJhdGl2ZSBhbmFseXNpcwpgYGB7cn0KY29ycF9jb21iaW5lZCA8LSBjKGNvcnBfMTk5Ml9jbGVhbiwgY29ycF8yMDE5X2NsZWFuKQpgYGAKCiMjIFN0ZXAgMzogVGV4dCBBbmFseXNpcwojIyMgVGVybS1Eb2N1bWVudCBNYXRyaXgKCldlIGdlbmVyYXRlIGEgdGVybS1kb2N1bWVudCBtYXRyaXggdG8gYW5hbHl6ZSB3b3JkIGZyZXF1ZW5jeQpgYGB7cn0KIyBUZXJtLURvY3VtZW50IE1hdHJpeCBmb3IgdGhlIDE5OTIgdmVyc2lvbgpkdG1fMTk5MiA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycF8xOTkyX2NsZWFuKQoKIyBUZXJtLURvY3VtZW50IE1hdHJpeCBmb3IgdGhlIDIwMTkgdmVyc2lvbgpkdG1fMjAxOSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycF8yMDE5X2NsZWFuKQoKIyBUZXJtLURvY3VtZW50IE1hdHJpeCBmb3IgQ29tYmluZWQgdmVyc2lvbnMKZHRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChjb3JwX2NvbWJpbmVkKQpkdG1fbWF0cml4IDwtIGFzLm1hdHJpeChkdG0pCmBgYAoKIyMjIEZyZXF1ZW5jeSBvZiBXb3JkcwpXZSBmaW5kIHRoZSBtb3N0IGZyZXF1ZW50IHRlcm1zIGFjcm9zcyBib3RoIHNjcmlwdHMgYW5kIHRoZWlyIGNvdW50cwpgYGB7cn0KZnJlcV90ZXJtcyA8LSBmaW5kRnJlcVRlcm1zKGR0bSwgbG93ZnJlcSA9IDIwKQpmcmVxX21hdHJpeCA8LSBkdG1fbWF0cml4W2ZyZXFfdGVybXMsIF0KYXBwbHkoZnJlcV9tYXRyaXgsIDEsIHN1bSkKYGBgCgojIyMgQXNzb2NpYXRpb24gQW5hbHlzaXMKQW5hbHl6ZSB3b3JkcyB0aGF0IGNvbW1vbmx5IGNvLW9jY3VyIHdpdGggYSBzcGVjaWZpYyB3b3JkLCBzdWNoIGFzICJnZW5pZSIKYGBge3J9CmFzc29jaWF0aW9ucyA8LSBmaW5kQXNzb2NzKGR0bSwgImdlbmllIiwgMC4zKQoKIyBFeHRyYWN0aW5nIHRoZSBhc3NvY2lhdGlvbnMgZm9yICdnZW5pJyBhbmQgc29ydGluZyB0aGVtIGluIGRlY3JlYXNpbmcgb3JkZXIKZ2VuaV9hc3NvY2lhdGlvbnMgPC0gYXNzb2NpYXRpb25zJGdlbmkKZ2VuaV9hc3NvY2lhdGlvbnNfc29ydGVkIDwtIHNvcnQoZ2VuaV9hc3NvY2lhdGlvbnMsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBHZXR0aW5nIHRoZSB0b3AgMTAgYXNzb2NpYXRpb25zCnRvcF8xMF9hc3NvY2lhdGlvbnMgPC0gaGVhZChnZW5pX2Fzc29jaWF0aW9uc19zb3J0ZWQsIDEwKQoKIyBQcmludCB0aGUgdG9wIDEwIGFzc29jaWF0aW9ucwpwcmludCh0b3BfMTBfYXNzb2NpYXRpb25zKQpgYGAKCklmIHdhbnRlZCB0byBzZWUgYWxsIG9mIHRoZSBhc3NvY2lhdGlvbnMKYGBge3J9CiMgZmluZEFzc29jcyhkdG0sICJnZW5pZSIsIDAuMykKYGBgCgojIyMgRnJlY3VlbnQgVGVybXMKYGBge3J9CiMgRmluZCBmcmVxdWVudCB0ZXJtcyBpbiB0aGUgMTk5MiB2ZXJzaW9uCmZ0XzE5OTIgPC0gZmluZEZyZXFUZXJtcyhkdG1fMTk5MiwgbG93ZnJlcSA9IDkwKQoKIyBGaW5kIGZyZXF1ZW50IHRlcm1zIGluIHRoZSAyMDE5IHZlcnNpb24KZnRfMjAxOSA8LSBmaW5kRnJlcVRlcm1zKGR0bV8yMDE5LCBsb3dmcmVxID0gMTApCgojIEV4dHJhY3QgZnJlcXVlbmNpZXMgZm9yIHRoZSAxOTkyIHZlcnNpb24KZnJlcV9tYXRyaXhfMTk5MiA8LSBhcy5tYXRyaXgoZHRtXzE5OTJbZnRfMTk5MiwgXSkKZnJlcXNfMTk5MiA8LSByb3dTdW1zKGZyZXFfbWF0cml4XzE5OTIpCgojIEV4dHJhY3QgZnJlcXVlbmNpZXMgZm9yIHRoZSAyMDE5IHZlcnNpb24KZnJlcV9tYXRyaXhfMjAxOSA8LSBhcy5tYXRyaXgoZHRtXzIwMTlbZnRfMjAxOSwgXSkKZnJlcXNfMjAxOSA8LSByb3dTdW1zKGZyZXFfbWF0cml4XzIwMTkpCgojIENvbWJpbmUgaW50byBhIGRhdGEgZnJhbWUgZm9yIGNvbXBhcmlzb24KIyBUaGlzIHdpbGwgaW5jbHVkZSBvbmx5IHRlcm1zIHRoYXQgd2VyZSBpZGVudGlmaWVkIGFzIGZyZXF1ZW50IGluIGF0IGxlYXN0IG9uZSBvZiB0aGUgdmVyc2lvbnMKZnJlcV9jb21wYXJpc29uIDwtIG1lcmdlKGRhdGEuZnJhbWUoVGVybSA9IG5hbWVzKGZyZXFzXzE5OTIpLCBBbGFkZGluXzE5OTIgPSBmcmVxc18xOTkyKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoVGVybSA9IG5hbWVzKGZyZXFzXzIwMTkpLCBBbGFkZGluXzIwMTkgPSBmcmVxc18yMDE5KSwKICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIlRlcm0iLCBhbGwgPSBUUlVFKQoKIyBSZXBsYWNlIE5BIHdpdGggMCBmb3IgdGVybXMgbm90IHByZXNlbnQgaW4gb25lIG9mIHRoZSB2ZXJzaW9ucwpmcmVxX2NvbXBhcmlzb25baXMubmEoZnJlcV9jb21wYXJpc29uKV0gPC0gMAoKIyBPcmRlcmluZyBieSBvbmUgb2YgdGhlIGZyZXF1ZW5jaWVzIGZvciBiZXR0ZXIgdmlzdWFsaXphdGlvbgpmcmVxX2NvbXBhcmlzb24gPC0gZnJlcV9jb21wYXJpc29uW29yZGVyKC1mcmVxX2NvbXBhcmlzb24kQWxhZGRpbl8xOTkyKSxdCgojIFZpZXcgdGhlIGNvbXBhcmlzb24KcHJpbnQoZnJlcV9jb21wYXJpc29uKQpgYGAKCgojIyBTdGVwIDQ6IFdvcmQgQ2xvdWQgQW5hbHlzaXMKCmBgYHtyfQpjb2xvcl9wYWxldHRlIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiIzYzMjM4RSIsICIjRUVCNDA1IikpCgojIENvbnZlcnQgdGhlIHRlcm0tZG9jdW1lbnQgbWF0cml4IHRvIGEgbWF0cml4CmR0bV9tYXRyaXggPC0gYXMubWF0cml4KFRlcm1Eb2N1bWVudE1hdHJpeChjb3JwX2NvbWJpbmVkKSkKCiMgQ2FsY3VsYXRlIHdvcmQgZnJlcXVlbmNpZXMKd29yZF9mcmVxcyA8LSBzb3J0KHJvd1N1bXMoZHRtX21hdHJpeCksIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBSZW1vdmUgd29yZHMgdGhhdCBzdGFydCBvciBlbmQgd2l0aCBxdW90YXRpb24gbWFya3MgZnJvbSB0aGUgZnJlcXVlbmN5IGxpc3QKd29yZF9mcmVxcyA8LSB3b3JkX2ZyZXFzWyFncmVwbCgnXiJ8IiQnLCBuYW1lcyh3b3JkX2ZyZXFzKSldCgojIEdlbmVyYXRlIHRoZSB3b3JkIGNsb3VkLCBub3cgZXhjbHVkaW5nIHdvcmRzIHdpdGggcXVvdGF0aW9uIG1hcmtzCndvcmRjbG91ZChuYW1lcyh3b3JkX2ZyZXFzKSwgd29yZF9mcmVxcywgbWF4LndvcmRzID0gMjAsIGNvbG9ycyA9IGNvbG9yX3BhbGV0dGUoNCkpCmBgYAoKIyMgU3RlcCA1OiBTZW50aW1lbnQgQW5hbHlzaXMKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgQ2FyZ2FyIGVsIGd1aW9uIGRlIDE5OTIKdGV4dF8xOTkyIDwtIHJlYWRMaW5lcygiQWxhZGRpbl8xOTkyLnR4dCIpCmNvcnBfMTk5MiA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHRfMTk5MikpCgojIENhcmdhciBlbCBndWlvbiBkZSAyMDE5CnRleHRfMjAxOSA8LSByZWFkTGluZXMoIkFsYWRkaW5fMjAxOS50eHQiKSAgCmNvcnBfMjAxOSA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHRfMjAxOSkpCmBgYAoKIyMjIFNlbnRpbWVudCBmb3IgMTk5MiBWZXJzaW9uCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvcnBfMTk5MiA8LSB0bV9tYXAoY29ycF8xOTkyLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQpjb3JwXzE5OTIgPC0gdG1fbWFwKGNvcnBfMTk5MiwgcmVtb3ZlUHVuY3R1YXRpb24pCmNvcnBfMTk5MiA8LSB0bV9tYXAoY29ycF8xOTkyLCByZW1vdmVOdW1iZXJzKQpjb3JwXzE5OTIgPC0gdG1fbWFwKGNvcnBfMTk5MiwgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKQpjb3JwXzE5OTIgPC0gdG1fbWFwKGNvcnBfMTk5Miwgc3RyaXBXaGl0ZXNwYWNlKQoKIyBDb252ZXJ0IHRoZSBjb3JwdXMgdG8gcGxhaW4gdGV4dAp0ZXh0XzE5OTJfY2xlYW4gPC0gc2FwcGx5KGNvcnBfMTk5MiwgYXMuY2hhcmFjdGVyKQoKIyBTZW50aW1lbnQgYW5hbHlzaXMKZW1vY2lvbmVzX2RmIDwtIGdldF9ucmNfc2VudGltZW50KHRleHRfMTk5Ml9jbGVhbikKCiMgUGxvdHRpbmcgZW1vdGlvbiBkaXN0cmlidXRpb24KZW1vdGlvbnNfc3VtcyA8LSBjb2xTdW1zKHByb3AudGFibGUoZW1vY2lvbmVzX2RmWywgMTo4XSkpCmJhcnBsb3QoZW1vdGlvbnNfc3VtcywgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgRW1vdGlvbnMiLCB5bGFiID0gIlByb3BvcnRpb24iLCBsYXMgPSAyKQoKIyBDYWxjdWxhdGUgc2VudGltZW50IHZhbHVlcyB1c2luZyBzeXV6aGV0CnNlbnRpbWVudF92YWx1ZXMgPC0gZ2V0X3NlbnRpbWVudCh0ZXh0XzE5OTJfY2xlYW4sIG1ldGhvZCA9ICJzeXV6aGV0IikKCiMgR2VuZXJhdGUgdGhlIFN5dXpoZXQgcGxvdApwbG90X2RhdGEgPC0gZGF0YS5mcmFtZShzY29yZXMgPSBzZW50aW1lbnRfdmFsdWVzLCBpbmRleCA9IDE6bGVuZ3RoKHNlbnRpbWVudF92YWx1ZXMpKQpnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IGluZGV4LCB5ID0gc2NvcmVzKSkgKyAKICBnZW9tX2xpbmUoKSArIAogIGdlb21fc21vb3RoKHNwYW4gPSAwLjA1LCBtZXRob2QgPSAibG9lc3MiLCBjb2xvdXIgPSAiYmx1ZSIsIHNlID0gRkFMU0UpICsKICBnZW9tX3Ntb290aChzcGFuID0gMC4xLCBtZXRob2QgPSAibG9lc3MiLCBjb2xvdXIgPSAicmVkIiwgc2UgPSBGQUxTRSkgKwogIGxhYnModGl0bGUgPSAiU3l1emhldCBQbG90IiwgeCA9ICJGdWxsIE5hcnJhdGl2ZSBUaW1lIiwgeSA9ICJTY2FsZWQgU2VudGltZW50IikgKyAKICB0aGVtZV9taW5pbWFsKCkKCiMgR2VuZXJhdGUgdGhlIHNpbXBsaWZpZWQgbWFjcm8gc2hhcGUgcGxvdApkY3RfdmFsdWVzXzE5OTIgPC0gZ2V0X2RjdF90cmFuc2Zvcm0oc2VudGltZW50X3ZhbHVlcywgbG93X3Bhc3Nfc2l6ZSA9IDUsIHhfcmV2ZXJzZV9sZW4gPSBsZW5ndGgoc2VudGltZW50X3ZhbHVlcykpCnBsb3RfZGF0YV9kY3QgPC0gZGF0YS5mcmFtZShzY29yZXMgPSBkY3RfdmFsdWVzXzE5OTIsIGluZGV4ID0gMTpsZW5ndGgoZGN0X3ZhbHVlc18xOTkyKSkKZ2dwbG90KHBsb3RfZGF0YV9kY3QsIGFlcyh4ID0gaW5kZXgsIHkgPSBzY29yZXMpKSArIAogIGdlb21fbGluZShjb2xvdXIgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSAiU2ltcGxpZmllZCBNYWNybyBTaGFwZSIsIHggPSAiTm9ybWFsaXplZCBOYXJyYXRpdmUgVGltZSIsIHkgPSAiU2NhbGVkIFNlbnRpbWVudCIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyMgU2VudGltZW50IGZvciAyMDE5IFZlcnNpb24KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY29ycF8yMDE5IDwtIHRtX21hcChjb3JwXzIwMTksIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpCmNvcnBfMjAxOSA8LSB0bV9tYXAoY29ycF8yMDE5LCByZW1vdmVQdW5jdHVhdGlvbikKY29ycF8yMDE5IDwtIHRtX21hcChjb3JwXzIwMTksIHJlbW92ZU51bWJlcnMpCmNvcnBfMjAxOSA8LSB0bV9tYXAoY29ycF8yMDE5LCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCmNvcnBfMjAxOSA8LSB0bV9tYXAoY29ycF8yMDE5LCBzdHJpcFdoaXRlc3BhY2UpCgojIENvbnZlcnQgdGhlIGNvcnB1cyB0byBwbGFpbiB0ZXh0CnRleHRfMjAxOV9jbGVhbiA8LSBzYXBwbHkoY29ycF8yMDE5LCBhcy5jaGFyYWN0ZXIpCgojIFNlbnRpbWVudCBhbmFseXNpcwplbW9jaW9uZXNfZGYgPC0gZ2V0X25yY19zZW50aW1lbnQodGV4dF8yMDE5X2NsZWFuKQoKIyBQbG90dGluZyBlbW90aW9uIGRpc3RyaWJ1dGlvbgplbW90aW9uc19zdW1zXzIwMTkgPC0gY29sU3Vtcyhwcm9wLnRhYmxlKGVtb2Npb25lc19kZlssIDE6OF0pKQpiYXJwbG90KGVtb3Rpb25zX3N1bXNfMjAxOSwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgRW1vdGlvbnMiLCB5bGFiID0gIlByb3BvcnRpb24iLCBsYXMgPSAyKQoKIyBDYWxjdWxhdGUgc2VudGltZW50IHZhbHVlcyB1c2luZyBzeXV6aGV0CnNlbnRpbWVudF92YWx1ZXMgPC0gZ2V0X3NlbnRpbWVudCh0ZXh0XzIwMTlfY2xlYW4sIG1ldGhvZCA9ICJzeXV6aGV0IikKCiMgR2VuZXJhdGUgdGhlIFN5dXpoZXQgcGxvdApwbG90X2RhdGEgPC0gZGF0YS5mcmFtZShzY29yZXMgPSBzZW50aW1lbnRfdmFsdWVzLCBpbmRleCA9IDE6bGVuZ3RoKHNlbnRpbWVudF92YWx1ZXMpKQpnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IGluZGV4LCB5ID0gc2NvcmVzKSkgKyAKICBnZW9tX2xpbmUoKSArIAogIGdlb21fc21vb3RoKHNwYW4gPSAwLjA1LCBtZXRob2QgPSAibG9lc3MiLCBjb2xvdXIgPSAiYmx1ZSIsIHNlID0gRkFMU0UpICsKICBnZW9tX3Ntb290aChzcGFuID0gMC4xLCBtZXRob2QgPSAibG9lc3MiLCBjb2xvdXIgPSAicmVkIiwgc2UgPSBGQUxTRSkgKwogIGxhYnModGl0bGUgPSAiU3l1emhldCBQbG90IiwgeCA9ICJGdWxsIE5hcnJhdGl2ZSBUaW1lIiwgeSA9ICJTY2FsZWQgU2VudGltZW50IikgKyAKICB0aGVtZV9taW5pbWFsKCkKCiMgR2VuZXJhdGUgdGhlIHNpbXBsaWZpZWQgbWFjcm8gc2hhcGUgcGxvdApkY3RfdmFsdWVzXzIwMTkgPC0gZ2V0X2RjdF90cmFuc2Zvcm0oc2VudGltZW50X3ZhbHVlcywgbG93X3Bhc3Nfc2l6ZSA9IDUsIHhfcmV2ZXJzZV9sZW4gPSBsZW5ndGgoc2VudGltZW50X3ZhbHVlcykpCnBsb3RfZGF0YV9kY3QgPC0gZGF0YS5mcmFtZShzY29yZXMgPSBkY3RfdmFsdWVzXzIwMTksIGluZGV4ID0gMTpsZW5ndGgoZGN0X3ZhbHVlc18yMDE5KSkKZ2dwbG90KHBsb3RfZGF0YV9kY3QsIGFlcyh4ID0gaW5kZXgsIHkgPSBzY29yZXMpKSArIAogIGdlb21fbGluZShjb2xvdXIgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSAiU2ltcGxpZmllZCBNYWNybyBTaGFwZSIsIHggPSAiTm9ybWFsaXplZCBOYXJyYXRpdmUgVGltZSIsIHkgPSAiU2NhbGVkIFNlbnRpbWVudCIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyMgQ29tYmluZWQgQWxhZGRpbiBBbmFseXNpcwpgYGB7cn0KIyBCYXIgcGxvdCBmb3IgZW1vdGlvbiBkaXN0cmlidXRpb24gZm9yIGJvdGggdmVyc2lvbnMKZW1vdGlvbnNfZGZfY29tYmluZWQgPC0gcmJpbmQoZGF0YS5mcmFtZShFbW90aW9uID0gbmFtZXMoZW1vdGlvbnNfc3VtcyksIFByb3BvcnRpb24gPSBlbW90aW9uc19zdW1zLCBWZXJzaW9uID0gIjE5OTIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZShFbW90aW9uID0gbmFtZXMoZW1vdGlvbnNfc3Vtc18yMDE5KSwgUHJvcG9ydGlvbiA9IGVtb3Rpb25zX3N1bXNfMjAxOSwgVmVyc2lvbiA9ICIyMDE5IikpCgojIFBsb3R0aW5nIGNvbWJpbmVkIGJhciBwbG90CmdncGxvdChlbW90aW9uc19kZl9jb21iaW5lZCwgYWVzKHggPSBFbW90aW9uLCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IFZlcnNpb24pKSArIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIjE5OTIiID0gIiNFRUI0MDUiLCAiMjAxOSIgPSAiIzYzMjM4RSIpKSArCiAgbGFicyh0aXRsZSA9ICJFbW90aW9uIERpc3RyaWJ1dGlvbiBpbiBBbGFkZGluIDE5OTIgdnMuIDIwMTkiLCB5ID0gIlByb3BvcnRpb24iLCB4ID0gIkVtb3Rpb24iKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIFBsb3R0aW5nIHNpbXBsaWZpZWQgc2VudGltZW50IHRyZW5kIGZvciAxOTkyIHZlcnNpb24KcGxvdF8xOTkyIDwtIGdncGxvdChkYXRhID0gZGF0YS5mcmFtZShJbmRleCA9IDE6bGVuZ3RoKGRjdF92YWx1ZXNfMTk5MiksIFNjb3JlID0gZGN0X3ZhbHVlc18xOTkyKSwgCiAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBJbmRleCwgeSA9IFNjb3JlKSkgKwogICAgICAgICAgICAgIGdlb21fbGluZShjb2xvciA9ICIjRUVCNDA1IikgKwogICAgICAgICAgICAgIGxhYnModGl0bGUgPSAiU2ltcGxpZmllZCBTZW50aW1lbnQgVHJlbmQgaW4gQWxhZGRpbiAxOTkyIiwgeCA9ICJOYXJyYXRpdmUgVGltZSIsIHkgPSAiU2VudGltZW50IFNjb3JlIikgKwogICAgICAgICAgICAgIHRoZW1lX21pbmltYWwoKQoKIyBQbG90dGluZyBzaW1wbGlmaWVkIHNlbnRpbWVudCB0cmVuZCBmb3IgMjAxOSB2ZXJzaW9uCnBsb3RfMjAxOSA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEuZnJhbWUoSW5kZXggPSAxOmxlbmd0aChkY3RfdmFsdWVzXzIwMTkpLCBTY29yZSA9IGRjdF92YWx1ZXNfMjAxOSksIAogICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gSW5kZXgsIHkgPSBTY29yZSkpICsKICAgICAgICAgICAgICBnZW9tX2xpbmUoY29sb3IgPSAiIzYzMjM4RSIpICsKICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gIlNpbXBsaWZpZWQgU2VudGltZW50IFRyZW5kIGluIEFsYWRkaW4gMjAxOSIsIHggPSAiTmFycmF0aXZlIFRpbWUiLCB5ID0gIlNlbnRpbWVudCBTY29yZSIpICsKICAgICAgICAgICAgICB0aGVtZV9taW5pbWFsKCkKCiMgRGV0ZXJtaW5lIHRoZSBsZW5ndGggb2YgdGhlIGxvbmdlciBwbG90Cm1heF9sZW5ndGggPC0gbWF4KGxlbmd0aChkY3RfdmFsdWVzXzE5OTIpLCBsZW5ndGgoZGN0X3ZhbHVlc18yMDE5KSkKCiMgU2V0IHVwIHRoZSBncmlkCmdyaWQuYXJyYW5nZShwbG90XzE5OTIsIHBsb3RfMjAxOSwgbmNvbCA9IDEpCmBgYAoKIyMgQ29tcGFyYXRpdmUgQW5hbHlzaXMgSGlnaGxpZ2h0cwoKLSAqKkxlbmd0aCBhbmQgUmVwZXRpdGlvbioqOiBUaGUgc2NyaXB0IGZyb20gKkFsYWRkaW4qICgxOTkyKSBleGhpYml0cyBhIGdyZWF0ZXIgbGVuZ3RoLCByZXN1bHRpbmcgaW4gYSBtb3JlIGZyZXF1ZW50IHJlcGV0aXRpb24gb2YgY2VydGFpbiB3b3JkcyBhbmQgY2hhcmFjdGVyIG5hbWVzLiBUaGlzIHRyZW5kIHN1Z2dlc3RzIGEgcmljaGVyIGRpYWxvZ3VlIGFuZCBtb3JlIG51bWVyb3VzIG11c2ljYWwgc2VxdWVuY2VzIGluIHRoZSBhbmltYXRlZCBjbGFzc2ljLgoKLSAqKkFkYXB0YXRpb24gYW5kIElubm92YXRpb24qKjogVGhlIDIwMTkgcmVuZGl0aW9uIG9mICpBbGFkZGluKiBkaXZlcmdlcyBzdWJ0bHkgZnJvbSBpdHMgcHJlZGVjZXNzb3IsIG5vdCBvbmx5IGJ5IGNvbmRlbnNpbmcgdGhlIHNjcmlwdCBidXQgYWxzbyBieSBpbnRyb2R1Y2luZyBuZXcgZGlhbG9ndWVzIGFuZCBzb25ncyBhYnNlbnQgaW4gdGhlIG9yaWdpbmFsLiBUaGlzIHZhcmlhdGlvbiBpbmRpY2F0ZXMgYW4gZWZmb3J0IHRvIG1vZGVybml6ZSB0aGUgc3Rvcnkgd2hpbGUgbWFpbnRhaW5pbmcgaXRzIGNvcmUgZXNzZW5jZS4KCi0gKipLZXkgQ2hhcmFjdGVycyoqOiBUaGUgbmFtZXMgIkFsYWRkaW4iIGFuZCAiQWJ1IiBhcmUgYW1vbmdzdCB0aGUgbW9zdCByZXBlYXRlZCwgdW5kZXJzY29yaW5nIHRoZWlyIGNlbnRyYWwgcm9sZSBpbiB0aGUgbmFycmF0aXZlLiBUaGVpciBwcm9taW5lbmNlIGFjcm9zcyBib3RoIHZlcnNpb25zIGhpZ2hsaWdodHMgdGhlaXIgc2lnbmlmaWNhbmNlIGFzIHRoZSBtYWluIHByb3RhZ29uaXN0IGFuZCBoaXMgY29tcGFuaW9uLCByZXNwZWN0aXZlbHkuCgotICoqQ2hhcmFjdGVyIEFzc29jaWF0aW9ucyoqOiBUaGUgY2hhcmFjdGVyICJHZW5pZSIgaXMgbm90YWJseSBsaW5rZWQgd2l0aCAiY2FycGV0LCIgcmVmbGVjdGluZyB0aGVpciBpbnRlcmFjdGlvbnMgd2l0aGluIHRoZSBuYXJyYXRpdmUuIFRoZSBhc3NvY2lhdGlvbiBhbmFseXNpcyBhbHNvIGNvbm5lY3RzIEdlbmllIHdpdGggdGVybXMgbGlrZSAiYWZyYWlkIiBhbmQgImFsb25nLCIgbGlrZWx5IGVtZXJnaW5nIGZyb20gZGlhbG9ndWVzIGludm9sdmluZyBBbGFkZGluIG9yIEFidSwgcG9pbnRpbmcgdG8gdGhlIGRlcHRoIG9mIHRoZWlyIHJlbGF0aW9uc2hpcHMuCgotICoqU2VudGltZW50IEFuYWx5c2lzKio6IERlc3BpdGUgZGlmZmVyaW5nIGxlbmd0aHMsIGJvdGggc2NyaXB0cyBzaG93IGEgc2ltaWxhciBzZW50aW1lbnQgdHJhamVjdG9yeSwgcGVha2luZyB3aXRoIHBvc2l0aXZlIGVtb3Rpb25zIHRvd2FyZHMgdGhlIGNsaW1heC4gTm90YWJseSwgdGhlIDIwMTkgc2NyaXB0IGV4aGliaXRzIGZld2VyIG5lZ2F0aXZlIHNlbnRpbWVudHMgY29tcGFyZWQgdG8gdGhlIDE5OTIgdmVyc2lvbiwgd2hpY2ggZW1waGFzaXplZCBzdWNoIGVtb3Rpb25zIGVhcmx5IG9uLiBUaGlzIHNoaWZ0IHN1Z2dlc3RzIGEgbW9kZXJuIGFkYXB0YXRpb24ncyBwcmVmZXJlbmNlIGZvciBncmFkdWFsbHkgYnVpbGRpbmcgcG9zaXRpdmUgbW9tZW50cywgaWxsdXN0cmF0aW5nIGEgbnVhbmNlZCBjaGFuZ2UgaW4gc3Rvcnl0ZWxsaW5nIGFwcHJvYWNoLgoKLSAqKkVtb3Rpb25hbCBEeW5hbWljcyoqOiBUaGUgb3ZlcmFsbCBiYWxhbmNlIG9mIGVtb3Rpb25zIGJldHdlZW4gdGhlIHR3byB2ZXJzaW9ucyByZW1haW5zIHJlbWFya2FibHkgY29uc2lzdGVudCwgaW5kaWNhdGluZyB0aGF0IHRoZSBmdW5kYW1lbnRhbCB0b25lIG9mIHRoZSBzdG9yeSBoYXMgYmVlbiBwcmVzZXJ2ZWQgYWNyb3NzIGFkYXB0YXRpb25zLgoKIyMgQW5hbHlzaXMgU2NvcGUKCiMjIyBXaGF0IFdpbGwgQmUgQW5hbHl6ZWQ/CgoqKkluY2x1c2lvbiBDcml0ZXJpYSoqOgotIEFsbCBvZiB0aGUgdGV4dCBpbiB0aGUgc2NyaXB0LCBpbmNsdWRpbmcgY2hhcmFjdGVycywgbm90ZXMsIHNvbmdzLCBldGMuCi0gVGl0bGUgYW5kIG9yIHN1YnRpdGxlcyBpbmNsdWRlZCBhcmUgYWxzbyBiZWluZyBhbmFseXplLgoKKipFeGNsdXNpb24gQ3JpdGVyaWEqKjoKLSBTdG9wIHdvcmRzLCBwdW5jdHVhdGlvbiBhbmQgY2FwaXRhbCBsZXR0ZXJzIGFyZSBiZWluZyB0cmFuc2Zvcm1lZCBvciBlbGltaW5hdGVkLgoKIyMjIFdoeSBvciBXaHkgTm90PwoKVGhlIGVsaW1pbmF0aW9uIG9mIHB1bmN0dWF0aW9uLCBzdG9wIHdvcmRzIGFuZCBjYXBpdGFsIGxldHRlciBkbyBub3Qgc2VhcmNoIHRvIGJpYXMgdGhlIGFuYWx5c2lzIGJ1dCBpbiB0aGUgY29udHJhcnkgbWFrZSBpdCBlYXNpZXIgYW5kIHByZXZlbnQgZXhjZWVkaW5nIGZyb20gdGhlIG5lY2Vzc2FyeSBkYXRhIGZyb20gd2hpY2ggaW1wb3J0YW50IGluc2lnaHRzIGNhbiBiZSBvYnRhaW5lZC4gCgo=