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).
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.
Simple Logistic
Regression Model
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 |
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.
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.
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
(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].
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
(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%.
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)
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.
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