1 Introduction and Background

Here we have a dataset originally composed of over 5,000 songs that were available on the music-streaming service Spotify over the course of 2024. These tracks stem from a wide array of vastly different genres and styles of creation. The dataset is publicly available on the platform Kaggle and is provided in the References section below. Although the data originally contained 29 variables, only 11 play a particularly relevant role in the analysis I wish to do here. A breakdown of those variables, their meanings and data types is below:

Name Meaning Data_Type
track_popularity song’s rating on the 0 - 100 metric double
popular how popular the track is (more on that later) character
track_name name of the song character
track_artist artist’s stage name character
playlist_genre genre that Spotify classifies the song in character
playlist_genre subgenre that Spotify classifies the song in character
tempo the speed of a track, measured in beats per minute (BPM) double
danceability A score describing how suitable a track is for dancing based on tempo, rhythm stability, beat strength and overall regularity (0 to 1 scale) double
speechiness the presence of audible words (0 to 1 scale) double
instrumentalness likelihood that the track contains instrumentals (0 to 1 scale) double
duration_mins length of track in minutes double

Many of the other variables in the dataset I chose to disregard as they either pertained to unnecessary technical information (such as the algorithmic identifier for the particular song or its album), or extremely niche musical topics that the average listener or introductory critic would most likely not pick up on (such as mode and key).

1.1 Objective for my Analysis

Using this dataset, I wish to quantifiably examine what musical qualities and characteristics lead to a song (or “track”) becoming extremely successful (hence popular) via Spotify. As of October of 2025, Spotify has a market cap of over 139 billion dollars and close to 700 million users. This means that for any aspiring musician, “making it big” on Spotify would serve as a monumental and life-altering milestone.

Spotify has a metric known as the popularity index which serves to numerically represent the popularity of tracks on its platform. While the exact formula behind the score is kept confidential, critics in the music industry and those with strong technical backgrounds have theorized that the primary factors which influence a track’s score are the following; its total number of streams, its recent number of streams, its number of downloads and saves, and its month-to-month growth in all three of said metrics.

This popularity index operates on a scale ranging from 0 to 100, with only the most well-established stars reaching the 90th percentile and higher. That being said, any track with a rating of 75 or higher is largely considered a “top track” by industry experts, so that is the interpretation I will apply with my analysis. I created a categorical binary variable “popular”, which is valued as “yes” for tracks with a popularity index rating of 75 or higher, and “no” for tracks with a lower rating. I will perform logistic regression to assess which, if any, of the factors mentioned in my variable breakdown above contribute to a track being deemed popular or not.

2 Simple Logistic Regression Model

2.1 Checking for Pairwise Relationships

Before jumping into model creation, I created a correlation matrix for the quantitative predictor variables I am going to use in my analysis. This is because variables with very high correlations (r >= 0.8) often can function as almost multiples of one another, leading to inaccurate conclusions, especially when performing multiple regression.

cor_matrix = cor(Quantitative_Variables)
  # No high correlations between the variables

kable(cor_matrix, caption = "Correlation Matrix")
Correlation Matrix
tempo danceability speechiness instrumentalness duration_mins
tempo 1.0000000 0.0338179 0.0576956 -0.1518469 0.0397516
danceability 0.0338179 1.0000000 0.2840300 -0.3205070 -0.1374377
speechiness 0.0576956 0.2840300 1.0000000 -0.1903130 -0.1050720
instrumentalness -0.1518469 -0.3205070 -0.1903130 1.0000000 -0.2218689
duration_mins 0.0397516 -0.1374377 -0.1050720 -0.2218689 1.0000000

After creating a correlation matrix, we can see that none of the quantitative predictor variables that we are examining have a high correlation with one another. Practically speaking, this is not very surprising as even “similar” songs by the same artist or within the same genre can have wildly different characteristics when it comes to tempo or anything else we are looking at.

2.2 Picking Variable for Simple Model

Below I created histograms to represent the distributions of all five quantitative variables I am going to use in this analysis. The purpose for doing such is to determine if any sort of variable manipulation (typically log transformation or square root transformation) is necessary before using the variable in our logistic model.

par(mfrow = c(2, 3), mar = c(4, 4, 2, 1))  # mar controls margins 
  
  
ylimit = max(density(Work_Data$tempo)$y)
hist(Work_Data$tempo, probability = TRUE, main = "Tempo Distribution", xlab="Tempo", 
       col = "azure1", border="lightseagreen")
  lines(density(Work_Data$tempo, adjust=2), col="blue") 

ylimit = max(density(Work_Data$danceability)$y)
hist(Work_Data$danceability, probability = TRUE, main = "Danceability Distribution", xlab="Danceability", 
       col = "azure1", border="lightseagreen")
  lines(density(Work_Data$danceability, adjust=2), col="blue") 
  
ylimit = max(density(Work_Data$speechiness)$y)
hist(Work_Data$speechiness, probability = TRUE, main = "Speechiness Distribution", xlab="Speechiness", 
       col = "azure1", border="lightseagreen")
  lines(density(Work_Data$speechiness, adjust=2), col="blue") 
  
  
ylimit = max(density(Work_Data$instrumentalness)$y)
hist(Work_Data$instrumentalness, probability = TRUE, main = "Instrumentalness Distribution", xlab="Instrumentalness", 
       col = "azure1", border="lightseagreen")
  lines(density(Work_Data$instrumentalness, adjust=2), col="blue") 
  
  
ylimit = max(density(Work_Data$duration_mins)$y)
hist(Work_Data$duration_mins, probability = TRUE, main = "Length (mins) Distribution", xlab="Length (mins)", 
       col = "azure1", border="lightseagreen")
  lines(density(Work_Data$duration_mins, adjust=2), col="blue") 

We can see from the histograms that there is an extreme skew in speechiness, instrumentalness and length. While there are slight skews in tempo and danceability, they are far more moderate. Since tempo appears to be the least skewed of the variables, and it’s calculation is the most straightforward (a simple measure of beats per minute), I will use tempo to perform my simple logistic regression.

2.3 Creating the Model

Using built-in R functions, I created a simple binary logistic regression model, in which the tempo of a song is meant to predict whether or not that track is popular or not (popularity score of 75 or not). In the calculations, the base level, or 0, was stored for instances of a track’s popularity being marked as “no”. While the instance level, or 1, was stored for instances of a track’s popularity being marked as “yes”.

Log_Model = glm(formula = popular ~ tempo, family = binomial(link = "logit"), 
    data = Work_Data)

invisible(summary(Log_Model))

Log_Model_Coef_Summary = summary(Log_Model)$coef       # output stats of coefficients
Confidence_Interval = confint(Log_Model)                     # confidence intervals of betas
Summary_Stats = cbind(Log_Model_Coef_Summary, Confidence_Interval.95=Confidence_Interval)   # rounding off decimals
kable(Summary_Stats,caption = "Simple Logistic Regression Model Summary")  
Simple Logistic Regression Model Summary
Estimate Std. Error z value Pr(>|z|) 2.5 % 97.5 %
(Intercept) -2.2643674 0.2126810 -10.646777 0.000000 -2.6844577 -1.8504312
tempo 0.0060146 0.0017127 3.511866 0.000445 0.0026561 0.0093727

The summary of our model above leads us to believe that a track’s tempo does have a positive association with the likelihood that a track is popular on Spotify, however that association is very small in practical effect. Despite a statistically significant p value, \(\beta\)1 has an estimated association with the probability of a track being deemend popular of .006, and a 95% confidence interval deeming the association to fall between the interval [.003, .009].

2.4 Odds Ratio Summary

While the direct interpretation of a logistic regression model’s summary statistics can be helpful, it is sometimes more practical to examine our model’s odds ratio. An odds ratio represents the likelihood of success divided by the likelihood of failure. For example, an odds ratio of 2 would mean that whatever instance we are considering a “success” occurs twice the number of times than it fails to occur.

# Odds ratio
Log_Model_Coef_Summary = summary(Log_Model)$coef
Odds_Ratio = exp(coef(Log_Model))
out.stats = cbind(Log_Model_Coef_Summary, odds.ratio = Odds_Ratio)                 
kable(out.stats,caption = "Regression Model Coefficients W/ Odds Ratios")
Regression Model Coefficients W/ Odds Ratios
Estimate Std. Error z value Pr(>|z|) odds.ratio
(Intercept) -2.2643674 0.2126810 -10.646777 0.000000 0.1038957
tempo 0.0060146 0.0017127 3.511866 0.000445 1.0060327

The odds ratio between a track’s tempo and it’s popularity status is ~ 1.006. Since tempo is measured in beats per minute (BPM), this means that for every additional beat per minute that a song is recorded in, it’s probability of having a popularity score above 75 increases by about 0.6%.

2.5 Goodness-of-fit measures

Below I calculated the goodness-of-fit (GOF) measures for the logistic regression model. Generally speaking, it is beneficial to find a model’s GOF features as they serve as relative comparisons of model efficiency when comparing multiple models. In this instance, we only created one model so far, so the measures are not of practical use at the moment.

Residual_Deviance = Log_Model$deviance
Null_Residual_Deviance = Log_Model$null.deviance
aic = Log_Model$aic
Goodness_Of_Fit = cbind(Deviance.residual = Residual_Deviance, Null.Deviance.Residual = Null_Residual_Deviance,
      AIC = aic)
pander(Goodness_Of_Fit)
Deviance.residual Null.Deviance.Residual AIC
2451 2464 2455

2.6 Success Probability Curve

Below I created a visual of the the model’s S curve (also called success probability curve or logistic curve). The S curve helps us see the change in probability of an event happening (a track being popular or not on Spotify), in relation to a change in the value of a predictor variable (tempo in BPM in this instance).

###

tempo_range = range(Work_Data$tempo)
x = seq(tempo_range[1], tempo_range[2], length = 200)
beta.x = coef(Log_Model)[1] + coef(Log_Model)[2]*x
success.prob = exp(beta.x)/(1+exp(beta.x))
failure.prob = 1/(1+exp(beta.x))
ylimit = max(success.prob, failure.prob)
##
beta1 = coef(Log_Model)[2]
success.prob.rate = beta1*exp(beta.x)/(1+exp(beta.x))^2
##
##
par(mfrow = c(1,1))
plot(x, success.prob, type = "l", lwd = 2, col = "black",
     main = "The Probability of a Track Being \n Considered Popular on Spotify", 
     ylim=c(0, 1.1*ylimit),
     xlab = "Tempo (BPM)",
     ylab = "probability",
     axes = FALSE,
     col.main = "black",
     cex.main = 1.1)
# lines(x, failure.prob,lwd = 2, col = "darkred")
axis(1, pos = 0)
axis(2)

##
y.rate = max(success.prob.rate)
plot(x, success.prob.rate, type = "l", lwd = 2, col = "black",
     main = "The Rate of Change in Probability of a Track Being \n Considered Popular on Spotify", 
     xlab = "Tempo (BPM)",
     ylab = "Rate of Change",
     ylim=c(0,1.1*y.rate),
     axes = FALSE,
     col.main = "black",
     cex.main = 1.1
     )
axis(1, pos = 0)
axis(2)

The S Curve provides visual confirmation of the conclusions we were able to draw from analyzing our coefficient summary, confidence intervals and odds ratio. That is, that there is a positive association between a track’s tempo and it’s likelihood of being a popular track on Spotify, but that association is very minimal in practical effect.

We can see from our second plot, that looked at the relationship between the rate of change in said probability and a track’s tempo, that from 50 to 200 beats per minute, the probability of a track being popular’s positive rate of change only increases from 0.0006 to 0.0012.

3 Conclusion

To conclude, we can say that although there is a statistically significant and positive relationship between a track’s tempo and the probability that it is popular on Spotify, that association is of such a small magnitude that it is relatively a non-factor in practical sense. Therefore, it would be overly simplistic and hyperbolic for music labels or agents to aggressively push their artists towards a more up-tempo production, as the return on such a decision would likely not be worth the cost of souring the relationship with the artist at hand.

LS0tCnRpdGxlOiAiVGhlIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIGEgU29uZydzIFRlbXBvIGFuZCBpdHMgUHJvYmFiaWxpdHkgb2YgYmVpbmcgUG9wdWxhciBvbiBTcG90aWZ5IgphdXRob3I6ICJDaHJpcyBCYWhtIgpkYXRlOiAiMjAyNS0xMC0wNyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgZmlnX3dpZHRoOiA2CiAgICBmaWdfaGVpZ2h0OiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGNhcikpIHtsaWJyYXJ5KGNhcil9IAoKaWYgKCFyZXF1aXJlKCJzY2FsZXMiKSkgewppbnN0YWxsLnBhY2thZ2VzKCJzY2FsZXMiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKbGlicmFyeSgic2NhbGVzIikgCn0KCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFLAoJY29tbWVudCA9IE5BLAoJcmVzdWx0cyA9IFRSVUUKKQogICAKYGBgCgojIEludHJvZHVjdGlvbiBhbmQgQmFja2dyb3VuZAoKSGVyZSB3ZSBoYXZlIGEgZGF0YXNldCBvcmlnaW5hbGx5IGNvbXBvc2VkIG9mIG92ZXIgNSwwMDAgc29uZ3MgdGhhdCB3ZXJlIGF2YWlsYWJsZSBvbiB0aGUgbXVzaWMtc3RyZWFtaW5nIHNlcnZpY2UgU3BvdGlmeSBvdmVyIHRoZSBjb3Vyc2Ugb2YgMjAyNC4gVGhlc2UgdHJhY2tzIHN0ZW0gZnJvbSBhIHdpZGUgYXJyYXkgb2YgdmFzdGx5IGRpZmZlcmVudCBnZW5yZXMgYW5kIHN0eWxlcyBvZiBjcmVhdGlvbi4gVGhlIGRhdGFzZXQgaXMgcHVibGljbHkgYXZhaWxhYmxlIG9uIHRoZSBwbGF0Zm9ybSBLYWdnbGUgYW5kIGlzIHByb3ZpZGVkIGluIHRoZSBSZWZlcmVuY2VzIHNlY3Rpb24gYmVsb3cuIEFsdGhvdWdoIHRoZSBkYXRhIG9yaWdpbmFsbHkgY29udGFpbmVkIDI5IHZhcmlhYmxlcywgb25seSAxMSBwbGF5IGEgcGFydGljdWxhcmx5IHJlbGV2YW50IHJvbGUgaW4gdGhlIGFuYWx5c2lzIEkgd2lzaCB0byBkbyBoZXJlLiBBIGJyZWFrZG93biBvZiB0aG9zZSB2YXJpYWJsZXMsIHRoZWlyIG1lYW5pbmdzIGFuZCBkYXRhIHR5cGVzIGlzIGJlbG93OgoKYGBge3IgVmFyaWFibGUgVGFibGUsIGVjaG89RkFMU0V9CmxpYnJhcnkoa25pdHIpCgpWYXJfVGFibGUgPSBkYXRhLmZyYW1lKAogIE5hbWUgPSBjKCJ0cmFja19wb3B1bGFyaXR5IiwgInBvcHVsYXIiLCAidHJhY2tfbmFtZSIsICJ0cmFja19hcnRpc3QiLCAicGxheWxpc3RfZ2VucmUiLCAicGxheWxpc3RfZ2VucmUiLCAidGVtcG8iLCAiZGFuY2VhYmlsaXR5Iiwic3BlZWNoaW5lc3MiLCAiaW5zdHJ1bWVudGFsbmVzcyIsICJkdXJhdGlvbl9taW5zIiksCiAgCiAgTWVhbmluZyA9IGMoInNvbmcncyByYXRpbmcgb24gdGhlIDAgLSAxMDAgbWV0cmljIiwgImhvdyBwb3B1bGFyIHRoZSB0cmFjayBpcyAobW9yZSBvbiB0aGF0IGxhdGVyKSIsCiAgICAgICAgICAgICAgIm5hbWUgb2YgdGhlIHNvbmciLAogICAgICAgICAgICAgICJhcnRpc3QncyBzdGFnZSBuYW1lIiwgCiAgICAgICAgICAgICAgImdlbnJlIHRoYXQgU3BvdGlmeSBjbGFzc2lmaWVzIHRoZSBzb25nIGluIiwgCiAgICAgICAgICAgICAgInN1YmdlbnJlIHRoYXQgU3BvdGlmeSBjbGFzc2lmaWVzIHRoZSBzb25nIGluIiwgIAogICAgICAgICAgICAgICJ0aGUgc3BlZWQgb2YgYSB0cmFjaywgbWVhc3VyZWQgaW4gYmVhdHMgcGVyIG1pbnV0ZSAoQlBNKSIsIAogICAgICAgICAgICAgICJBIHNjb3JlIGRlc2NyaWJpbmcgaG93IHN1aXRhYmxlIGEgdHJhY2sgaXMgZm9yIGRhbmNpbmcgYmFzZWQgb24gdGVtcG8sIHJoeXRobSBzdGFiaWxpdHksIGJlYXQgc3RyZW5ndGggYW5kIG92ZXJhbGwgcmVndWxhcml0eSAoMCB0byAxIHNjYWxlKSIsIAogICAgICAgICAgICAgICJ0aGUgcHJlc2VuY2Ugb2YgYXVkaWJsZSB3b3JkcyAoMCB0byAxIHNjYWxlKSIsIAogICAgICAgICAgICAgICJsaWtlbGlob29kIHRoYXQgdGhlIHRyYWNrIGNvbnRhaW5zIGluc3RydW1lbnRhbHMgKDAgdG8gMSBzY2FsZSkgIiwgCiAgICAgICAgICAgICAgImxlbmd0aCBvZiB0cmFjayBpbiBtaW51dGVzIiksCiAgCiAgRGF0YV9UeXBlID0gYygiZG91YmxlIiwgImNoYXJhY3RlciIsICJjaGFyYWN0ZXIiLCAiY2hhcmFjdGVyIiwgImNoYXJhY3RlciIsICJjaGFyYWN0ZXIiLCAiZG91YmxlIiwgImRvdWJsZSIsICJkb3VibGUiLCAiZG91YmxlIiwgImRvdWJsZSIpCikKCmthYmxlKFZhcl9UYWJsZSkgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIikKYGBgCgpNYW55IG9mIHRoZSBvdGhlciB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQgSSBjaG9zZSB0byBkaXNyZWdhcmQgYXMgdGhleSBlaXRoZXIgcGVydGFpbmVkIHRvIHVubmVjZXNzYXJ5IHRlY2huaWNhbCBpbmZvcm1hdGlvbiAoc3VjaCBhcyB0aGUgYWxnb3JpdGhtaWMgaWRlbnRpZmllciBmb3IgdGhlIHBhcnRpY3VsYXIgc29uZyBvciBpdHMgYWxidW0pLCBvciBleHRyZW1lbHkgbmljaGUgbXVzaWNhbCB0b3BpY3MgdGhhdCB0aGUgYXZlcmFnZSBsaXN0ZW5lciBvciBpbnRyb2R1Y3RvcnkgY3JpdGljIHdvdWxkIG1vc3QgbGlrZWx5IG5vdCBwaWNrIHVwIG9uIChzdWNoIGFzIG1vZGUgYW5kIGtleSkuCgojIyBPYmplY3RpdmUgZm9yIG15IEFuYWx5c2lzClVzaW5nIHRoaXMgZGF0YXNldCwgSSB3aXNoIHRvIHF1YW50aWZpYWJseSBleGFtaW5lIHdoYXQgbXVzaWNhbCBxdWFsaXRpZXMgYW5kIGNoYXJhY3RlcmlzdGljcyBsZWFkIHRvIGEgc29uZyAob3IgInRyYWNrIikgYmVjb21pbmcgZXh0cmVtZWx5IHN1Y2Nlc3NmdWwgKGhlbmNlIHBvcHVsYXIpIHZpYSBTcG90aWZ5LiBBcyBvZiBPY3RvYmVyIG9mIDIwMjUsIFNwb3RpZnkgaGFzIGEgbWFya2V0IGNhcCBvZiBvdmVyIDEzOSBiaWxsaW9uIGRvbGxhcnMgYW5kIGNsb3NlIHRvIDcwMCBtaWxsaW9uIHVzZXJzLiBUaGlzIG1lYW5zIHRoYXQgZm9yIGFueSBhc3BpcmluZyBtdXNpY2lhbiwgIm1ha2luZyBpdCBiaWciIG9uIFNwb3RpZnkgd291bGQgc2VydmUgYXMgYSBtb251bWVudGFsIGFuZCBsaWZlLWFsdGVyaW5nIG1pbGVzdG9uZS4gCgpTcG90aWZ5IGhhcyBhIG1ldHJpYyBrbm93biBhcyB0aGUgcG9wdWxhcml0eSBpbmRleCB3aGljaCBzZXJ2ZXMgdG8gbnVtZXJpY2FsbHkgcmVwcmVzZW50IHRoZSBwb3B1bGFyaXR5IG9mIHRyYWNrcyBvbiBpdHMgcGxhdGZvcm0uIFdoaWxlIHRoZSBleGFjdCBmb3JtdWxhIGJlaGluZCB0aGUgc2NvcmUgaXMga2VwdCBjb25maWRlbnRpYWwsIGNyaXRpY3MgaW4gdGhlIG11c2ljIGluZHVzdHJ5IGFuZCB0aG9zZSB3aXRoIHN0cm9uZyB0ZWNobmljYWwgYmFja2dyb3VuZHMgaGF2ZSB0aGVvcml6ZWQgdGhhdCB0aGUgcHJpbWFyeSBmYWN0b3JzIHdoaWNoIGluZmx1ZW5jZSBhIHRyYWNrJ3Mgc2NvcmUgYXJlIHRoZSBmb2xsb3dpbmc7IGl0cyB0b3RhbCBudW1iZXIgb2Ygc3RyZWFtcywgaXRzIHJlY2VudCBudW1iZXIgb2Ygc3RyZWFtcywgaXRzIG51bWJlciBvZiBkb3dubG9hZHMgYW5kIHNhdmVzLCBhbmQgaXRzIG1vbnRoLXRvLW1vbnRoIGdyb3d0aCBpbiBhbGwgdGhyZWUgb2Ygc2FpZCBtZXRyaWNzLgoKVGhpcyBwb3B1bGFyaXR5IGluZGV4IG9wZXJhdGVzIG9uIGEgc2NhbGUgcmFuZ2luZyBmcm9tIDAgdG8gMTAwLCB3aXRoIG9ubHkgdGhlIG1vc3Qgd2VsbC1lc3RhYmxpc2hlZCBzdGFycyByZWFjaGluZyB0aGUgOTB0aCBwZXJjZW50aWxlIGFuZCBoaWdoZXIuIFRoYXQgYmVpbmcgc2FpZCwgYW55IHRyYWNrIHdpdGggYSByYXRpbmcgb2YgNzUgb3IgaGlnaGVyIGlzIGxhcmdlbHkgY29uc2lkZXJlZCBhICJ0b3AgdHJhY2siIGJ5IGluZHVzdHJ5IGV4cGVydHMsIHNvIHRoYXQgaXMgdGhlIGludGVycHJldGF0aW9uIEkgd2lsbCBhcHBseSB3aXRoIG15IGFuYWx5c2lzLiBJIGNyZWF0ZWQgYSBjYXRlZ29yaWNhbCBiaW5hcnkgdmFyaWFibGUgInBvcHVsYXIiLCB3aGljaCBpcyB2YWx1ZWQgYXMgInllcyIgZm9yIHRyYWNrcyB3aXRoIGEgcG9wdWxhcml0eSBpbmRleCByYXRpbmcgb2YgNzUgb3IgaGlnaGVyLCBhbmQgIm5vIiBmb3IgdHJhY2tzIHdpdGggYSBsb3dlciByYXRpbmcuIEkgd2lsbCBwZXJmb3JtIGxvZ2lzdGljIHJlZ3Jlc3Npb24gdG8gYXNzZXNzIHdoaWNoLCBpZiBhbnksIG9mIHRoZSBmYWN0b3JzIG1lbnRpb25lZCBpbiBteSB2YXJpYWJsZSBicmVha2Rvd24gYWJvdmUgY29udHJpYnV0ZSB0byBhIHRyYWNrIGJlaW5nIGRlZW1lZCBwb3B1bGFyIG9yIG5vdC4KCmBgYHtyIERhdGEgUmVhZCBpbiBhbmQgQ2xlYW5pbmcsIGluY2x1ZGU9RkFMU0V9Cm9wdGlvbnMoc2NpcGVuID0gOTk5KSAjIE91dCBvZiBzY2llbnRpZmljIG5vdGF0aW9uLCBwZXJzb25hbCBwcmVmZXJlbmNlCgpEYXRhX1VybF9BID0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DaHJpc0IyMzIzL1NUQTMyMS9yZWZzL2hlYWRzL21haW4vaGlnaF9wb3B1bGFyaXR5X3Nwb3RpZnlfZGF0YS5jc3YiCkFib3ZlXzY4ID0gcmVhZF9kZWxpbShEYXRhX1VybF9BLCBkZWxpbSA9ICIsIiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkKCkRhdGFfVXJsX0IgPSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0NocmlzQjIzMjMvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9sb3dfcG9wdWxhcml0eV9zcG90aWZ5X2RhdGEuY3N2IgpCZWxvd182OCA9IHJlYWRfZGVsaW0oRGF0YV9VcmxfQiwgZGVsaW0gPSAiLCIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCgoKIyMjIExpbmUgYmVsb3cgd2FzIHVzZWQgZm9yIGluaXRpYWwgdmlzdWFsIHB1cnBvc2VzIAojQWJvdmVfNjggPSBBYm92ZV82OFssIGMoInRyYWNrX25hbWUiLCAidHJhY2tfYWxidW1fbmFtZSIsICJ0cmFja19hcnRpc3QiLCAicGxheWxpc3RfbmFtZSIsICJwbGF5bGlzdF9nZW5yZSIsICJwbGF5bGlzdF9zdWJnZW5yZSIsICJ0cmFja19wb3B1bGFyaXR5IiwgImVuZXJneSIsICJ0ZW1wbyIsICJkYW5jZWFiaWxpdHkiLCAibG91ZG5lc3MiLCAibGl2ZW5lc3MiLCAidmFsZW5jZSIsICJzcGVlY2hpbmVzcyIsICJpbnN0cnVtZW50YWxuZXNzIiwgImtleSIsICJkdXJhdGlvbl9tcyIsICJ0aW1lX3NpZ25hdHVyZSIsICJ0cmFja19ocmVmIiwgIm1vZGUiLCAidXJpIiwgInR5cGUiLCAidHJhY2tfYWxidW1fcmVsZWFzZV9kYXRlIiwgImFuYWx5c2lzX3VybCIsICJpZCIsICJ0cmFja19hbGJ1bV9pZCIsICJwbGF5bGlzdF9pZCIsICJ0cmFja19pZCIsICJhY291c3RpY25lc3MiKV0KCgpEYXRhID0gcmJpbmQoQWJvdmVfNjgsIEJlbG93XzY4KQogIERhdGEkZHVyYXRpb25fbWlucyA9IERhdGEkZHVyYXRpb25fbXMvNjAwMDAKRGF0YSRwb3B1bGFyID0gaWZlbHNlKERhdGEkdHJhY2tfcG9wdWxhcml0eSA+IDc1LCAieWVzIiwgIm5vIikKCkRhdGEgPSBzZWxlY3QoRGF0YSwgdHJhY2tfcG9wdWxhcml0eSwgcG9wdWxhciwgdHJhY2tfbmFtZSwgdHJhY2tfYWxidW1fbmFtZSwgdHJhY2tfYXJ0aXN0LCBwbGF5bGlzdF9uYW1lLCBwbGF5bGlzdF9nZW5yZSwgcGxheWxpc3Rfc3ViZ2VucmUsIGVuZXJneSwgdGVtcG8sIGRhbmNlYWJpbGl0eSwgbG91ZG5lc3MsIGxpdmVuZXNzLCB2YWxlbmNlLCBzcGVlY2hpbmVzcywgaW5zdHJ1bWVudGFsbmVzcywga2V5LCBkdXJhdGlvbl9taW5zKQoKdW5pcXVlKERhdGEkcGxheWxpc3RfZ2VucmUpCgojIEJyZWFrZG93biBvZiBWYXJpYWJsZXMgS2VwdAogICAjIElkZW50aWZ5aW5nIFZhcmlhYmxlczoKICAgICAgICMgdHJhY2tfbmFtZQogICAgICAgIyB0cmFja19hbGJ1bV9uYW1lCiAgICAgICAjIHRyYWNrX2FydGlzdAogICAjIENhdGVnb3JpY2FsIEluZm86CiAgICAgICAjIHBsYXlsaXN0X25hbWUKICAgICAgICMgcGxheWxpc3RfZ2VucmUKICAgICAgICMgcGxheWxpc3Rfc3ViZ2VucmUKICAgICAgICMgKioqKiBwb3B1bGFyICoqKiogYmluYXJ5IHJlc3BvbnNlIHZhcmlhYmxlIHNlbGYtY3JlYXRlZAogICAjIFF1YW50aXRhdGl2ZSBJbmZvOgogICAgICAgIyB0cmFja19wb3B1bGFyaXR5CiAgICAgICAjIGVuZXJneQogICAgICAgIyB0ZW1wbwogICAgICAgIyBkYW5jZWFiaWxpdHkKICAgICAgICMgbG91ZG5lc3MKICAgICAgICMgbGl2ZW5lc3MKICAgICAgICMgdmFsZW5jZQogICAgICAgIyBzcGVlY2hpbmVzcwogICAgICAgIyBpbnN0cnVtZW50YWxuZXNzCiAgICAgICAjIGtleQogICAgICAgIyBkdXJhdGlvbl9tcwogICAKICAgICMgMTcgc2VsZWN0ZWQgYWJvdmUgZnJvbSBvcmlnaW5hbCBkYXRhIHNldCwgcGx1cyBwb3B1bGFyCiAgIAogICMgVmFyaWFibGVzIHdlIGFyZSBub3QgaW5jbHVkaW5nIGluIHJlZHVjZWQgZGF0YSBzZXQgYXJlIGxhcmdlbHkgdGVjaG5pY2FsIHRyYWNraW5nIHZhcmlhYmxlcyBzdWNoIGFzIGlkIGFuZCBhbmFseXNpc191cmwsIG9yIHZlcnkgbmljaGUgbXVzaWNhbCBtZXRyaWNzIHRoYXQgdGhlIGF2ZXJhZ2UgbGlzdGVuZXIgd291bGQgYmUgdW5hd2FyZSBvZiBzdWNoIGFzIG1vZGUuCgoKIyMjIyBDaGVja2luZyBmb3IgRHVwbGljYXRlczoKCkR1cGxpY2F0ZV9Tb25ncyA9IERhdGFbZHVwbGljYXRlZChEYXRhJHRyYWNrX25hbWUpIHwgZHVwbGljYXRlZChEYXRhJHRyYWNrX25hbWUsIGZyb21MYXN0ID0gVFJVRSksIF0KRHVwbGljYXRlX1NvbmdzX1JlZHVjZWQgPSBzZWxlY3QoRHVwbGljYXRlX1NvbmdzLCB0cmFja19uYW1lLCB0cmFja19hcnRpc3QsIHBsYXlsaXN0X25hbWUsIHBsYXlsaXN0X2dlbnJlLCBwbGF5bGlzdF9zdWJnZW5yZSkKCkR1cGxpY2F0ZV9Tb25nX0NvdW50cyA9IGFzLmRhdGEuZnJhbWUodGFibGUoRHVwbGljYXRlX1NvbmdzJHRyYWNrX25hbWUpKSAgIAogICMgODM3IGluc3RhbmNlcyBvZiB0aGUgc2FtZSBzb25nIGJlaW5nIGxpc3RlZCBtb3JlIHRoYW4gb25jZQoKbmFtZXMoRHVwbGljYXRlX1NvbmdfQ291bnRzKSA9IGMoInRyYWNrX25hbWUiLCAiY291bnQiKQogICMgMzc4IHNvbmdzIGxpc3RlZCBtb3JlIHRoYW4gb25jZQoKc3VtKER1cGxpY2F0ZV9Tb25nX0NvdW50cyRjb3VudCkgICAjIFN1bSBmdW5jdGlvbiBjb25maXJtcyB0aGVyZSBhcmUgODM3IHRvdGFsIHJlcGVhdHMKCiAgCiMgR29pbmcgdG8gcmVkdWNlIG1haW4gZGF0YXNldCB0byBvbmx5IG9uZSBvYnNlcnZhdGlvbiBwZXIgc29uZywgdXNlZCBiYXNlIFIgZnVuY3Rpb24gdG8ga2VlcCBmaXJzdCBvY2N1cmVuY2Ugb2YgZWFjaCBzb25nCgojIyMjIE5ld19EYXRhID0gbm8gZHVwbGljYXRlcwpOZXdfRGF0YSA9IERhdGFbIWR1cGxpY2F0ZWQoRGF0YSR0cmFja19uYW1lKSwgXQoKIyBHb2luZyB0byBlbGltaW5hdGUgZ2VucmVzIHRoYXQgYXJlIG5vdCBwcmV2YWxlbnQgaW4gTm9ydGggQW1lcmljYSBhbmQgRXVyb3BlLCBhcyBteSBhbmFseXNpcyB3aWxsIGFwcGx5IGxhcmdlbHkgdG8gYXVkaWVuY2UgaW4gV2VzdGVybiB3b3JsZAoKdW5pcXVlKE5ld19EYXRhJHBsYXlsaXN0X2dlbnJlKQoKTmV3X0RhdGEkV2VzdCA9IGlmZWxzZSgKICBOZXdfRGF0YSRwbGF5bGlzdF9nZW5yZSAlaW4lIGMoImJyYXppbGlhbiIsICJhcmFiaWMiLCAiaW5kaWFuIiwgIm1hbmRvcG9wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNhbnRvcG9wIiwgImstcG9wIiwgInR1cmtpc2giLCAia29yZWFuIiwgImotcG9wIiwgIndvcmxkIiwgImxhdGluIiwgImVsZWN0cm9uaWMiKSwKICAibm8iLAogICJ5ZXMiCikKCnRhYmxlKE5ld19EYXRhJFdlc3QpCgojIyMjIE5ld19EYXRhMiA9IENvbmZpbmVkIHRvIFdlc3Rlcm4gbXVzaWMgZ2VucmVzCk5ld19EYXRhMiA9IE5ld19EYXRhW05ld19EYXRhJFdlc3QhPSAibm8iLCBdCmNvbG5hbWVzKE5ld19EYXRhMikKCiMjIyMgV29ya19EYXRhID0gUmVkdWNlZCBudW1iZXIgb2YgdmFyaWFibGVzIHRvIHBlcmZvcm0gYW5hbHlzaXMgb24sIG1pc3NpbmcgdmFsdWUgY2hlY2tzIHBlcmZvcm1lZApXb3JrX0RhdGEgPSBzZWxlY3QoTmV3X0RhdGEyLCB0cmFja19wb3B1bGFyaXR5LCBwb3B1bGFyLCB0cmFja19uYW1lLCB0cmFja19hcnRpc3QsIHBsYXlsaXN0X2dlbnJlLCBwbGF5bGlzdF9zdWJnZW5yZSwgdGVtcG8sIGRhbmNlYWJpbGl0eSwgc3BlZWNoaW5lc3MsIGluc3RydW1lbnRhbG5lc3MsIGR1cmF0aW9uX21pbnMpCgpXb3JrX0RhdGEgPSBzb3J0X2J5KFdvcmtfRGF0YSwgV29ya19EYXRhJHRyYWNrX3BvcHVsYXJpdHksIGRlY3JlYXNpbmc9VFJVRSkKCnN1bShpcy5uYShXb3JrX0RhdGEpKSAjIDUgbWlzc2luZyB2YWx1ZXMgaW4gZGF0YXNldAoKTWlzc2luZ19Sb3dzID0gV29ya19EYXRhWyFjb21wbGV0ZS5jYXNlcyhXb3JrX0RhdGEpLCBdCiAjIEFsbCA1IG1pc3NpbmcgdmFsdWVzIGNvbWUgZnJvbSBvbmUgb2JzZXJ2YXRpb24sIHRoZSBzb25nIGlzICJNYWtlIEl0IiBieSBCZXJoYW5pby4gSSB3aWxsIGp1c3QgcmVtb3ZlIHRoaXMgc29uZyBmcm9tIHRoZSBkYXRhc2V0IHVzaW5nIGZpbHRlciBmdW5jdGlvbiBiZWxvdy4KCldvcmtfRGF0YSA9IGZpbHRlcihXb3JrX0RhdGEsIHRyYWNrX25hbWUgIT0gIk1ha2UgSXQiICkKCiAgdHJhY2tfcG9wdWxhcml0eSA9IFdvcmtfRGF0YSR0cmFja19wb3B1bGFyaXR5IAogIHBvcHVsYXIgPSBXb3JrX0RhdGEkcG9wdWxhcgogIHRyYWNrX25hbWUgPSBXb3JrX0RhdGEkdHJhY2tfbmFtZQogIHRyYWNrX2FydGlzdCA9IFdvcmtfRGF0YSR0cmFja19hcnRpc3QKICBwbGF5bGlzdF9nZW5yZSA9IFdvcmtfRGF0YSRwbGF5bGlzdF9nZW5yZQogIHBsYXlsaXN0X3N1YmdlbnJlID0gV29ya19EYXRhJHBsYXlsaXN0X3N1YmdlbnJlCiAgdGVtcG8gPSBXb3JrX0RhdGEkdGVtcG8KICBkYW5jZWFiaWxpdHkgPSBXb3JrX0RhdGEkZGFuY2VhYmlsaXR5CiAgc3BlZWNoaW5lc3MgPSBXb3JrX0RhdGEkc3BlZWNoaW5lc3MKICBpbnN0cnVtZW50YWxuZXNzID0gV29ya19EYXRhJGluc3RydW1lbnRhbG5lc3MKICBkdXJhdGlvbl9taW5zID0gV29ya19EYXRhJGR1cmF0aW9uX21pbnMKICAKUXVhbnRpdGF0aXZlX1ZhcmlhYmxlcyA9IGNiaW5kKHRlbXBvLCBkYW5jZWFiaWxpdHksIHNwZWVjaGluZXNzLCBpbnN0cnVtZW50YWxuZXNzLCBkdXJhdGlvbl9taW5zKQoKQ2F0ZWdvcmljYWxfVmFyaWFibGVzID0gY2JpbmQocGxheWxpc3RfZ2VucmUsIHBsYXlsaXN0X3N1YmdlbnJlKQogCmBgYAoKIyBTaW1wbGUgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbAoKIyMgQ2hlY2tpbmcgZm9yIFBhaXJ3aXNlIFJlbGF0aW9uc2hpcHMKQmVmb3JlIGp1bXBpbmcgaW50byBtb2RlbCBjcmVhdGlvbiwgSSBjcmVhdGVkIGEgY29ycmVsYXRpb24gbWF0cml4IGZvciB0aGUgcXVhbnRpdGF0aXZlIHByZWRpY3RvciB2YXJpYWJsZXMgSSBhbSBnb2luZyB0byB1c2UgaW4gbXkgYW5hbHlzaXMuIFRoaXMgaXMgYmVjYXVzZSB2YXJpYWJsZXMgd2l0aCB2ZXJ5IGhpZ2ggY29ycmVsYXRpb25zIChyID49IDAuOCkgb2Z0ZW4gY2FuIGZ1bmN0aW9uIGFzIGFsbW9zdCBtdWx0aXBsZXMgb2Ygb25lIGFub3RoZXIsIGxlYWRpbmcgdG8gaW5hY2N1cmF0ZSBjb25jbHVzaW9ucywgZXNwZWNpYWxseSB3aGVuIHBlcmZvcm1pbmcgbXVsdGlwbGUgcmVncmVzc2lvbi4KYGBge3J9CmNvcl9tYXRyaXggPSBjb3IoUXVhbnRpdGF0aXZlX1ZhcmlhYmxlcykKICAjIE5vIGhpZ2ggY29ycmVsYXRpb25zIGJldHdlZW4gdGhlIHZhcmlhYmxlcwoKa2FibGUoY29yX21hdHJpeCwgY2FwdGlvbiA9ICJDb3JyZWxhdGlvbiBNYXRyaXgiKQpgYGAKCkFmdGVyIGNyZWF0aW5nIGEgY29ycmVsYXRpb24gbWF0cml4LCB3ZSBjYW4gc2VlIHRoYXQgbm9uZSBvZiB0aGUgcXVhbnRpdGF0aXZlIHByZWRpY3RvciB2YXJpYWJsZXMgdGhhdCB3ZSBhcmUgZXhhbWluaW5nIGhhdmUgYSBoaWdoIGNvcnJlbGF0aW9uIHdpdGggb25lIGFub3RoZXIuIFByYWN0aWNhbGx5IHNwZWFraW5nLCB0aGlzIGlzIG5vdCB2ZXJ5IHN1cnByaXNpbmcgYXMgZXZlbiAic2ltaWxhciIgc29uZ3MgYnkgdGhlIHNhbWUgYXJ0aXN0IG9yIHdpdGhpbiB0aGUgc2FtZSBnZW5yZSBjYW4gaGF2ZSB3aWxkbHkgZGlmZmVyZW50IGNoYXJhY3RlcmlzdGljcyB3aGVuIGl0IGNvbWVzIHRvIHRlbXBvIG9yIGFueXRoaW5nIGVsc2Ugd2UgYXJlIGxvb2tpbmcgYXQuCgoKIyMgUGlja2luZyBWYXJpYWJsZSBmb3IgU2ltcGxlIE1vZGVsCkJlbG93IEkgY3JlYXRlZCBoaXN0b2dyYW1zIHRvIHJlcHJlc2VudCB0aGUgZGlzdHJpYnV0aW9ucyBvZiBhbGwgZml2ZSBxdWFudGl0YXRpdmUgdmFyaWFibGVzIEkgYW0gZ29pbmcgdG8gdXNlIGluIHRoaXMgYW5hbHlzaXMuIFRoZSBwdXJwb3NlIGZvciBkb2luZyBzdWNoIGlzIHRvIGRldGVybWluZSBpZiBhbnkgc29ydCBvZiB2YXJpYWJsZSBtYW5pcHVsYXRpb24gKHR5cGljYWxseSBsb2cgdHJhbnNmb3JtYXRpb24gb3Igc3F1YXJlIHJvb3QgdHJhbnNmb3JtYXRpb24pIGlzIG5lY2Vzc2FyeSBiZWZvcmUgdXNpbmcgdGhlIHZhcmlhYmxlIGluIG91ciBsb2dpc3RpYyBtb2RlbC4KYGBge3J9CnBhcihtZnJvdyA9IGMoMiwgMyksIG1hciA9IGMoNCwgNCwgMiwgMSkpICAjIG1hciBjb250cm9scyBtYXJnaW5zIAogIAogIAp5bGltaXQgPSBtYXgoZGVuc2l0eShXb3JrX0RhdGEkdGVtcG8pJHkpCmhpc3QoV29ya19EYXRhJHRlbXBvLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSAiVGVtcG8gRGlzdHJpYnV0aW9uIiwgeGxhYj0iVGVtcG8iLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKGRlbnNpdHkoV29ya19EYXRhJHRlbXBvLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAoKeWxpbWl0ID0gbWF4KGRlbnNpdHkoV29ya19EYXRhJGRhbmNlYWJpbGl0eSkkeSkKaGlzdChXb3JrX0RhdGEkZGFuY2VhYmlsaXR5LCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSAiRGFuY2VhYmlsaXR5IERpc3RyaWJ1dGlvbiIsIHhsYWI9IkRhbmNlYWJpbGl0eSIsIAogICAgICAgY29sID0gImF6dXJlMSIsIGJvcmRlcj0ibGlnaHRzZWFncmVlbiIpCiAgbGluZXMoZGVuc2l0eShXb3JrX0RhdGEkZGFuY2VhYmlsaXR5LCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAogIAp5bGltaXQgPSBtYXgoZGVuc2l0eShXb3JrX0RhdGEkc3BlZWNoaW5lc3MpJHkpCmhpc3QoV29ya19EYXRhJHNwZWVjaGluZXNzLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSAiU3BlZWNoaW5lc3MgRGlzdHJpYnV0aW9uIiwgeGxhYj0iU3BlZWNoaW5lc3MiLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKGRlbnNpdHkoV29ya19EYXRhJHNwZWVjaGluZXNzLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAogIAogIAp5bGltaXQgPSBtYXgoZGVuc2l0eShXb3JrX0RhdGEkaW5zdHJ1bWVudGFsbmVzcykkeSkKaGlzdChXb3JrX0RhdGEkaW5zdHJ1bWVudGFsbmVzcywgcHJvYmFiaWxpdHkgPSBUUlVFLCBtYWluID0gIkluc3RydW1lbnRhbG5lc3MgRGlzdHJpYnV0aW9uIiwgeGxhYj0iSW5zdHJ1bWVudGFsbmVzcyIsIAogICAgICAgY29sID0gImF6dXJlMSIsIGJvcmRlcj0ibGlnaHRzZWFncmVlbiIpCiAgbGluZXMoZGVuc2l0eShXb3JrX0RhdGEkaW5zdHJ1bWVudGFsbmVzcywgYWRqdXN0PTIpLCBjb2w9ImJsdWUiKSAKICAKICAKeWxpbWl0ID0gbWF4KGRlbnNpdHkoV29ya19EYXRhJGR1cmF0aW9uX21pbnMpJHkpCmhpc3QoV29ya19EYXRhJGR1cmF0aW9uX21pbnMsIHByb2JhYmlsaXR5ID0gVFJVRSwgbWFpbiA9ICJMZW5ndGggKG1pbnMpIERpc3RyaWJ1dGlvbiIsIHhsYWI9Ikxlbmd0aCAobWlucykiLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKGRlbnNpdHkoV29ya19EYXRhJGR1cmF0aW9uX21pbnMsIGFkanVzdD0yKSwgY29sPSJibHVlIikgCgoKYGBgCgpXZSBjYW4gc2VlIGZyb20gdGhlIGhpc3RvZ3JhbXMgdGhhdCB0aGVyZSBpcyBhbiBleHRyZW1lIHNrZXcgaW4gc3BlZWNoaW5lc3MsIGluc3RydW1lbnRhbG5lc3MgYW5kIGxlbmd0aC4gV2hpbGUgdGhlcmUgYXJlIHNsaWdodCBza2V3cyBpbiB0ZW1wbyBhbmQgZGFuY2VhYmlsaXR5LCB0aGV5IGFyZSAqZmFyKiBtb3JlIG1vZGVyYXRlLiBTaW5jZSB0ZW1wbyBhcHBlYXJzIHRvIGJlIHRoZSBsZWFzdCBza2V3ZWQgb2YgdGhlIHZhcmlhYmxlcywgYW5kIGl0J3MgY2FsY3VsYXRpb24gaXMgdGhlIG1vc3Qgc3RyYWlnaHRmb3J3YXJkIChhIHNpbXBsZSBtZWFzdXJlIG9mIGJlYXRzIHBlciBtaW51dGUpLCBJIHdpbGwgdXNlIHRlbXBvIHRvIHBlcmZvcm0gbXkgc2ltcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24uCgoKIyMgQ3JlYXRpbmcgdGhlIE1vZGVsClVzaW5nIGJ1aWx0LWluIFIgZnVuY3Rpb25zLCBJIGNyZWF0ZWQgYSBzaW1wbGUgYmluYXJ5IGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwsIGluIHdoaWNoIHRoZSB0ZW1wbyBvZiBhIHNvbmcgaXMgbWVhbnQgdG8gcHJlZGljdCB3aGV0aGVyIG9yIG5vdCB0aGF0IHRyYWNrIGlzIHBvcHVsYXIgb3Igbm90IChwb3B1bGFyaXR5IHNjb3JlIG9mIDc1IG9yIG5vdCkuIEluIHRoZSBjYWxjdWxhdGlvbnMsIHRoZSBiYXNlIGxldmVsLCBvciAwLCB3YXMgc3RvcmVkIGZvciBpbnN0YW5jZXMgb2YgYSB0cmFjaydzIHBvcHVsYXJpdHkgYmVpbmcgbWFya2VkIGFzICJubyIuIFdoaWxlIHRoZSBpbnN0YW5jZSBsZXZlbCwgb3IgMSwgd2FzIHN0b3JlZCBmb3IgaW5zdGFuY2VzIG9mIGEgdHJhY2sncyBwb3B1bGFyaXR5IGJlaW5nIG1hcmtlZCBhcyAieWVzIi4KYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMgQ29udmVydCB0aGUgY2hhcmFjdGVyIHZhbHVlcyB0byBmYWN0b3JzLCBuZWNlc3NhcnkgZm9yIGdsbSBmdW5jdGlvbiB0byB3b3JrCldvcmtfRGF0YSRwb3B1bGFyID0gZmFjdG9yKFdvcmtfRGF0YSRwb3B1bGFyLCBsZXZlbHMgPSBjKCJubyIsICJ5ZXMiKSkKICBpbnZpc2libGUoc3RyKFdvcmtfRGF0YSRwb3B1bGFyKSkKICBpbnZpc2libGUodW5pcXVlKFdvcmtfRGF0YSRwb3B1bGFyKSkKYGBgCmBgYHtyfQpMb2dfTW9kZWwgPSBnbG0oZm9ybXVsYSA9IHBvcHVsYXIgfiB0ZW1wbywgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLCAKICAgIGRhdGEgPSBXb3JrX0RhdGEpCgppbnZpc2libGUoc3VtbWFyeShMb2dfTW9kZWwpKQoKTG9nX01vZGVsX0NvZWZfU3VtbWFyeSA9IHN1bW1hcnkoTG9nX01vZGVsKSRjb2VmICAgICAgICMgb3V0cHV0IHN0YXRzIG9mIGNvZWZmaWNpZW50cwpDb25maWRlbmNlX0ludGVydmFsID0gY29uZmludChMb2dfTW9kZWwpICAgICAgICAgICAgICAgICAgICAgIyBjb25maWRlbmNlIGludGVydmFscyBvZiBiZXRhcwpTdW1tYXJ5X1N0YXRzID0gY2JpbmQoTG9nX01vZGVsX0NvZWZfU3VtbWFyeSwgQ29uZmlkZW5jZV9JbnRlcnZhbC45NT1Db25maWRlbmNlX0ludGVydmFsKSAgICMgcm91bmRpbmcgb2ZmIGRlY2ltYWxzCmthYmxlKFN1bW1hcnlfU3RhdHMsY2FwdGlvbiA9ICJTaW1wbGUgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbCBTdW1tYXJ5IikgIApgYGAKVGhlIHN1bW1hcnkgb2Ygb3VyIG1vZGVsIGFib3ZlIGxlYWRzIHVzIHRvIGJlbGlldmUgdGhhdCBhIHRyYWNrJ3MgdGVtcG8gZG9lcyBoYXZlIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gd2l0aCB0aGUgbGlrZWxpaG9vZCB0aGF0IGEgdHJhY2sgaXMgcG9wdWxhciBvbiBTcG90aWZ5LCBob3dldmVyIHRoYXQgYXNzb2NpYXRpb24gaXMgdmVyeSBzbWFsbCBpbiBwcmFjdGljYWwgZWZmZWN0LiBEZXNwaXRlIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBwIHZhbHVlLCAkXGJldGEkfjF+IGhhcyBhbiBlc3RpbWF0ZWQgYXNzb2NpYXRpb24gd2l0aCB0aGUgcHJvYmFiaWxpdHkgb2YgYSB0cmFjayBiZWluZyBkZWVtZW5kIHBvcHVsYXIgb2YgLjAwNiwgYW5kIGEgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZGVlbWluZyB0aGUgYXNzb2NpYXRpb24gdG8gZmFsbCBiZXR3ZWVuIHRoZSBpbnRlcnZhbCBbLjAwMywgLjAwOV0uCgoKIyMgT2RkcyBSYXRpbyBTdW1tYXJ5CldoaWxlIHRoZSBkaXJlY3QgaW50ZXJwcmV0YXRpb24gb2YgYSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsJ3Mgc3VtbWFyeSBzdGF0aXN0aWNzIGNhbiBiZSBoZWxwZnVsLCBpdCBpcyBzb21ldGltZXMgbW9yZSBwcmFjdGljYWwgdG8gZXhhbWluZSBvdXIgbW9kZWwncyBvZGRzIHJhdGlvLiBBbiBvZGRzIHJhdGlvIHJlcHJlc2VudHMgdGhlIGxpa2VsaWhvb2Qgb2Ygc3VjY2VzcyBkaXZpZGVkIGJ5IHRoZSBsaWtlbGlob29kIG9mIGZhaWx1cmUuIEZvciBleGFtcGxlLCBhbiBvZGRzIHJhdGlvIG9mIDIgd291bGQgbWVhbiB0aGF0IHdoYXRldmVyIGluc3RhbmNlIHdlIGFyZSBjb25zaWRlcmluZyBhICJzdWNjZXNzIiBvY2N1cnMgdHdpY2UgdGhlIG51bWJlciBvZiB0aW1lcyB0aGFuIGl0IGZhaWxzIHRvIG9jY3VyLgpgYGB7cn0KIyBPZGRzIHJhdGlvCkxvZ19Nb2RlbF9Db2VmX1N1bW1hcnkgPSBzdW1tYXJ5KExvZ19Nb2RlbCkkY29lZgpPZGRzX1JhdGlvID0gZXhwKGNvZWYoTG9nX01vZGVsKSkKb3V0LnN0YXRzID0gY2JpbmQoTG9nX01vZGVsX0NvZWZfU3VtbWFyeSwgb2Rkcy5yYXRpbyA9IE9kZHNfUmF0aW8pICAgICAgICAgICAgICAgICAKa2FibGUob3V0LnN0YXRzLGNhcHRpb24gPSAiUmVncmVzc2lvbiBNb2RlbCBDb2VmZmljaWVudHMgVy8gT2RkcyBSYXRpb3MiKQpgYGAKVGhlIG9kZHMgcmF0aW8gYmV0d2VlbiBhIHRyYWNrJ3MgdGVtcG8gYW5kIGl0J3MgcG9wdWxhcml0eSBzdGF0dXMgaXMgfiAxLjAwNi4gU2luY2UgdGVtcG8gaXMgbWVhc3VyZWQgaW4gYmVhdHMgcGVyIG1pbnV0ZSAoQlBNKSwgdGhpcyBtZWFucyB0aGF0IGZvciBldmVyeSBhZGRpdGlvbmFsIGJlYXQgcGVyIG1pbnV0ZSB0aGF0IGEgc29uZyBpcyByZWNvcmRlZCBpbiwgaXQncyBwcm9iYWJpbGl0eSBvZiBoYXZpbmcgYSBwb3B1bGFyaXR5IHNjb3JlIGFib3ZlIDc1IGluY3JlYXNlcyBieSBhYm91dCAwLjYlLgoKIyMgR29vZG5lc3Mtb2YtZml0IG1lYXN1cmVzCkJlbG93IEkgY2FsY3VsYXRlZCB0aGUgZ29vZG5lc3Mtb2YtZml0IChHT0YpIG1lYXN1cmVzIGZvciB0aGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbC4gR2VuZXJhbGx5IHNwZWFraW5nLCBpdCBpcyBiZW5lZmljaWFsIHRvIGZpbmQgYSBtb2RlbCdzIEdPRiBmZWF0dXJlcyBhcyB0aGV5IHNlcnZlIGFzIHJlbGF0aXZlIGNvbXBhcmlzb25zIG9mIG1vZGVsIGVmZmljaWVuY3kgd2hlbiBjb21wYXJpbmcgbXVsdGlwbGUgbW9kZWxzLiBJbiB0aGlzIGluc3RhbmNlLCB3ZSBvbmx5IGNyZWF0ZWQgb25lIG1vZGVsIHNvIGZhciwgc28gdGhlIG1lYXN1cmVzIGFyZSBub3Qgb2YgcHJhY3RpY2FsIHVzZSBhdCB0aGUgbW9tZW50LgpgYGB7cn0KUmVzaWR1YWxfRGV2aWFuY2UgPSBMb2dfTW9kZWwkZGV2aWFuY2UKTnVsbF9SZXNpZHVhbF9EZXZpYW5jZSA9IExvZ19Nb2RlbCRudWxsLmRldmlhbmNlCmFpYyA9IExvZ19Nb2RlbCRhaWMKR29vZG5lc3NfT2ZfRml0ID0gY2JpbmQoRGV2aWFuY2UucmVzaWR1YWwgPSBSZXNpZHVhbF9EZXZpYW5jZSwgTnVsbC5EZXZpYW5jZS5SZXNpZHVhbCA9IE51bGxfUmVzaWR1YWxfRGV2aWFuY2UsCiAgICAgIEFJQyA9IGFpYykKcGFuZGVyKEdvb2RuZXNzX09mX0ZpdCkKCmBgYAoKIyMgU3VjY2VzcyBQcm9iYWJpbGl0eSBDdXJ2ZQpCZWxvdyBJIGNyZWF0ZWQgYSB2aXN1YWwgb2YgdGhlIHRoZSBtb2RlbCdzIFMgY3VydmUgKGFsc28gY2FsbGVkIHN1Y2Nlc3MgcHJvYmFiaWxpdHkgY3VydmUgb3IgbG9naXN0aWMgY3VydmUpLiBUaGUgUyBjdXJ2ZSBoZWxwcyB1cyBzZWUgdGhlIGNoYW5nZSBpbiBwcm9iYWJpbGl0eSBvZiBhbiBldmVudCBoYXBwZW5pbmcgKGEgdHJhY2sgYmVpbmcgcG9wdWxhciBvciBub3Qgb24gU3BvdGlmeSksIGluIHJlbGF0aW9uIHRvIGEgY2hhbmdlIGluIHRoZSB2YWx1ZSBvZiBhIHByZWRpY3RvciB2YXJpYWJsZSAodGVtcG8gaW4gQlBNIGluIHRoaXMgaW5zdGFuY2UpLgpgYGB7cn0KIyMjCgp0ZW1wb19yYW5nZSA9IHJhbmdlKFdvcmtfRGF0YSR0ZW1wbykKeCA9IHNlcSh0ZW1wb19yYW5nZVsxXSwgdGVtcG9fcmFuZ2VbMl0sIGxlbmd0aCA9IDIwMCkKYmV0YS54ID0gY29lZihMb2dfTW9kZWwpWzFdICsgY29lZihMb2dfTW9kZWwpWzJdKngKc3VjY2Vzcy5wcm9iID0gZXhwKGJldGEueCkvKDErZXhwKGJldGEueCkpCmZhaWx1cmUucHJvYiA9IDEvKDErZXhwKGJldGEueCkpCnlsaW1pdCA9IG1heChzdWNjZXNzLnByb2IsIGZhaWx1cmUucHJvYikKIyMKYmV0YTEgPSBjb2VmKExvZ19Nb2RlbClbMl0Kc3VjY2Vzcy5wcm9iLnJhdGUgPSBiZXRhMSpleHAoYmV0YS54KS8oMStleHAoYmV0YS54KSleMgojIwojIwpwYXIobWZyb3cgPSBjKDEsMSkpCnBsb3QoeCwgc3VjY2Vzcy5wcm9iLCB0eXBlID0gImwiLCBsd2QgPSAyLCBjb2wgPSAiYmxhY2siLAogICAgIG1haW4gPSAiVGhlIFByb2JhYmlsaXR5IG9mIGEgVHJhY2sgQmVpbmcgXG4gQ29uc2lkZXJlZCBQb3B1bGFyIG9uIFNwb3RpZnkiLCAKICAgICB5bGltPWMoMCwgMS4xKnlsaW1pdCksCiAgICAgeGxhYiA9ICJUZW1wbyAoQlBNKSIsCiAgICAgeWxhYiA9ICJwcm9iYWJpbGl0eSIsCiAgICAgYXhlcyA9IEZBTFNFLAogICAgIGNvbC5tYWluID0gImJsYWNrIiwKICAgICBjZXgubWFpbiA9IDEuMSkKIyBsaW5lcyh4LCBmYWlsdXJlLnByb2IsbHdkID0gMiwgY29sID0gImRhcmtyZWQiKQpheGlzKDEsIHBvcyA9IDApCmF4aXMoMikKCiMjCnkucmF0ZSA9IG1heChzdWNjZXNzLnByb2IucmF0ZSkKcGxvdCh4LCBzdWNjZXNzLnByb2IucmF0ZSwgdHlwZSA9ICJsIiwgbHdkID0gMiwgY29sID0gImJsYWNrIiwKICAgICBtYWluID0gIlRoZSBSYXRlIG9mIENoYW5nZSBpbiBQcm9iYWJpbGl0eSBvZiBhIFRyYWNrIEJlaW5nIFxuIENvbnNpZGVyZWQgUG9wdWxhciBvbiBTcG90aWZ5IiwgCiAgICAgeGxhYiA9ICJUZW1wbyAoQlBNKSIsCiAgICAgeWxhYiA9ICJSYXRlIG9mIENoYW5nZSIsCiAgICAgeWxpbT1jKDAsMS4xKnkucmF0ZSksCiAgICAgYXhlcyA9IEZBTFNFLAogICAgIGNvbC5tYWluID0gImJsYWNrIiwKICAgICBjZXgubWFpbiA9IDEuMQogICAgICkKYXhpcygxLCBwb3MgPSAwKQpheGlzKDIpCmBgYAoKVGhlIFMgQ3VydmUgcHJvdmlkZXMgdmlzdWFsIGNvbmZpcm1hdGlvbiBvZiB0aGUgY29uY2x1c2lvbnMgd2Ugd2VyZSBhYmxlIHRvIGRyYXcgZnJvbSBhbmFseXppbmcgb3VyIGNvZWZmaWNpZW50IHN1bW1hcnksIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBvZGRzIHJhdGlvLiBUaGF0IGlzLCB0aGF0IHRoZXJlIGlzIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiBhIHRyYWNrJ3MgdGVtcG8gYW5kIGl0J3MgbGlrZWxpaG9vZCBvZiBiZWluZyBhIHBvcHVsYXIgdHJhY2sgb24gU3BvdGlmeSwgKipidXQqKiB0aGF0IGFzc29jaWF0aW9uIGlzIHZlcnkgbWluaW1hbCBpbiBwcmFjdGljYWwgZWZmZWN0LgoKV2UgY2FuIHNlZSBmcm9tIG91ciBzZWNvbmQgcGxvdCwgdGhhdCBsb29rZWQgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSByYXRlIG9mIGNoYW5nZSBpbiBzYWlkIHByb2JhYmlsaXR5IGFuZCBhIHRyYWNrJ3MgdGVtcG8sIHRoYXQgZnJvbSA1MCB0byAyMDAgYmVhdHMgcGVyIG1pbnV0ZSwgdGhlIHByb2JhYmlsaXR5IG9mIGEgdHJhY2sgYmVpbmcgcG9wdWxhcidzIHBvc2l0aXZlIHJhdGUgb2YgY2hhbmdlIG9ubHkgaW5jcmVhc2VzIGZyb20gMC4wMDA2IHRvIDAuMDAxMi4KCiMgQ29uY2x1c2lvbgpUbyBjb25jbHVkZSwgd2UgY2FuIHNheSB0aGF0IGFsdGhvdWdoIHRoZXJlIGlzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhbmQgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSB0cmFjaydzIHRlbXBvIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBpdCBpcyBwb3B1bGFyIG9uIFNwb3RpZnksIHRoYXQgYXNzb2NpYXRpb24gaXMgb2Ygc3VjaCBhIHNtYWxsIG1hZ25pdHVkZSB0aGF0IGl0IGlzIHJlbGF0aXZlbHkgYSBub24tZmFjdG9yIGluIHByYWN0aWNhbCBzZW5zZS4gVGhlcmVmb3JlLCBpdCB3b3VsZCBiZSBvdmVybHkgc2ltcGxpc3RpYyBhbmQgaHlwZXJib2xpYyBmb3IgbXVzaWMgbGFiZWxzIG9yIGFnZW50cyB0byBhZ2dyZXNzaXZlbHkgcHVzaCB0aGVpciBhcnRpc3RzIHRvd2FyZHMgYSBtb3JlIHVwLXRlbXBvIHByb2R1Y3Rpb24sIGFzIHRoZSByZXR1cm4gb24gc3VjaCBhIGRlY2lzaW9uIHdvdWxkIGxpa2VseSBub3QgYmUgd29ydGggdGhlIGNvc3Qgb2Ygc291cmluZyB0aGUgcmVsYXRpb25zaGlwIHdpdGggdGhlIGFydGlzdCBhdCBoYW5kLiAKCiMgUmVmZXJlbmNlczoKCk9yaWdpbmFsIERhdGFzZXQgU291cmNlOgoKLSBodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3NvbG9tb25hbWVoL3Nwb3RpZnktbXVzaWMtZGF0YXNldD9zZWxlY3Q9aGlnaF9wb3B1bGFyaXR5X3Nwb3RpZnlfZGF0YS5jc3YKCkRhdGFzZXQgRG93bmxvYWQgTGlua3MgdmlhIEdpdGh1YjoKCi0gaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0NocmlzQjIzMjMvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9oaWdoX3BvcHVsYXJpdHlfc3BvdGlmeV9kYXRhLmNzdgoKLSBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ2hyaXNCMjMyMy9TVEEzMjEvcmVmcy9oZWFkcy9tYWluL2xvd19wb3B1bGFyaXR5X3Nwb3RpZnlfZGF0YS5jc3YK