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_subgenre
|
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 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 Simple
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”.
Simple_Log_Model = glm(formula = popular ~ tempo, family = binomial(link = "logit"),
data = Work_Data)
invisible(summary(Simple_Log_Model))
Simple_Log_Model_Coef_Summary = summary(Simple_Log_Model)$coef # output stats of coefficients
Simple_Confidence_Interval = confint(Simple_Log_Model) # confidence intervals of betas
Simple_Summary_Stats = cbind(Simple_Log_Model_Coef_Summary, Simple_Confidence_Interval.95=Simple_Confidence_Interval) # rounding off decimals
kable(Simple_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 deemed 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
Simple_Log_Model_Coef_Summary = summary(Simple_Log_Model)$coef
Odds_Ratio = exp(coef(Simple_Log_Model))
out.stats = cbind(Simple_Log_Model_Coef_Summary, odds.ratio = Odds_Ratio)
kable(out.stats,caption = "Simple Regression Model Coefficients W/ Odds Ratios")
Simple 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 = Simple_Log_Model$deviance
Null_Residual_Deviance = Simple_Log_Model$null.deviance
aic = Simple_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(Simple_Log_Model)[1] + coef(Simple_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(Simple_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.
Takeaways from Simple
Logistic Regression Model
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.
Multiple Logistic
Regression Model
As we saw earlier when creating our simple regression model, there is
no significant risk of multicollinearity with the data we are working
with. However, we also saw there is an extreme rightward skew in the
distribution of speechiness, instrumentalness and length. Below I take a
closer look at the distributions of those three variables.
## Remember in the HW instructions, include not just the numerical variables but two categorical ones too (let's use playlist_genre and playlist_subgenre)
par(mfrow=c(1,2))
hist(speechiness, xlab="Speechiness", main = "")
hist(instrumentalness, xlab = "Instrumentalness", main = "")

hist(duration_mins, xlab = "Length (Mins)", main = "")

To combat the skew of all three variables, I will perform
discretization on each of them. The coding for such can be seen
below.
# Speechiness = "presence of audible words on 0 to 1 scale"
grp.speechiness = speechiness
grp.speechiness[speechiness < 0.5] = ": s under 0.5"
grp.speechiness[speechiness > 0.5] = ": s over 0.5"
# sum(speechiness > 0.5) = 14
# sum(speechiness < 0.5) = 2641
# Instrumentalness = "likelihood that the track contains instrumentals (0 to 1 scale)"
grp.instrumentalness = instrumentalness
grp.instrumentalness[instrumentalness < 0.1] = ": s under 0.1"
grp.instrumentalness[instrumentalness > 0.1 & instrumentalness <= 0.7] = ": s from 0.1 to 0.7"
grp.instrumentalness[instrumentalness > 0.7] = ": s over 0.7"
# sum(instrumentalness < 0.1) = 1802
# sum(instrumentalness > 0.1 & instrumentalness < 0.7) = 193
# sum(instrumentalness > 0.7) = 659
# duration_mins below
grp.duration_mins = duration_mins
grp.duration_mins[duration_mins < 5] = ": Under 5 mins"
grp.duration_mins[duration_mins >= 5 & duration_mins <= 10] = ": Between 5 and 10 mins"
grp.duration_mins[duration_mins > 10] = ": Over 10 mins"
# sum(duration_mins < 5) = 2424
# sum(duration_mins >= 5 & duration_mins <= 10) = 211
# sum(duration_mins > 10) = 20
Work_Data$grp.speechiness = grp.speechiness
Work_Data$grp.instrumentalness = grp.instrumentalness
Work_Data$grp.duration_mins = grp.duration_mins
Building Full
Multiple Logistic Model
For the full multiple logistic model, I will initially include the
continuous numerical variables tempo and danceability in their original
form, as well as the discretized transformations of instrumentalness,
length in minutes and speechiness. After coding this model in, I will
examine its summary statistics.
Multiple_Full_Log_Model = glm(formula = popular ~ tempo + danceability + grp.speechiness + grp.instrumentalness + grp.duration_mins, family = binomial(link = "logit"),
data = Work_Data)
invisible(summary(Multiple_Full_Log_Model))
Multiple_Full_Log_Model_Coef_Summary = summary(Multiple_Full_Log_Model)$coef
Multiple_Full_Confidence_Interval = confint(Multiple_Full_Log_Model)
Multiple_Full_Summary_Stats = cbind(Multiple_Full_Log_Model_Coef_Summary, Multiple_Full_Confidence_Interval.95=Multiple_Full_Confidence_Interval) # rounding off decimals
kable(Multiple_Full_Summary_Stats,caption = "Full Multiple Logistic Regression Model Summary")
Full Multiple Logistic Regression Model Summary
| (Intercept) |
-17.3380444 |
375.7154226 |
-0.0461467 |
0.9631933 |
NA |
7.5447416 |
| tempo |
0.0038700 |
0.0018965 |
2.0405532 |
0.0412953 |
0.0001487 |
0.0075874 |
| danceability |
0.3230690 |
0.3274150 |
0.9867263 |
0.3237768 |
-0.3156955 |
0.9684832 |
| grp.speechiness: s under 0.5 |
14.2760281 |
375.7151570 |
0.0379969 |
0.9696901 |
-10.9252242 |
NA |
| grp.instrumentalness: s over 0.7 |
-2.1650529 |
0.3613366 |
-5.9917905 |
0.0000000 |
-2.9070614 |
-1.4777880 |
| grp.instrumentalness: s under 0.1 |
0.6024645 |
0.2205999 |
2.7310277 |
0.0063137 |
0.1872867 |
1.0554459 |
| grp.duration_mins: Over 10 mins |
-13.2932711 |
310.2840235 |
-0.0428423 |
0.9658273 |
NA |
4.4755962 |
| grp.duration_mins: Under 5 mins |
0.6782754 |
0.2321971 |
2.9211189 |
0.0034878 |
0.2431306 |
1.1574116 |
invisible(table(Work_Data$popular, Work_Data$grp.speechiness))
invisible(table(Work_Data$popular, Work_Data$grp.instrumentalness))
invisible(table(Work_Data$popular, Work_Data$grp.duration_mins))
#NA's in kable function display are due to "perfect" results between certain levels of our discretized variables and the response variable of popular or not. If all observations in a certain level result in one of the two options for the response variable, then that coefficient will trend towards negative or positive infinity per R's calculations.
We can see the following from our model summary. First, just like the
results from our simple regression model, there is once again a
statistically significant association between a track’s tempo and its
likelihood of being popular on Spotify (p ~ 0.0413). However that
association is so small that it is of little practical
importance. Additionally, it appears that a track’s instrumentalness and
length absolutely play a part in its probability of being popular on
Spotify.
If we look at the discretized breakdown of instrumentalness, we see
that there is an significant difference in tracks whose instrumentalness
rating is of 0.7 and higher, or less than 0.1, when compared to tracks
whose rating is somewhere in the middle. For track length, there also
appears to be significant evidence that tracks less than 5 minutes long
have a greater probability of achieving popularity on Spotify than those
of any other lengths in our dataset.
On the other hand, there is not evidence to suggest that a track’s
danceability or speechiness have such an association with its
popularity.
After examining the model summary, I also chose to run VIF on this
full model, which can be seen below. Given that all GVIF are below 1.1,
we can safely say that multicollinearity is not pertinent to this
dataset. This finding is in line with the takeaway from our pairwise
scatterplot earlier on.
vif(Multiple_Full_Log_Model)
GVIF Df GVIF^(1/(2*Df))
tempo 1.018314 1 1.009116
danceability 1.048916 1 1.024166
grp.speechiness 1.000000 1 1.000000
grp.instrumentalness 1.035527 2 1.008766
grp.duration_mins 1.012616 2 1.003139
Manually Reduced
Multiple Logistic Model
Since parsimony (having as least amount of variables as possible
without losing significant accuracy in association examination or
prediction accuracy) is an important aspect of statistical modeling, I
also then chose to create a reduced version of my multiple logistic
model above. In this model, I did not include predictors whose impact
was very clearly insignificant as per the original full model’s summary
(danceability and speechiness). The summary for this new reduced model
is below.
Multiple_Reduced_Log_Model = glm(formula = popular ~ tempo + grp.instrumentalness + grp.duration_mins, family = binomial(link = "logit"),
data = Work_Data)
invisible(summary(Multiple_Reduced_Log_Model))
Multiple_Reduced_Log_Model_Coef_Summary = summary(Multiple_Reduced_Log_Model)$coef
Multiple_Reduced_Log_Model_Confidence_Interval = confint(Multiple_Reduced_Log_Model)
Multiple_Reduced_Summary_Stats = cbind(Multiple_Reduced_Log_Model_Coef_Summary, Multiple_Reduced_Confidence_Interval.95=Multiple_Reduced_Log_Model_Confidence_Interval) # rounding off decimals
kable(Multiple_Reduced_Summary_Stats,caption = "Reduced Multiple Logistic Regression Model Summary")
Reduced Multiple Logistic Regression Model Summary
| (Intercept) |
-2.8580203 |
0.3686009 |
-7.7536985 |
0.0000000 |
-3.5991921 |
-2.1520692 |
| tempo |
0.0035527 |
0.0018681 |
1.9017792 |
0.0572000 |
-0.0001176 |
0.0072091 |
| grp.instrumentalness: s over 0.7 |
-2.1920495 |
0.3605499 |
-6.0797397 |
0.0000000 |
-2.9326652 |
-1.5064166 |
| grp.instrumentalness: s under 0.1 |
0.6152133 |
0.2195892 |
2.8016558 |
0.0050841 |
0.2022035 |
1.0664024 |
| grp.duration_mins: Over 10 mins |
-13.3332333 |
310.6582027 |
-0.0429193 |
0.9657659 |
NA |
4.4642172 |
| grp.duration_mins: Under 5 mins |
0.6999423 |
0.2308747 |
3.0316973 |
0.0024318 |
0.2676486 |
1.1767544 |
The results from this new reduced model largely align with the
findings from the original multiple model. However, just as overfitting
a model with needless information is a poor practice, so is underfitting
a model by not including everything that is truly important. To ensure
validity of this reduced model’s structure, below I ran automatic
stepwwise selection via R’s AIC function. The model’s summary statistics
have been printed.
Algorithmically
Reduced Multiple Logistic Model
library(MASS)
AIC_Model = stepAIC(Multiple_Reduced_Log_Model,
scope = list(lower=formula(Multiple_Reduced_Log_Model),upper=formula(Multiple_Full_Log_Model)),
direction = "forward", # forward selection
trace = 0 # do not show the details
)
kable(Multiple_Reduced_Summary_Stats,caption ="AIC-Created Multiple Logistic Regression Model Summary")
AIC-Created Multiple Logistic Regression Model
Summary
| (Intercept) |
-2.8580203 |
0.3686009 |
-7.7536985 |
0.0000000 |
-3.5991921 |
-2.1520692 |
| tempo |
0.0035527 |
0.0018681 |
1.9017792 |
0.0572000 |
-0.0001176 |
0.0072091 |
| grp.instrumentalness: s over 0.7 |
-2.1920495 |
0.3605499 |
-6.0797397 |
0.0000000 |
-2.9326652 |
-1.5064166 |
| grp.instrumentalness: s under 0.1 |
0.6152133 |
0.2195892 |
2.8016558 |
0.0050841 |
0.2022035 |
1.0664024 |
| grp.duration_mins: Over 10 mins |
-13.3332333 |
310.6582027 |
-0.0429193 |
0.9657659 |
NA |
4.4642172 |
| grp.duration_mins: Under 5 mins |
0.6999423 |
0.2308747 |
3.0316973 |
0.0024318 |
0.2676486 |
1.1767544 |
We can see from our model summary that the AIC-created model and the
reduced model I coded in via manual variable selection are identical.
This is not surprising due to how clearly significant or insignificant
the predictors were in the original full model. Below I will perform
global GOF measures on the model to have record of a formal comparison
of each one’s accuracy.
Model Comparison and
Selection
# GOF Full Multiple Model
Mult_Full_Residual_Deviance = Multiple_Full_Log_Model$deviance
Mult_Full_Null_Residual_Deviance = Multiple_Full_Log_Model$null.deviance
Mult_Full_aic = Multiple_Full_Log_Model$aic
Mult_Full_Goodness_Of_Fit = cbind(Mult_Full_Residual_Deviance,
Mult_Full_Null_Residual_Deviance, Mult_Full_aic)
# GOF Manually Reduced Multiple Model
Mult_Reduced_Residual_Deviance = Multiple_Reduced_Log_Model$deviance
Mult_Reduced_Null_Residual_Deviance = Multiple_Reduced_Log_Model$null.deviance
Mult_Reduced_aic = Multiple_Reduced_Log_Model$aic
Mult_Reduced_Goodness_Of_Fit = cbind(Mult_Reduced_Residual_Deviance,
Mult_Reduced_Null_Residual_Deviance, Mult_Reduced_aic)
# GOF AIC Reduced Model
Mult_AIC_Residual_Deviance = AIC_Model$deviance
Mult_AIC_Null_Residual_Deviance = AIC_Model$null.deviance
Mult_AIC_aic = AIC_Model$aic
Mult_AIC_Goodness_Of_Fit = cbind(Mult_AIC_Residual_Deviance,
Mult_AIC_Null_Residual_Deviance, Mult_AIC_aic)
Model_GOFs = rbind(Mult_Full_Goodness_Of_Fit, Mult_Reduced_Goodness_Of_Fit,
Mult_AIC_Goodness_Of_Fit)
rownames(Model_GOFs) = c("Full Model", "Manually Reduced Model", "AIC Reduced Model")
colnames(Model_GOFs) = c("Residual Deviance", "Null Deviance", "AIC")
kable(Model_GOFs, caption ="GOF Summary of Each Model")
GOF Summary of Each Model
| Full Model |
2216.519 |
2463.55 |
2232.519 |
| Manually Reduced Model |
2224.352 |
2463.55 |
2236.352 |
| AIC Reduced Model |
2217.497 |
2463.55 |
2231.497 |
As we can see from the table above, all three models perform
extremely similar. Since our AIC-created model has the lowest AIC, and
its residual deviance is only a fraction greater than that of our full
model, we will accept the AIC-created model as our final choice to use
for interpetation of this dataset.
Takeaways from
Multiple Logistic Regression Modeling Process
After the simple logistic regression modeling process earlier, we
came away with the conclusion that a track’s tempo was ‘technically’
significant in it’s likelihood of being popular on Spotify, but the
practical magnitude of its impact was so small that it was not a factor
that deserves a great deal of emphasis in the real world. Our
AIC-created model for the most part confirms this finding, (p ~
.0572).
The most important findings from our multiple logistic regression
process come from what was discovered by our discretized variables.
Tracks with very high instrumentalness (over 0.7 on this dataset’s
scale) have a lesser likelihood of being popular on Spotify than those
that fall in between 0.1 and 0.7 on said scale. Additionally, tracks
under 0.1 on the scale actually have a slighly higher chance of being
popular.
Regarding a track’s length, tracks being under 5 minutes does have a
significant association with increased likelihood of popularity when
compared to tracks ranging from 5 to 10 minutes and tracks beyond 10
minutes. However, there is not sufficient evidence that tracks going
above 10 minutes significantly increases or reduces their chance of
being popular when compared to those in the 5 to 10 minute category.
Below is a visual displaying the odds ratios for relevant variables
from my AIC-created model, they will be referenced in my final
conclusion. The extreme estimate, standard error and odds ratio for
speechiness can be disregarded and attributed largely to the vast
majority of observations falling below 0.5 on the speechiness scale.
That along with the variable’s extremely high p value, and standard
error being practically identical to the standard error of the model’s
null intercept lead us to believe that the summary statistics for
speechiness can be chalked up to random chance, not true logistic
association.
AIC_Model_Coef_Summary = summary(AIC_Model)$coef
AIC_Odds_Ratio = exp(coef(AIC_Model))
AIC_out.stats = cbind(AIC_Model_Coef_Summary, odds.ratio = AIC_Odds_Ratio)
kable(AIC_out.stats,caption = "AIC-Created Multiple Regression Model Coefficients W/ Odds Ratios")
AIC-Created Multiple Regression Model Coefficients W/ Odds
Ratios
| (Intercept) |
-17.1140371 |
375.3481554 |
-0.0455951 |
0.9636330 |
0.0000000 |
| tempo |
0.0036649 |
0.0018745 |
1.9551582 |
0.0505644 |
1.0036716 |
| grp.instrumentalness: s over 0.7 |
-2.1888224 |
0.3605641 |
-6.0705491 |
0.0000000 |
0.1120486 |
| grp.instrumentalness: s under 0.1 |
0.6234236 |
0.2196071 |
2.8388131 |
0.0045282 |
1.8653032 |
| grp.duration_mins: Over 10 mins |
-13.3387936 |
310.5685700 |
-0.0429496 |
0.9657417 |
0.0000016 |
| grp.duration_mins: Under 5 mins |
0.7018358 |
0.2310153 |
3.0380492 |
0.0023812 |
2.0174530 |
| grp.speechiness: s under 0.5 |
14.2414898 |
375.3479579 |
0.0379421 |
0.9697338 |
1531088.9917716 |
LS0tCnRpdGxlOiAiVGhlIEZhY3RvcnMgQXNzb2NpYXRlZCB3aXRoIGEgU29uZydzIFByb2JhYmlsaXR5IG9mIGJlaW5nIFBvcHVsYXIgb24gU3BvdGlmeSIKYXV0aG9yOiAiQ2hyaXMgQmFobSIKZGF0ZTogIjIwMjUtMTAtMTUiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ193aWR0aDogNgogICAgZmlnX2hlaWdodDogNAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogbHVtZW4KICAgIGhpZ2hsaWdodDogdGFuZ28KICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogNAotLS0KCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLwogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsKICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsKICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7CiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7Cn0KCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovCiAgZm9udC1zaXplOiAyNHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICBmb250LXNpemU6IDE4cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICBmb250LXNpemU6IDE4cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgY29sb3I6IERhcmtCbHVlOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAyMHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBkYXJrcmVkOwogICAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDE4cHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDE2cHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDE0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBkYXJrcmVkOwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLwouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7CiAgY29udGVudDogIi4iOwp9CmBgYAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCAKIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuCgppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsgICAgICAgICAgICAgICAgICAgICAgIyB1c2UgY29uZGl0aW9uYWwgc3RhdGVtZW50IHRvIGRldGVjdAogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpICAgICAgICAgICAgICAgICAgIyB3aGV0aGVyIGEgcGFja2FnZSB3YXMgaW5zdGFsbGVkIGluCiAgIGxpYnJhcnkoa25pdHIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdXIgbWFjaGluZS4gSWYgbm90LCBpbnN0YWxsIGl0IGFuZAp9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsb2FkIGl0IHRvIHRoZSB3b3JraW5nIGRpcmVjdG9yeS4KCmlmICghcmVxdWlyZSh0aWR5dmVyc2UpKSB7bGlicmFyeSh0aWR5dnNlcnNlKX0gCgppZiAoIXJlcXVpcmUoR0dhbGx5KSkge2xpYnJhcnkoR0dhbGx5KX0gCgppZiAoIXJlcXVpcmUoa2FibGVFeHRyYSkpIHtsaWJyYXJ5KGthYmxlRXh0cmEpfSAKCmlmICghcmVxdWlyZShnZ3Bsb3QyKSkge2xpYnJhcnkoZ2dwbG90Mil9IAoKaWYgKCFyZXF1aXJlKGNhcikpIHtsaWJyYXJ5KGNhcil9IAoKaWYgKCFyZXF1aXJlKGRwbHlyKSkge2xpYnJhcnkoZHBseXIpfSAKCmlmICghcmVxdWlyZShwYW5kZXIpKSB7bGlicmFyeShwYW5kZXIpfSAKCmlmICghcmVxdWlyZShjYXIpKSB7bGlicmFyeShjYXIpfSAKCmlmICghcmVxdWlyZSgic2NhbGVzIikpIHsKaW5zdGFsbC5wYWNrYWdlcygic2NhbGVzIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmxpYnJhcnkoInNjYWxlcyIpIAp9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRSwKCWNvbW1lbnQgPSBOQSwKCXJlc3VsdHMgPSBUUlVFCikKICAgCmBgYAoKIyBJbnRyb2R1Y3Rpb24gYW5kIEJhY2tncm91bmQKCkhlcmUgd2UgaGF2ZSBhIGRhdGFzZXQgb3JpZ2luYWxseSBjb21wb3NlZCBvZiBvdmVyIDUsMDAwIHNvbmdzIHRoYXQgd2VyZSBhdmFpbGFibGUgb24gdGhlIG11c2ljLXN0cmVhbWluZyBzZXJ2aWNlIFNwb3RpZnkgb3ZlciB0aGUgY291cnNlIG9mIDIwMjQuIFRoZXNlIHRyYWNrcyBzdGVtIGZyb20gYSB3aWRlIGFycmF5IG9mIHZhc3RseSBkaWZmZXJlbnQgZ2VucmVzIGFuZCBzdHlsZXMgb2YgY3JlYXRpb24uIFRoZSBkYXRhc2V0IGlzIHB1YmxpY2x5IGF2YWlsYWJsZSBvbiB0aGUgcGxhdGZvcm0gS2FnZ2xlIGFuZCBpcyBwcm92aWRlZCBpbiB0aGUgUmVmZXJlbmNlcyBzZWN0aW9uIGJlbG93LiBBbHRob3VnaCB0aGUgZGF0YSBvcmlnaW5hbGx5IGNvbnRhaW5lZCAyOSB2YXJpYWJsZXMsIG9ubHkgMTEgcGxheSBhIHBhcnRpY3VsYXJseSByZWxldmFudCByb2xlIGluIHRoZSBhbmFseXNpcyBJIHdpc2ggdG8gZG8gaGVyZS4gQSBicmVha2Rvd24gb2YgdGhvc2UgdmFyaWFibGVzLCB0aGVpciBtZWFuaW5ncyBhbmQgZGF0YSB0eXBlcyBpcyBiZWxvdzoKCmBgYHtyIFZhcmlhYmxlIFRhYmxlLCBlY2hvPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKVmFyX1RhYmxlID0gZGF0YS5mcmFtZSgKICBOYW1lID0gYygidHJhY2tfcG9wdWxhcml0eSIsICJwb3B1bGFyIiwgInRyYWNrX25hbWUiLCAidHJhY2tfYXJ0aXN0IiwgInBsYXlsaXN0X2dlbnJlIiwgInBsYXlsaXN0X3N1YmdlbnJlIiwgInRlbXBvIiwgImRhbmNlYWJpbGl0eSIsInNwZWVjaGluZXNzIiwgImluc3RydW1lbnRhbG5lc3MiLCAiZHVyYXRpb25fbWlucyIpLAogIAogIE1lYW5pbmcgPSBjKCJzb25nJ3MgcmF0aW5nIG9uIHRoZSAwIC0gMTAwIG1ldHJpYyIsICJob3cgcG9wdWxhciB0aGUgdHJhY2sgaXMgKG1vcmUgb24gdGhhdCBsYXRlcikiLAogICAgICAgICAgICAgICJuYW1lIG9mIHRoZSBzb25nIiwKICAgICAgICAgICAgICAiYXJ0aXN0J3Mgc3RhZ2UgbmFtZSIsIAogICAgICAgICAgICAgICJnZW5yZSB0aGF0IFNwb3RpZnkgY2xhc3NpZmllcyB0aGUgc29uZyBpbiIsIAogICAgICAgICAgICAgICJzdWJnZW5yZSB0aGF0IFNwb3RpZnkgY2xhc3NpZmllcyB0aGUgc29uZyBpbiIsICAKICAgICAgICAgICAgICAidGhlIHNwZWVkIG9mIGEgdHJhY2ssIG1lYXN1cmVkIGluIGJlYXRzIHBlciBtaW51dGUgKEJQTSkiLCAKICAgICAgICAgICAgICAiQSBzY29yZSBkZXNjcmliaW5nIGhvdyBzdWl0YWJsZSBhIHRyYWNrIGlzIGZvciBkYW5jaW5nIGJhc2VkIG9uIHRlbXBvLCByaHl0aG0gc3RhYmlsaXR5LCBiZWF0IHN0cmVuZ3RoIGFuZCBvdmVyYWxsIHJlZ3VsYXJpdHkgKDAgdG8gMSBzY2FsZSkiLCAKICAgICAgICAgICAgICAidGhlIHByZXNlbmNlIG9mIGF1ZGlibGUgd29yZHMgKDAgdG8gMSBzY2FsZSkiLCAKICAgICAgICAgICAgICAibGlrZWxpaG9vZCB0aGF0IHRoZSB0cmFjayBjb250YWlucyBpbnN0cnVtZW50YWxzICgwIHRvIDEgc2NhbGUpICIsIAogICAgICAgICAgICAgICJsZW5ndGggb2YgdHJhY2sgaW4gbWludXRlcyIpLAogIAogIERhdGFfVHlwZSA9IGMoImRvdWJsZSIsICJjaGFyYWN0ZXIiLCAiY2hhcmFjdGVyIiwgImNoYXJhY3RlciIsICJjaGFyYWN0ZXIiLCAiY2hhcmFjdGVyIiwgImRvdWJsZSIsICJkb3VibGUiLCAiZG91YmxlIiwgImRvdWJsZSIsICJkb3VibGUiKQopCgprYWJsZShWYXJfVGFibGUpICU+JQogIGthYmxlX3N0eWxpbmcoCiAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiYm9yZGVyZWQiKSwKICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwKICAgIHBvc2l0aW9uID0gImNlbnRlciIpCmBgYAoKTWFueSBvZiB0aGUgb3RoZXIgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0IEkgY2hvc2UgdG8gZGlzcmVnYXJkIGFzIHRoZXkgZWl0aGVyIHBlcnRhaW5lZCB0byB1bm5lY2Vzc2FyeSB0ZWNobmljYWwgaW5mb3JtYXRpb24gKHN1Y2ggYXMgdGhlIGFsZ29yaXRobWljIGlkZW50aWZpZXIgZm9yIHRoZSBwYXJ0aWN1bGFyIHNvbmcgb3IgaXRzIGFsYnVtKSwgb3IgZXh0cmVtZWx5IG5pY2hlIG11c2ljYWwgdG9waWNzIHRoYXQgdGhlIGF2ZXJhZ2UgbGlzdGVuZXIgb3IgaW50cm9kdWN0b3J5IGNyaXRpYyB3b3VsZCBtb3N0IGxpa2VseSBub3QgcGljayB1cCBvbiAoc3VjaCBhcyBtb2RlIGFuZCBrZXkpLgoKIyMgT2JqZWN0aXZlIGZvciBteSBBbmFseXNpcwpVc2luZyB0aGlzIGRhdGFzZXQsIEkgd2lzaCB0byBxdWFudGlmaWFibHkgZXhhbWluZSB3aGF0IG11c2ljYWwgcXVhbGl0aWVzIGFuZCBjaGFyYWN0ZXJpc3RpY3MgbGVhZCB0byBhIHNvbmcgKG9yICJ0cmFjayIpIGJlY29taW5nIGV4dHJlbWVseSBzdWNjZXNzZnVsIChoZW5jZSBwb3B1bGFyKSB2aWEgU3BvdGlmeS4gQXMgb2YgT2N0b2JlciBvZiAyMDI1LCBTcG90aWZ5IGhhcyBhIG1hcmtldCBjYXAgb2Ygb3ZlciAxMzkgYmlsbGlvbiBkb2xsYXJzIGFuZCBjbG9zZSB0byA3MDAgbWlsbGlvbiB1c2Vycy4gVGhpcyBtZWFucyB0aGF0IGZvciBhbnkgYXNwaXJpbmcgbXVzaWNpYW4sICJtYWtpbmcgaXQgYmlnIiBvbiBTcG90aWZ5IHdvdWxkIHNlcnZlIGFzIGEgbW9udW1lbnRhbCBhbmQgbGlmZS1hbHRlcmluZyBtaWxlc3RvbmUuIAoKU3BvdGlmeSBoYXMgYSBtZXRyaWMga25vd24gYXMgdGhlIHBvcHVsYXJpdHkgaW5kZXggd2hpY2ggc2VydmVzIHRvIG51bWVyaWNhbGx5IHJlcHJlc2VudCB0aGUgcG9wdWxhcml0eSBvZiB0cmFja3Mgb24gaXRzIHBsYXRmb3JtLiBXaGlsZSB0aGUgZXhhY3QgZm9ybXVsYSBiZWhpbmQgdGhlIHNjb3JlIGlzIGtlcHQgY29uZmlkZW50aWFsLCBjcml0aWNzIGluIHRoZSBtdXNpYyBpbmR1c3RyeSBhbmQgdGhvc2Ugd2l0aCBzdHJvbmcgdGVjaG5pY2FsIGJhY2tncm91bmRzIGhhdmUgdGhlb3JpemVkIHRoYXQgdGhlIHByaW1hcnkgZmFjdG9ycyB3aGljaCBpbmZsdWVuY2UgYSB0cmFjaydzIHNjb3JlIGFyZSB0aGUgZm9sbG93aW5nOyBpdHMgdG90YWwgbnVtYmVyIG9mIHN0cmVhbXMsIGl0cyByZWNlbnQgbnVtYmVyIG9mIHN0cmVhbXMsIGl0cyBudW1iZXIgb2YgZG93bmxvYWRzIGFuZCBzYXZlcywgYW5kIGl0cyBtb250aC10by1tb250aCBncm93dGggaW4gYWxsIHRocmVlIG9mIHNhaWQgbWV0cmljcy4KClRoaXMgcG9wdWxhcml0eSBpbmRleCBvcGVyYXRlcyBvbiBhIHNjYWxlIHJhbmdpbmcgZnJvbSAwIHRvIDEwMCwgd2l0aCBvbmx5IHRoZSBtb3N0IHdlbGwtZXN0YWJsaXNoZWQgc3RhcnMgcmVhY2hpbmcgdGhlIDkwdGggcGVyY2VudGlsZSBhbmQgaGlnaGVyLiBUaGF0IGJlaW5nIHNhaWQsIGFueSB0cmFjayB3aXRoIGEgcmF0aW5nIG9mIDc1IG9yIGhpZ2hlciBpcyBsYXJnZWx5IGNvbnNpZGVyZWQgYSAidG9wIHRyYWNrIiBieSBpbmR1c3RyeSBleHBlcnRzLCBzbyB0aGF0IGlzIHRoZSBpbnRlcnByZXRhdGlvbiBJIHdpbGwgYXBwbHkgd2l0aCBteSBhbmFseXNpcy4gSSBjcmVhdGVkIGEgY2F0ZWdvcmljYWwgYmluYXJ5IHZhcmlhYmxlICJwb3B1bGFyIiwgd2hpY2ggaXMgdmFsdWVkIGFzICJ5ZXMiIGZvciB0cmFja3Mgd2l0aCBhIHBvcHVsYXJpdHkgaW5kZXggcmF0aW5nIG9mIDc1IG9yIGhpZ2hlciwgYW5kICJubyIgZm9yIHRyYWNrcyB3aXRoIGEgbG93ZXIgcmF0aW5nLiBJIHdpbGwgcGVyZm9ybSBsb2dpc3RpYyByZWdyZXNzaW9uIHRvIGFzc2VzcyB3aGljaCwgaWYgYW55LCBvZiB0aGUgZmFjdG9ycyBtZW50aW9uZWQgaW4gbXkgdmFyaWFibGUgYnJlYWtkb3duIGFib3ZlIGNvbnRyaWJ1dGUgdG8gYSB0cmFjayBiZWluZyBkZWVtZWQgcG9wdWxhciBvciBub3QuCgpgYGB7ciBEYXRhIFJlYWQgaW4gYW5kIENsZWFuaW5nLCBpbmNsdWRlPUZBTFNFfQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgIyBPdXQgb2Ygc2NpZW50aWZpYyBub3RhdGlvbiwgcGVyc29uYWwgcHJlZmVyZW5jZQoKRGF0YV9VcmxfQSA9ICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ2hyaXNCMjMyMy9TVEEzMjEvcmVmcy9oZWFkcy9tYWluL2hpZ2hfcG9wdWxhcml0eV9zcG90aWZ5X2RhdGEuY3N2IgpBYm92ZV82OCA9IHJlYWRfZGVsaW0oRGF0YV9VcmxfQSwgZGVsaW0gPSAiLCIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCgpEYXRhX1VybF9CID0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DaHJpc0IyMzIzL1NUQTMyMS9yZWZzL2hlYWRzL21haW4vbG93X3BvcHVsYXJpdHlfc3BvdGlmeV9kYXRhLmNzdiIKQmVsb3dfNjggPSByZWFkX2RlbGltKERhdGFfVXJsX0IsIGRlbGltID0gIiwiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQoKCiMjIyBMaW5lIGJlbG93IHdhcyB1c2VkIGZvciBpbml0aWFsIHZpc3VhbCBwdXJwb3NlcyAKI0Fib3ZlXzY4ID0gQWJvdmVfNjhbLCBjKCJ0cmFja19uYW1lIiwgInRyYWNrX2FsYnVtX25hbWUiLCAidHJhY2tfYXJ0aXN0IiwgInBsYXlsaXN0X25hbWUiLCAicGxheWxpc3RfZ2VucmUiLCAicGxheWxpc3Rfc3ViZ2VucmUiLCAidHJhY2tfcG9wdWxhcml0eSIsICJlbmVyZ3kiLCAidGVtcG8iLCAiZGFuY2VhYmlsaXR5IiwgImxvdWRuZXNzIiwgImxpdmVuZXNzIiwgInZhbGVuY2UiLCAic3BlZWNoaW5lc3MiLCAiaW5zdHJ1bWVudGFsbmVzcyIsICJrZXkiLCAiZHVyYXRpb25fbXMiLCAidGltZV9zaWduYXR1cmUiLCAidHJhY2tfaHJlZiIsICJtb2RlIiwgInVyaSIsICJ0eXBlIiwgInRyYWNrX2FsYnVtX3JlbGVhc2VfZGF0ZSIsICJhbmFseXNpc191cmwiLCAiaWQiLCAidHJhY2tfYWxidW1faWQiLCAicGxheWxpc3RfaWQiLCAidHJhY2tfaWQiLCAiYWNvdXN0aWNuZXNzIildCgoKRGF0YSA9IHJiaW5kKEFib3ZlXzY4LCBCZWxvd182OCkKICBEYXRhJGR1cmF0aW9uX21pbnMgPSBEYXRhJGR1cmF0aW9uX21zLzYwMDAwCkRhdGEkcG9wdWxhciA9IGlmZWxzZShEYXRhJHRyYWNrX3BvcHVsYXJpdHkgPiA3NSwgInllcyIsICJubyIpCgpEYXRhID0gZHBseXI6OnNlbGVjdChEYXRhLCB0cmFja19wb3B1bGFyaXR5LCBwb3B1bGFyLCB0cmFja19uYW1lLCB0cmFja19hbGJ1bV9uYW1lLCB0cmFja19hcnRpc3QsIHBsYXlsaXN0X25hbWUsIHBsYXlsaXN0X2dlbnJlLCBwbGF5bGlzdF9zdWJnZW5yZSwgZW5lcmd5LCB0ZW1wbywgZGFuY2VhYmlsaXR5LCBsb3VkbmVzcywgbGl2ZW5lc3MsIHZhbGVuY2UsIHNwZWVjaGluZXNzLCBpbnN0cnVtZW50YWxuZXNzLCBrZXksIGR1cmF0aW9uX21pbnMpCgp1bmlxdWUoRGF0YSRwbGF5bGlzdF9nZW5yZSkKCiMgQnJlYWtkb3duIG9mIFZhcmlhYmxlcyBLZXB0CiAgICMgSWRlbnRpZnlpbmcgVmFyaWFibGVzOgogICAgICAgIyB0cmFja19uYW1lCiAgICAgICAjIHRyYWNrX2FsYnVtX25hbWUKICAgICAgICMgdHJhY2tfYXJ0aXN0CiAgICMgQ2F0ZWdvcmljYWwgSW5mbzoKICAgICAgICMgcGxheWxpc3RfbmFtZQogICAgICAgIyBwbGF5bGlzdF9nZW5yZQogICAgICAgIyBwbGF5bGlzdF9zdWJnZW5yZQogICAgICAgIyAqKioqIHBvcHVsYXIgKioqKiBiaW5hcnkgcmVzcG9uc2UgdmFyaWFibGUgc2VsZi1jcmVhdGVkCiAgICMgUXVhbnRpdGF0aXZlIEluZm86CiAgICAgICAjIHRyYWNrX3BvcHVsYXJpdHkKICAgICAgICMgZW5lcmd5CiAgICAgICAjIHRlbXBvCiAgICAgICAjIGRhbmNlYWJpbGl0eQogICAgICAgIyBsb3VkbmVzcwogICAgICAgIyBsaXZlbmVzcwogICAgICAgIyB2YWxlbmNlCiAgICAgICAjIHNwZWVjaGluZXNzCiAgICAgICAjIGluc3RydW1lbnRhbG5lc3MKICAgICAgICMga2V5CiAgICAgICAjIGR1cmF0aW9uX21zCiAgIAogICAgIyAxNyBzZWxlY3RlZCBhYm92ZSBmcm9tIG9yaWdpbmFsIGRhdGEgc2V0LCBwbHVzIHBvcHVsYXIKICAgCiAgIyBWYXJpYWJsZXMgd2UgYXJlIG5vdCBpbmNsdWRpbmcgaW4gcmVkdWNlZCBkYXRhIHNldCBhcmUgbGFyZ2VseSB0ZWNobmljYWwgdHJhY2tpbmcgdmFyaWFibGVzIHN1Y2ggYXMgaWQgYW5kIGFuYWx5c2lzX3VybCwgb3IgdmVyeSBuaWNoZSBtdXNpY2FsIG1ldHJpY3MgdGhhdCB0aGUgYXZlcmFnZSBsaXN0ZW5lciB3b3VsZCBiZSB1bmF3YXJlIG9mIHN1Y2ggYXMgbW9kZS4KCgojIyMjIENoZWNraW5nIGZvciBEdXBsaWNhdGVzOgoKRHVwbGljYXRlX1NvbmdzID0gRGF0YVtkdXBsaWNhdGVkKERhdGEkdHJhY2tfbmFtZSkgfCBkdXBsaWNhdGVkKERhdGEkdHJhY2tfbmFtZSwgZnJvbUxhc3QgPSBUUlVFKSwgXQpEdXBsaWNhdGVfU29uZ3NfUmVkdWNlZCA9IGRwbHlyOjpzZWxlY3QoRHVwbGljYXRlX1NvbmdzLCB0cmFja19uYW1lLCB0cmFja19hcnRpc3QsIHBsYXlsaXN0X25hbWUsIHBsYXlsaXN0X2dlbnJlLCBwbGF5bGlzdF9zdWJnZW5yZSkKCkR1cGxpY2F0ZV9Tb25nX0NvdW50cyA9IGFzLmRhdGEuZnJhbWUodGFibGUoRHVwbGljYXRlX1NvbmdzJHRyYWNrX25hbWUpKSAgIAogICMgODM3IGluc3RhbmNlcyBvZiB0aGUgc2FtZSBzb25nIGJlaW5nIGxpc3RlZCBtb3JlIHRoYW4gb25jZQoKbmFtZXMoRHVwbGljYXRlX1NvbmdfQ291bnRzKSA9IGMoInRyYWNrX25hbWUiLCAiY291bnQiKQogICMgMzc4IHNvbmdzIGxpc3RlZCBtb3JlIHRoYW4gb25jZQoKc3VtKER1cGxpY2F0ZV9Tb25nX0NvdW50cyRjb3VudCkgICAjIFN1bSBmdW5jdGlvbiBjb25maXJtcyB0aGVyZSBhcmUgODM3IHRvdGFsIHJlcGVhdHMKCiAgCiMgR29pbmcgdG8gcmVkdWNlIG1haW4gZGF0YXNldCB0byBvbmx5IG9uZSBvYnNlcnZhdGlvbiBwZXIgc29uZywgdXNlZCBiYXNlIFIgZnVuY3Rpb24gdG8ga2VlcCBmaXJzdCBvY2N1cmVuY2Ugb2YgZWFjaCBzb25nCgojIyMjIE5ld19EYXRhID0gbm8gZHVwbGljYXRlcwpOZXdfRGF0YSA9IERhdGFbIWR1cGxpY2F0ZWQoRGF0YSR0cmFja19uYW1lKSwgXQoKIyBHb2luZyB0byBlbGltaW5hdGUgZ2VucmVzIHRoYXQgYXJlIG5vdCBwcmV2YWxlbnQgaW4gTm9ydGggQW1lcmljYSBhbmQgRXVyb3BlLCBhcyBteSBhbmFseXNpcyB3aWxsIGFwcGx5IGxhcmdlbHkgdG8gYXVkaWVuY2UgaW4gV2VzdGVybiB3b3JsZAoKdW5pcXVlKE5ld19EYXRhJHBsYXlsaXN0X2dlbnJlKQoKTmV3X0RhdGEkV2VzdCA9IGlmZWxzZSgKICBOZXdfRGF0YSRwbGF5bGlzdF9nZW5yZSAlaW4lIGMoImJyYXppbGlhbiIsICJhcmFiaWMiLCAiaW5kaWFuIiwgIm1hbmRvcG9wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNhbnRvcG9wIiwgImstcG9wIiwgInR1cmtpc2giLCAia29yZWFuIiwgImotcG9wIiwgIndvcmxkIiwgImxhdGluIiwgImVsZWN0cm9uaWMiKSwKICAibm8iLAogICJ5ZXMiCikKCnRhYmxlKE5ld19EYXRhJFdlc3QpCgojIyMjIE5ld19EYXRhMiA9IENvbmZpbmVkIHRvIFdlc3Rlcm4gbXVzaWMgZ2VucmVzCk5ld19EYXRhMiA9IE5ld19EYXRhW05ld19EYXRhJFdlc3QhPSAibm8iLCBdCmNvbG5hbWVzKE5ld19EYXRhMikKCiMjIyMgV29ya19EYXRhID0gUmVkdWNlZCBudW1iZXIgb2YgdmFyaWFibGVzIHRvIHBlcmZvcm0gYW5hbHlzaXMgb24sIG1pc3NpbmcgdmFsdWUgY2hlY2tzIHBlcmZvcm1lZApXb3JrX0RhdGEgPSBkcGx5cjo6c2VsZWN0KE5ld19EYXRhMiwgdHJhY2tfcG9wdWxhcml0eSwgcG9wdWxhciwgdHJhY2tfbmFtZSwgdHJhY2tfYXJ0aXN0LCBwbGF5bGlzdF9nZW5yZSwgcGxheWxpc3Rfc3ViZ2VucmUsIHRlbXBvLCBkYW5jZWFiaWxpdHksIHNwZWVjaGluZXNzLCBpbnN0cnVtZW50YWxuZXNzLCBkdXJhdGlvbl9taW5zKQoKV29ya19EYXRhID0gc29ydF9ieShXb3JrX0RhdGEsIFdvcmtfRGF0YSR0cmFja19wb3B1bGFyaXR5LCBkZWNyZWFzaW5nPVRSVUUpCgpzdW0oaXMubmEoV29ya19EYXRhKSkgIyA1IG1pc3NpbmcgdmFsdWVzIGluIGRhdGFzZXQKCk1pc3NpbmdfUm93cyA9IFdvcmtfRGF0YVshY29tcGxldGUuY2FzZXMoV29ya19EYXRhKSwgXQogIyBBbGwgNSBtaXNzaW5nIHZhbHVlcyBjb21lIGZyb20gb25lIG9ic2VydmF0aW9uLCB0aGUgc29uZyBpcyAiTWFrZSBJdCIgYnkgQmVyaGFuaW8uIEkgd2lsbCBqdXN0IHJlbW92ZSB0aGlzIHNvbmcgZnJvbSB0aGUgZGF0YXNldCB1c2luZyBmaWx0ZXIgZnVuY3Rpb24gYmVsb3cuCgpXb3JrX0RhdGEgPSBmaWx0ZXIoV29ya19EYXRhLCB0cmFja19uYW1lICE9ICJNYWtlIEl0IiApCgogIHRyYWNrX3BvcHVsYXJpdHkgPSBXb3JrX0RhdGEkdHJhY2tfcG9wdWxhcml0eSAKICBwb3B1bGFyID0gV29ya19EYXRhJHBvcHVsYXIKICB0cmFja19uYW1lID0gV29ya19EYXRhJHRyYWNrX25hbWUKICB0cmFja19hcnRpc3QgPSBXb3JrX0RhdGEkdHJhY2tfYXJ0aXN0CiAgcGxheWxpc3RfZ2VucmUgPSBXb3JrX0RhdGEkcGxheWxpc3RfZ2VucmUKICBwbGF5bGlzdF9zdWJnZW5yZSA9IFdvcmtfRGF0YSRwbGF5bGlzdF9zdWJnZW5yZQogIHRlbXBvID0gV29ya19EYXRhJHRlbXBvCiAgZGFuY2VhYmlsaXR5ID0gV29ya19EYXRhJGRhbmNlYWJpbGl0eQogIHNwZWVjaGluZXNzID0gV29ya19EYXRhJHNwZWVjaGluZXNzCiAgaW5zdHJ1bWVudGFsbmVzcyA9IFdvcmtfRGF0YSRpbnN0cnVtZW50YWxuZXNzCiAgZHVyYXRpb25fbWlucyA9IFdvcmtfRGF0YSRkdXJhdGlvbl9taW5zCiAgClF1YW50aXRhdGl2ZV9WYXJpYWJsZXMgPSBjYmluZCh0ZW1wbywgZGFuY2VhYmlsaXR5LCBzcGVlY2hpbmVzcywgaW5zdHJ1bWVudGFsbmVzcywgZHVyYXRpb25fbWlucykKCkNhdGVnb3JpY2FsX1ZhcmlhYmxlcyA9IGNiaW5kKHBsYXlsaXN0X2dlbnJlLCBwbGF5bGlzdF9zdWJnZW5yZSkKIApgYGAKCiMgU2ltcGxlIExvZ2lzdGljIFJlZ3Jlc3Npb24gTW9kZWwKCiMjIENoZWNraW5nIGZvciBQYWlyd2lzZSBSZWxhdGlvbnNoaXBzCkJlZm9yZSBqdW1waW5nIGludG8gbW9kZWwgY3JlYXRpb24sIEkgY3JlYXRlZCBhIGNvcnJlbGF0aW9uIG1hdHJpeCBmb3IgdGhlIHF1YW50aXRhdGl2ZSBwcmVkaWN0b3IgdmFyaWFibGVzIEkgYW0gZ29pbmcgdG8gdXNlIGluIG15IGFuYWx5c2lzLiBUaGlzIGlzIGJlY2F1c2UgdmFyaWFibGVzIHdpdGggdmVyeSBoaWdoIGNvcnJlbGF0aW9ucyAociA+PSAwLjgpIG9mdGVuIGNhbiBmdW5jdGlvbiBhcyBhbG1vc3QgbXVsdGlwbGVzIG9mIG9uZSBhbm90aGVyLCBsZWFkaW5nIHRvIGluYWNjdXJhdGUgY29uY2x1c2lvbnMsIGVzcGVjaWFsbHkgd2hlbiBwZXJmb3JtaW5nIG11bHRpcGxlIHJlZ3Jlc3Npb24uCmBgYHtyfQpjb3JfbWF0cml4ID0gY29yKFF1YW50aXRhdGl2ZV9WYXJpYWJsZXMpCiAgIyBObyBoaWdoIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMKCmthYmxlKGNvcl9tYXRyaXgsIGNhcHRpb24gPSAiQ29ycmVsYXRpb24gTWF0cml4IikKYGBgCgpBZnRlciBjcmVhdGluZyBhIGNvcnJlbGF0aW9uIG1hdHJpeCwgd2UgY2FuIHNlZSB0aGF0IG5vbmUgb2YgdGhlIHF1YW50aXRhdGl2ZSBwcmVkaWN0b3IgdmFyaWFibGVzIHRoYXQgd2UgYXJlIGV4YW1pbmluZyBoYXZlIGEgaGlnaCBjb3JyZWxhdGlvbiB3aXRoIG9uZSBhbm90aGVyLiBQcmFjdGljYWxseSBzcGVha2luZywgdGhpcyBpcyBub3QgdmVyeSBzdXJwcmlzaW5nIGFzIGV2ZW4gInNpbWlsYXIiIHNvbmdzIGJ5IHRoZSBzYW1lIGFydGlzdCBvciB3aXRoaW4gdGhlIHNhbWUgZ2VucmUgY2FuIGhhdmUgd2lsZGx5IGRpZmZlcmVudCBjaGFyYWN0ZXJpc3RpY3Mgd2hlbiBpdCBjb21lcyB0byB0ZW1wbyBvciBhbnl0aGluZyBlbHNlIHdlIGFyZSBsb29raW5nIGF0LgoKCiMjIFBpY2tpbmcgVmFyaWFibGUgZm9yIFNpbXBsZSBNb2RlbApCZWxvdyBJIGNyZWF0ZWQgaGlzdG9ncmFtcyB0byByZXByZXNlbnQgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgYWxsIGZpdmUgcXVhbnRpdGF0aXZlIHZhcmlhYmxlcyBJIGFtIGdvaW5nIHRvIHVzZSBpbiB0aGlzIGFuYWx5c2lzLiBUaGUgcHVycG9zZSBmb3IgZG9pbmcgc3VjaCBpcyB0byBkZXRlcm1pbmUgaWYgYW55IHNvcnQgb2YgdmFyaWFibGUgbWFuaXB1bGF0aW9uIGlzIG5lY2Vzc2FyeSBiZWZvcmUgdXNpbmcgdGhlIHZhcmlhYmxlIGluIG91ciBsb2dpc3RpYyBtb2RlbC4KYGBge3J9CnBhcihtZnJvdyA9IGMoMiwgMyksIG1hciA9IGMoNCwgNCwgMiwgMSkpICAjIG1hciBjb250cm9scyBtYXJnaW5zIAogIAogIAp5bGltaXQgPSBtYXgoZGVuc2l0eShXb3JrX0RhdGEkdGVtcG8pJHkpCmhpc3QoV29ya19EYXRhJHRlbXBvLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSAiVGVtcG8gRGlzdHJpYnV0aW9uIiwgeGxhYj0iVGVtcG8iLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKGRlbnNpdHkoV29ya19EYXRhJHRlbXBvLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAoKeWxpbWl0ID0gbWF4KGRlbnNpdHkoV29ya19EYXRhJGRhbmNlYWJpbGl0eSkkeSkKaGlzdChXb3JrX0RhdGEkZGFuY2VhYmlsaXR5LCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSAiRGFuY2VhYmlsaXR5IERpc3RyaWJ1dGlvbiIsIHhsYWI9IkRhbmNlYWJpbGl0eSIsIAogICAgICAgY29sID0gImF6dXJlMSIsIGJvcmRlcj0ibGlnaHRzZWFncmVlbiIpCiAgbGluZXMoZGVuc2l0eShXb3JrX0RhdGEkZGFuY2VhYmlsaXR5LCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAogIAp5bGltaXQgPSBtYXgoZGVuc2l0eShXb3JrX0RhdGEkc3BlZWNoaW5lc3MpJHkpCmhpc3QoV29ya19EYXRhJHNwZWVjaGluZXNzLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSAiU3BlZWNoaW5lc3MgRGlzdHJpYnV0aW9uIiwgeGxhYj0iU3BlZWNoaW5lc3MiLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKGRlbnNpdHkoV29ya19EYXRhJHNwZWVjaGluZXNzLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAogIAogIAp5bGltaXQgPSBtYXgoZGVuc2l0eShXb3JrX0RhdGEkaW5zdHJ1bWVudGFsbmVzcykkeSkKaGlzdChXb3JrX0RhdGEkaW5zdHJ1bWVudGFsbmVzcywgcHJvYmFiaWxpdHkgPSBUUlVFLCBtYWluID0gIkluc3RydW1lbnRhbG5lc3MgRGlzdHJpYnV0aW9uIiwgeGxhYj0iSW5zdHJ1bWVudGFsbmVzcyIsIAogICAgICAgY29sID0gImF6dXJlMSIsIGJvcmRlcj0ibGlnaHRzZWFncmVlbiIpCiAgbGluZXMoZGVuc2l0eShXb3JrX0RhdGEkaW5zdHJ1bWVudGFsbmVzcywgYWRqdXN0PTIpLCBjb2w9ImJsdWUiKSAKICAKICAKeWxpbWl0ID0gbWF4KGRlbnNpdHkoV29ya19EYXRhJGR1cmF0aW9uX21pbnMpJHkpCmhpc3QoV29ya19EYXRhJGR1cmF0aW9uX21pbnMsIHByb2JhYmlsaXR5ID0gVFJVRSwgbWFpbiA9ICJMZW5ndGggKG1pbnMpIERpc3RyaWJ1dGlvbiIsIHhsYWI9Ikxlbmd0aCAobWlucykiLCAKICAgICAgIGNvbCA9ICJhenVyZTEiLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKGRlbnNpdHkoV29ya19EYXRhJGR1cmF0aW9uX21pbnMsIGFkanVzdD0yKSwgY29sPSJibHVlIikgCgoKYGBgCgpXZSBjYW4gc2VlIGZyb20gdGhlIGhpc3RvZ3JhbXMgdGhhdCB0aGVyZSBpcyBhbiBleHRyZW1lIHNrZXcgaW4gc3BlZWNoaW5lc3MsIGluc3RydW1lbnRhbG5lc3MgYW5kIGxlbmd0aC4gV2hpbGUgdGhlcmUgYXJlIHNsaWdodCBza2V3cyBpbiB0ZW1wbyBhbmQgZGFuY2VhYmlsaXR5LCB0aGV5IGFyZSAqZmFyKiBtb3JlIG1vZGVyYXRlLiBTaW5jZSB0ZW1wbyBhcHBlYXJzIHRvIGJlIHRoZSBsZWFzdCBza2V3ZWQgb2YgdGhlIHZhcmlhYmxlcywgYW5kIGl0J3MgY2FsY3VsYXRpb24gaXMgdGhlIG1vc3Qgc3RyYWlnaHRmb3J3YXJkIChhIHNpbXBsZSBtZWFzdXJlIG9mIGJlYXRzIHBlciBtaW51dGUpLCBJIHdpbGwgdXNlIHRlbXBvIHRvIHBlcmZvcm0gbXkgc2ltcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24uCgoKIyMgQ3JlYXRpbmcgdGhlIFNpbXBsZSBNb2RlbApVc2luZyBidWlsdC1pbiBSIGZ1bmN0aW9ucywgSSBjcmVhdGVkIGEgc2ltcGxlIGJpbmFyeSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsLCBpbiB3aGljaCB0aGUgdGVtcG8gb2YgYSBzb25nIGlzIG1lYW50IHRvIHByZWRpY3Qgd2hldGhlciBvciBub3QgdGhhdCB0cmFjayBpcyBwb3B1bGFyIG9yIG5vdCAocG9wdWxhcml0eSBzY29yZSBvZiA3NSBvciBub3QpLiBJbiB0aGUgY2FsY3VsYXRpb25zLCB0aGUgYmFzZSBsZXZlbCwgb3IgMCwgd2FzIHN0b3JlZCBmb3IgaW5zdGFuY2VzIG9mIGEgdHJhY2sncyBwb3B1bGFyaXR5IGJlaW5nIG1hcmtlZCBhcyAibm8iLiBXaGlsZSB0aGUgaW5zdGFuY2UgbGV2ZWwsIG9yIDEsIHdhcyBzdG9yZWQgZm9yIGluc3RhbmNlcyBvZiBhIHRyYWNrJ3MgcG9wdWxhcml0eSBiZWluZyBtYXJrZWQgYXMgInllcyIuCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIENvbnZlcnQgdGhlIGNoYXJhY3RlciB2YWx1ZXMgdG8gZmFjdG9ycywgbmVjZXNzYXJ5IGZvciBnbG0gZnVuY3Rpb24gdG8gd29yawpXb3JrX0RhdGEkcG9wdWxhciA9IGZhY3RvcihXb3JrX0RhdGEkcG9wdWxhciwgbGV2ZWxzID0gYygibm8iLCAieWVzIikpCiAgaW52aXNpYmxlKHN0cihXb3JrX0RhdGEkcG9wdWxhcikpCiAgaW52aXNpYmxlKHVuaXF1ZShXb3JrX0RhdGEkcG9wdWxhcikpCmBgYApgYGB7cn0KU2ltcGxlX0xvZ19Nb2RlbCA9IGdsbShmb3JtdWxhID0gcG9wdWxhciB+IHRlbXBvLCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gImxvZ2l0IiksIAogICAgZGF0YSA9IFdvcmtfRGF0YSkKCmludmlzaWJsZShzdW1tYXJ5KFNpbXBsZV9Mb2dfTW9kZWwpKQoKU2ltcGxlX0xvZ19Nb2RlbF9Db2VmX1N1bW1hcnkgPSBzdW1tYXJ5KFNpbXBsZV9Mb2dfTW9kZWwpJGNvZWYgICAgICAgIyBvdXRwdXQgc3RhdHMgb2YgY29lZmZpY2llbnRzClNpbXBsZV9Db25maWRlbmNlX0ludGVydmFsID0gY29uZmludChTaW1wbGVfTG9nX01vZGVsKSAgICAgICAgICAgICAgICAgICAgICMgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgYmV0YXMKU2ltcGxlX1N1bW1hcnlfU3RhdHMgPSBjYmluZChTaW1wbGVfTG9nX01vZGVsX0NvZWZfU3VtbWFyeSwgU2ltcGxlX0NvbmZpZGVuY2VfSW50ZXJ2YWwuOTU9U2ltcGxlX0NvbmZpZGVuY2VfSW50ZXJ2YWwpICAgIyByb3VuZGluZyBvZmYgZGVjaW1hbHMKa2FibGUoU2ltcGxlX1N1bW1hcnlfU3RhdHMsY2FwdGlvbiA9ICJTaW1wbGUgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbCBTdW1tYXJ5IikgIApgYGAKVGhlIHN1bW1hcnkgb2Ygb3VyIG1vZGVsIGFib3ZlIGxlYWRzIHVzIHRvIGJlbGlldmUgdGhhdCBhIHRyYWNrJ3MgdGVtcG8gZG9lcyBoYXZlIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gd2l0aCB0aGUgbGlrZWxpaG9vZCB0aGF0IGEgdHJhY2sgaXMgcG9wdWxhciBvbiBTcG90aWZ5LCBob3dldmVyIHRoYXQgYXNzb2NpYXRpb24gaXMgdmVyeSBzbWFsbCBpbiBwcmFjdGljYWwgZWZmZWN0LiBEZXNwaXRlIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBwIHZhbHVlLCAkXGJldGEkfjF+IGhhcyBhbiBlc3RpbWF0ZWQgYXNzb2NpYXRpb24gd2l0aCB0aGUgcHJvYmFiaWxpdHkgb2YgYSB0cmFjayBiZWluZyBkZWVtZWQgcG9wdWxhciBvZiAuMDA2LCBhbmQgYSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBkZWVtaW5nIHRoZSBhc3NvY2lhdGlvbiB0byBmYWxsIGJldHdlZW4gdGhlIGludGVydmFsIFsuMDAzLCAuMDA5XS4KCgojIyBPZGRzIFJhdGlvIFN1bW1hcnkKV2hpbGUgdGhlIGRpcmVjdCBpbnRlcnByZXRhdGlvbiBvZiBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwncyBzdW1tYXJ5IHN0YXRpc3RpY3MgY2FuIGJlIGhlbHBmdWwsIGl0IGlzIHNvbWV0aW1lcyBtb3JlIHByYWN0aWNhbCB0byBleGFtaW5lIG91ciBtb2RlbCdzIG9kZHMgcmF0aW8uIEFuIG9kZHMgcmF0aW8gcmVwcmVzZW50cyB0aGUgbGlrZWxpaG9vZCBvZiBzdWNjZXNzIGRpdmlkZWQgYnkgdGhlIGxpa2VsaWhvb2Qgb2YgZmFpbHVyZS4gRm9yIGV4YW1wbGUsIGFuIG9kZHMgcmF0aW8gb2YgMiB3b3VsZCBtZWFuIHRoYXQgd2hhdGV2ZXIgaW5zdGFuY2Ugd2UgYXJlIGNvbnNpZGVyaW5nIGEgInN1Y2Nlc3MiIG9jY3VycyB0d2ljZSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRoYW4gaXQgZmFpbHMgdG8gb2NjdXIuCmBgYHtyfQojIE9kZHMgcmF0aW8KU2ltcGxlX0xvZ19Nb2RlbF9Db2VmX1N1bW1hcnkgPSBzdW1tYXJ5KFNpbXBsZV9Mb2dfTW9kZWwpJGNvZWYKT2Rkc19SYXRpbyA9IGV4cChjb2VmKFNpbXBsZV9Mb2dfTW9kZWwpKQpvdXQuc3RhdHMgPSBjYmluZChTaW1wbGVfTG9nX01vZGVsX0NvZWZfU3VtbWFyeSwgb2Rkcy5yYXRpbyA9IE9kZHNfUmF0aW8pICAgICAgICAgICAgICAgICAKa2FibGUob3V0LnN0YXRzLGNhcHRpb24gPSAiU2ltcGxlIFJlZ3Jlc3Npb24gTW9kZWwgQ29lZmZpY2llbnRzIFcvIE9kZHMgUmF0aW9zIikKYGBgClRoZSBvZGRzIHJhdGlvIGJldHdlZW4gYSB0cmFjaydzIHRlbXBvIGFuZCBpdCdzIHBvcHVsYXJpdHkgc3RhdHVzIGlzIH4gMS4wMDYuIFNpbmNlIHRlbXBvIGlzIG1lYXN1cmVkIGluIGJlYXRzIHBlciBtaW51dGUgKEJQTSksIHRoaXMgbWVhbnMgdGhhdCBmb3IgZXZlcnkgYWRkaXRpb25hbCBiZWF0IHBlciBtaW51dGUgdGhhdCBhIHNvbmcgaXMgcmVjb3JkZWQgaW4sIGl0J3MgcHJvYmFiaWxpdHkgb2YgaGF2aW5nIGEgcG9wdWxhcml0eSBzY29yZSBhYm92ZSA3NSBpbmNyZWFzZXMgYnkgYWJvdXQgMC42JS4KCiMjIEdvb2RuZXNzLW9mLWZpdCBtZWFzdXJlcwpCZWxvdyBJIGNhbGN1bGF0ZWQgdGhlIGdvb2RuZXNzLW9mLWZpdCAoR09GKSBtZWFzdXJlcyBmb3IgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwuIEdlbmVyYWxseSBzcGVha2luZywgaXQgaXMgYmVuZWZpY2lhbCB0byBmaW5kIGEgbW9kZWwncyBHT0YgZmVhdHVyZXMgYXMgdGhleSBzZXJ2ZSBhcyByZWxhdGl2ZSBjb21wYXJpc29ucyBvZiBtb2RlbCBlZmZpY2llbmN5IHdoZW4gY29tcGFyaW5nIG11bHRpcGxlIG1vZGVscy4gSW4gdGhpcyBpbnN0YW5jZSwgd2Ugb25seSBjcmVhdGVkIG9uZSBtb2RlbCBzbyBmYXIsIHNvIHRoZSBtZWFzdXJlcyBhcmUgbm90IG9mIHByYWN0aWNhbCB1c2UgYXQgdGhlIG1vbWVudC4KYGBge3J9ClJlc2lkdWFsX0RldmlhbmNlID0gU2ltcGxlX0xvZ19Nb2RlbCRkZXZpYW5jZQpOdWxsX1Jlc2lkdWFsX0RldmlhbmNlID0gU2ltcGxlX0xvZ19Nb2RlbCRudWxsLmRldmlhbmNlCmFpYyA9IFNpbXBsZV9Mb2dfTW9kZWwkYWljCkdvb2RuZXNzX09mX0ZpdCA9IGNiaW5kKERldmlhbmNlLnJlc2lkdWFsID0gUmVzaWR1YWxfRGV2aWFuY2UsIE51bGwuRGV2aWFuY2UuUmVzaWR1YWwgPSBOdWxsX1Jlc2lkdWFsX0RldmlhbmNlLAogICAgICBBSUMgPSBhaWMpCnBhbmRlcihHb29kbmVzc19PZl9GaXQpCgpgYGAKCiMjIFN1Y2Nlc3MgUHJvYmFiaWxpdHkgQ3VydmUKQmVsb3cgSSBjcmVhdGVkIGEgdmlzdWFsIG9mIHRoZSB0aGUgbW9kZWwncyBTIGN1cnZlIChhbHNvIGNhbGxlZCBzdWNjZXNzIHByb2JhYmlsaXR5IGN1cnZlIG9yIGxvZ2lzdGljIGN1cnZlKS4gVGhlIFMgY3VydmUgaGVscHMgdXMgc2VlIHRoZSBjaGFuZ2UgaW4gcHJvYmFiaWxpdHkgb2YgYW4gZXZlbnQgaGFwcGVuaW5nIChhIHRyYWNrIGJlaW5nIHBvcHVsYXIgb3Igbm90IG9uIFNwb3RpZnkpLCBpbiByZWxhdGlvbiB0byBhIGNoYW5nZSBpbiB0aGUgdmFsdWUgb2YgYSBwcmVkaWN0b3IgdmFyaWFibGUgKHRlbXBvIGluIEJQTSBpbiB0aGlzIGluc3RhbmNlKS4KYGBge3J9CiMjIwoKdGVtcG9fcmFuZ2UgPSByYW5nZShXb3JrX0RhdGEkdGVtcG8pCnggPSBzZXEodGVtcG9fcmFuZ2VbMV0sIHRlbXBvX3JhbmdlWzJdLCBsZW5ndGggPSAyMDApCmJldGEueCA9IGNvZWYoU2ltcGxlX0xvZ19Nb2RlbClbMV0gKyBjb2VmKFNpbXBsZV9Mb2dfTW9kZWwpWzJdKngKc3VjY2Vzcy5wcm9iID0gZXhwKGJldGEueCkvKDErZXhwKGJldGEueCkpCmZhaWx1cmUucHJvYiA9IDEvKDErZXhwKGJldGEueCkpCnlsaW1pdCA9IG1heChzdWNjZXNzLnByb2IsIGZhaWx1cmUucHJvYikKIyMKYmV0YTEgPSBjb2VmKFNpbXBsZV9Mb2dfTW9kZWwpWzJdCnN1Y2Nlc3MucHJvYi5yYXRlID0gYmV0YTEqZXhwKGJldGEueCkvKDErZXhwKGJldGEueCkpXjIKIyMKIyMKcGFyKG1mcm93ID0gYygxLDEpKQpwbG90KHgsIHN1Y2Nlc3MucHJvYiwgdHlwZSA9ICJsIiwgbHdkID0gMiwgY29sID0gImJsYWNrIiwKICAgICBtYWluID0gIlRoZSBQcm9iYWJpbGl0eSBvZiBhIFRyYWNrIEJlaW5nIFxuIENvbnNpZGVyZWQgUG9wdWxhciBvbiBTcG90aWZ5IiwgCiAgICAgeWxpbT1jKDAsIDEuMSp5bGltaXQpLAogICAgIHhsYWIgPSAiVGVtcG8gKEJQTSkiLAogICAgIHlsYWIgPSAicHJvYmFiaWxpdHkiLAogICAgIGF4ZXMgPSBGQUxTRSwKICAgICBjb2wubWFpbiA9ICJibGFjayIsCiAgICAgY2V4Lm1haW4gPSAxLjEpCiMgbGluZXMoeCwgZmFpbHVyZS5wcm9iLGx3ZCA9IDIsIGNvbCA9ICJkYXJrcmVkIikKYXhpcygxLCBwb3MgPSAwKQpheGlzKDIpCgojIwp5LnJhdGUgPSBtYXgoc3VjY2Vzcy5wcm9iLnJhdGUpCnBsb3QoeCwgc3VjY2Vzcy5wcm9iLnJhdGUsIHR5cGUgPSAibCIsIGx3ZCA9IDIsIGNvbCA9ICJibGFjayIsCiAgICAgbWFpbiA9ICJUaGUgUmF0ZSBvZiBDaGFuZ2UgaW4gUHJvYmFiaWxpdHkgb2YgYSBUcmFjayBCZWluZyBcbiBDb25zaWRlcmVkIFBvcHVsYXIgb24gU3BvdGlmeSIsIAogICAgIHhsYWIgPSAiVGVtcG8gKEJQTSkiLAogICAgIHlsYWIgPSAiUmF0ZSBvZiBDaGFuZ2UiLAogICAgIHlsaW09YygwLDEuMSp5LnJhdGUpLAogICAgIGF4ZXMgPSBGQUxTRSwKICAgICBjb2wubWFpbiA9ICJibGFjayIsCiAgICAgY2V4Lm1haW4gPSAxLjEKICAgICApCmF4aXMoMSwgcG9zID0gMCkKYXhpcygyKQpgYGAKClRoZSBTIEN1cnZlIHByb3ZpZGVzIHZpc3VhbCBjb25maXJtYXRpb24gb2YgdGhlIGNvbmNsdXNpb25zIHdlIHdlcmUgYWJsZSB0byBkcmF3IGZyb20gYW5hbHl6aW5nIG91ciBjb2VmZmljaWVudCBzdW1tYXJ5LCBjb25maWRlbmNlIGludGVydmFscyBhbmQgb2RkcyByYXRpby4gVGhhdCBpcywgdGhhdCB0aGVyZSBpcyBhIHBvc2l0aXZlIGFzc29jaWF0aW9uIGJldHdlZW4gYSB0cmFjaydzIHRlbXBvIGFuZCBpdCdzIGxpa2VsaWhvb2Qgb2YgYmVpbmcgYSBwb3B1bGFyIHRyYWNrIG9uIFNwb3RpZnksICoqYnV0KiogdGhhdCBhc3NvY2lhdGlvbiBpcyB2ZXJ5IG1pbmltYWwgaW4gcHJhY3RpY2FsIGVmZmVjdC4KCldlIGNhbiBzZWUgZnJvbSBvdXIgc2Vjb25kIHBsb3QsIHRoYXQgbG9va2VkIGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcmF0ZSBvZiBjaGFuZ2UgaW4gc2FpZCBwcm9iYWJpbGl0eSBhbmQgYSB0cmFjaydzIHRlbXBvLCB0aGF0IGZyb20gNTAgdG8gMjAwIGJlYXRzIHBlciBtaW51dGUsIHRoZSBwcm9iYWJpbGl0eSBvZiBhIHRyYWNrIGJlaW5nIHBvcHVsYXIncyBwb3NpdGl2ZSByYXRlIG9mIGNoYW5nZSBvbmx5IGluY3JlYXNlcyBmcm9tIDAuMDAwNiB0byAwLjAwMTIuCgojIyBUYWtlYXdheXMgZnJvbSBTaW1wbGUgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbApUbyBjb25jbHVkZSwgd2UgY2FuIHNheSB0aGF0IGFsdGhvdWdoIHRoZXJlIGlzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhbmQgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSB0cmFjaydzIHRlbXBvIGFuZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBpdCBpcyBwb3B1bGFyIG9uIFNwb3RpZnksIHRoYXQgYXNzb2NpYXRpb24gaXMgb2Ygc3VjaCBhIHNtYWxsIG1hZ25pdHVkZSB0aGF0IGl0IGlzIHJlbGF0aXZlbHkgYSBub24tZmFjdG9yIGluIHByYWN0aWNhbCBzZW5zZS4gVGhlcmVmb3JlLCBpdCB3b3VsZCBiZSBvdmVybHkgc2ltcGxpc3RpYyBhbmQgaHlwZXJib2xpYyBmb3IgbXVzaWMgbGFiZWxzIG9yIGFnZW50cyB0byBhZ2dyZXNzaXZlbHkgcHVzaCB0aGVpciBhcnRpc3RzIHRvd2FyZHMgYSBtb3JlIHVwLXRlbXBvIHByb2R1Y3Rpb24sIGFzIHRoZSByZXR1cm4gb24gc3VjaCBhIGRlY2lzaW9uIHdvdWxkIGxpa2VseSBub3QgYmUgd29ydGggdGhlIGNvc3Qgb2Ygc291cmluZyB0aGUgcmVsYXRpb25zaGlwIHdpdGggdGhlIGFydGlzdCBhdCBoYW5kLiAKCiMgTXVsdGlwbGUgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbApBcyB3ZSBzYXcgZWFybGllciB3aGVuIGNyZWF0aW5nIG91ciBzaW1wbGUgcmVncmVzc2lvbiBtb2RlbCwgdGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgcmlzayBvZiBtdWx0aWNvbGxpbmVhcml0eSB3aXRoIHRoZSBkYXRhIHdlIGFyZSB3b3JraW5nIHdpdGguIEhvd2V2ZXIsIHdlIGFsc28gc2F3IHRoZXJlIGlzIGFuIGV4dHJlbWUgcmlnaHR3YXJkIHNrZXcgaW4gdGhlIGRpc3RyaWJ1dGlvbiBvZiBzcGVlY2hpbmVzcywgaW5zdHJ1bWVudGFsbmVzcyBhbmQgbGVuZ3RoLiBCZWxvdyBJIHRha2UgYSBjbG9zZXIgbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9ucyBvZiB0aG9zZSB0aHJlZSB2YXJpYWJsZXMuCmBgYHtyfQojIyBSZW1lbWJlciBpbiB0aGUgSFcgaW5zdHJ1Y3Rpb25zLCBpbmNsdWRlIG5vdCBqdXN0IHRoZSBudW1lcmljYWwgdmFyaWFibGVzIGJ1dCB0d28gY2F0ZWdvcmljYWwgb25lcyB0b28gKGxldCdzIHVzZSBwbGF5bGlzdF9nZW5yZSBhbmQgcGxheWxpc3Rfc3ViZ2VucmUpCgpwYXIobWZyb3c9YygxLDIpKQpoaXN0KHNwZWVjaGluZXNzLCB4bGFiPSJTcGVlY2hpbmVzcyIsIG1haW4gPSAiIikKaGlzdChpbnN0cnVtZW50YWxuZXNzLCB4bGFiID0gIkluc3RydW1lbnRhbG5lc3MiLCBtYWluID0gIiIpCmhpc3QoZHVyYXRpb25fbWlucywgeGxhYiA9ICJMZW5ndGggKE1pbnMpIiwgbWFpbiA9ICIiKQpgYGAKClRvIGNvbWJhdCB0aGUgc2tldyBvZiBhbGwgdGhyZWUgdmFyaWFibGVzLCBJIHdpbGwgcGVyZm9ybSBkaXNjcmV0aXphdGlvbiBvbiBlYWNoIG9mIHRoZW0uIFRoZSBjb2RpbmcgZm9yIHN1Y2ggY2FuIGJlIHNlZW4gYmVsb3cuCmBgYHtyfQogICMgU3BlZWNoaW5lc3MgPSAicHJlc2VuY2Ugb2YgYXVkaWJsZSB3b3JkcyBvbiAwIHRvIDEgc2NhbGUiCmdycC5zcGVlY2hpbmVzcyA9IHNwZWVjaGluZXNzCmdycC5zcGVlY2hpbmVzc1tzcGVlY2hpbmVzcyA8IDAuNV0gPSAiOiBzIHVuZGVyIDAuNSIKZ3JwLnNwZWVjaGluZXNzW3NwZWVjaGluZXNzID4gMC41XSA9ICI6IHMgb3ZlciAwLjUiCgogICMgc3VtKHNwZWVjaGluZXNzID4gMC41KSA9IDE0CiAgIyBzdW0oc3BlZWNoaW5lc3MgPCAwLjUpID0gMjY0MQoKCiAgIyBJbnN0cnVtZW50YWxuZXNzID0gImxpa2VsaWhvb2QgdGhhdCB0aGUgdHJhY2sgY29udGFpbnMgaW5zdHJ1bWVudGFscyAoMCB0byAxIHNjYWxlKSIKZ3JwLmluc3RydW1lbnRhbG5lc3MgPSBpbnN0cnVtZW50YWxuZXNzCmdycC5pbnN0cnVtZW50YWxuZXNzW2luc3RydW1lbnRhbG5lc3MgPCAwLjFdID0gIjogcyB1bmRlciAwLjEiCmdycC5pbnN0cnVtZW50YWxuZXNzW2luc3RydW1lbnRhbG5lc3MgPiAwLjEgJiBpbnN0cnVtZW50YWxuZXNzIDw9IDAuN10gPSAiOiBzIGZyb20gMC4xIHRvIDAuNyIKZ3JwLmluc3RydW1lbnRhbG5lc3NbaW5zdHJ1bWVudGFsbmVzcyA+IDAuN10gPSAiOiBzIG92ZXIgMC43IgogCiAjICBzdW0oaW5zdHJ1bWVudGFsbmVzcyA8IDAuMSkgPSAxODAyCiAjICBzdW0oaW5zdHJ1bWVudGFsbmVzcyA+IDAuMSAmIGluc3RydW1lbnRhbG5lc3MgPCAwLjcpID0gMTkzCiAjICBzdW0oaW5zdHJ1bWVudGFsbmVzcyA+IDAuNykgPSA2NTkKICAKCiAgIyBkdXJhdGlvbl9taW5zIGJlbG93CmdycC5kdXJhdGlvbl9taW5zID0gZHVyYXRpb25fbWlucwpncnAuZHVyYXRpb25fbWluc1tkdXJhdGlvbl9taW5zIDwgNV0gPSAiOiBVbmRlciA1IG1pbnMiCmdycC5kdXJhdGlvbl9taW5zW2R1cmF0aW9uX21pbnMgPj0gNSAmIGR1cmF0aW9uX21pbnMgPD0gMTBdID0gIjogQmV0d2VlbiA1IGFuZCAxMCBtaW5zIgpncnAuZHVyYXRpb25fbWluc1tkdXJhdGlvbl9taW5zID4gMTBdID0gIjogT3ZlciAxMCBtaW5zIgogIAojIHN1bShkdXJhdGlvbl9taW5zIDwgNSkgPSAyNDI0CiMgc3VtKGR1cmF0aW9uX21pbnMgPj0gNSAmIGR1cmF0aW9uX21pbnMgPD0gMTApID0gMjExCiMgc3VtKGR1cmF0aW9uX21pbnMgPiAxMCkgPSAyMAoKCldvcmtfRGF0YSRncnAuc3BlZWNoaW5lc3MgPSBncnAuc3BlZWNoaW5lc3MKV29ya19EYXRhJGdycC5pbnN0cnVtZW50YWxuZXNzID0gZ3JwLmluc3RydW1lbnRhbG5lc3MKV29ya19EYXRhJGdycC5kdXJhdGlvbl9taW5zID0gZ3JwLmR1cmF0aW9uX21pbnMKYGBgCgoKIyMgQnVpbGRpbmcgRnVsbCBNdWx0aXBsZSBMb2dpc3RpYyBNb2RlbApGb3IgdGhlIGZ1bGwgbXVsdGlwbGUgbG9naXN0aWMgbW9kZWwsIEkgd2lsbCBpbml0aWFsbHkgaW5jbHVkZSB0aGUgY29udGludW91cyBudW1lcmljYWwgdmFyaWFibGVzIHRlbXBvIGFuZCBkYW5jZWFiaWxpdHkgaW4gdGhlaXIgb3JpZ2luYWwgZm9ybSwgYXMgd2VsbCBhcyB0aGUgZGlzY3JldGl6ZWQgdHJhbnNmb3JtYXRpb25zIG9mIGluc3RydW1lbnRhbG5lc3MsIGxlbmd0aCBpbiBtaW51dGVzIGFuZCBzcGVlY2hpbmVzcy4gQWZ0ZXIgY29kaW5nIHRoaXMgbW9kZWwgaW4sIEkgd2lsbCBleGFtaW5lIGl0cyBzdW1tYXJ5IHN0YXRpc3RpY3MuCgpgYGB7cn0KTXVsdGlwbGVfRnVsbF9Mb2dfTW9kZWwgPSBnbG0oZm9ybXVsYSA9IHBvcHVsYXIgfiB0ZW1wbyArIGRhbmNlYWJpbGl0eSArIGdycC5zcGVlY2hpbmVzcyArIGdycC5pbnN0cnVtZW50YWxuZXNzICsgZ3JwLmR1cmF0aW9uX21pbnMsIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSwgCiAgICBkYXRhID0gV29ya19EYXRhKQoKaW52aXNpYmxlKHN1bW1hcnkoTXVsdGlwbGVfRnVsbF9Mb2dfTW9kZWwpKQoKTXVsdGlwbGVfRnVsbF9Mb2dfTW9kZWxfQ29lZl9TdW1tYXJ5ID0gc3VtbWFyeShNdWx0aXBsZV9GdWxsX0xvZ19Nb2RlbCkkY29lZgpNdWx0aXBsZV9GdWxsX0NvbmZpZGVuY2VfSW50ZXJ2YWwgPSBjb25maW50KE11bHRpcGxlX0Z1bGxfTG9nX01vZGVsKSAgCgpNdWx0aXBsZV9GdWxsX1N1bW1hcnlfU3RhdHMgPSBjYmluZChNdWx0aXBsZV9GdWxsX0xvZ19Nb2RlbF9Db2VmX1N1bW1hcnksIE11bHRpcGxlX0Z1bGxfQ29uZmlkZW5jZV9JbnRlcnZhbC45NT1NdWx0aXBsZV9GdWxsX0NvbmZpZGVuY2VfSW50ZXJ2YWwpICAgIyByb3VuZGluZyBvZmYgZGVjaW1hbHMKCmthYmxlKE11bHRpcGxlX0Z1bGxfU3VtbWFyeV9TdGF0cyxjYXB0aW9uID0gIkZ1bGwgTXVsdGlwbGUgTG9naXN0aWMgUmVncmVzc2lvbiBNb2RlbCBTdW1tYXJ5IikgCgppbnZpc2libGUodGFibGUoV29ya19EYXRhJHBvcHVsYXIsIFdvcmtfRGF0YSRncnAuc3BlZWNoaW5lc3MpKQppbnZpc2libGUodGFibGUoV29ya19EYXRhJHBvcHVsYXIsIFdvcmtfRGF0YSRncnAuaW5zdHJ1bWVudGFsbmVzcykpCmludmlzaWJsZSh0YWJsZShXb3JrX0RhdGEkcG9wdWxhciwgV29ya19EYXRhJGdycC5kdXJhdGlvbl9taW5zKSkKICAjTkEncyBpbiBrYWJsZSBmdW5jdGlvbiBkaXNwbGF5IGFyZSBkdWUgdG8gInBlcmZlY3QiIHJlc3VsdHMgYmV0d2VlbiBjZXJ0YWluIGxldmVscyBvZiBvdXIgZGlzY3JldGl6ZWQgdmFyaWFibGVzIGFuZCB0aGUgcmVzcG9uc2UgdmFyaWFibGUgb2YgcG9wdWxhciBvciBub3QuIElmIGFsbCBvYnNlcnZhdGlvbnMgaW4gYSBjZXJ0YWluIGxldmVsIHJlc3VsdCBpbiBvbmUgb2YgdGhlIHR3byBvcHRpb25zIGZvciB0aGUgcmVzcG9uc2UgdmFyaWFibGUsIHRoZW4gdGhhdCBjb2VmZmljaWVudCB3aWxsIHRyZW5kIHRvd2FyZHMgbmVnYXRpdmUgb3IgcG9zaXRpdmUgaW5maW5pdHkgcGVyIFIncyBjYWxjdWxhdGlvbnMuCgoKYGBgCgpXZSBjYW4gc2VlIHRoZSBmb2xsb3dpbmcgZnJvbSBvdXIgbW9kZWwgc3VtbWFyeS4gRmlyc3QsIGp1c3QgbGlrZSB0aGUgcmVzdWx0cyBmcm9tIG91ciBzaW1wbGUgcmVncmVzc2lvbiBtb2RlbCwgdGhlcmUgaXMgb25jZSBhZ2FpbiBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYXNzb2NpYXRpb24gYmV0d2VlbiBhIHRyYWNrJ3MgdGVtcG8gYW5kIGl0cyBsaWtlbGlob29kIG9mIGJlaW5nIHBvcHVsYXIgb24gU3BvdGlmeSAocCB+IDAuMDQxMykuIEhvd2V2ZXIgdGhhdCBhc3NvY2lhdGlvbiBpcyBzbyBzbWFsbCB0aGF0IGl0IGlzIG9mIGxpdHRsZSAqcHJhY3RpY2FsKiBpbXBvcnRhbmNlLiBBZGRpdGlvbmFsbHksIGl0IGFwcGVhcnMgdGhhdCBhIHRyYWNrJ3MgaW5zdHJ1bWVudGFsbmVzcyBhbmQgbGVuZ3RoIGFic29sdXRlbHkgcGxheSBhIHBhcnQgaW4gaXRzIHByb2JhYmlsaXR5IG9mIGJlaW5nIHBvcHVsYXIgb24gU3BvdGlmeS4gCgpJZiB3ZSBsb29rIGF0IHRoZSBkaXNjcmV0aXplZCBicmVha2Rvd24gb2YgaW5zdHJ1bWVudGFsbmVzcywgd2Ugc2VlIHRoYXQgdGhlcmUgaXMgYW4gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiB0cmFja3Mgd2hvc2UgaW5zdHJ1bWVudGFsbmVzcyByYXRpbmcgaXMgb2YgMC43IGFuZCBoaWdoZXIsIG9yIGxlc3MgdGhhbiAwLjEsIHdoZW4gY29tcGFyZWQgdG8gdHJhY2tzIHdob3NlIHJhdGluZyBpcyBzb21ld2hlcmUgaW4gdGhlIG1pZGRsZS4gRm9yIHRyYWNrIGxlbmd0aCwgdGhlcmUgYWxzbyBhcHBlYXJzIHRvIGJlIHNpZ25pZmljYW50IGV2aWRlbmNlIHRoYXQgdHJhY2tzIGxlc3MgdGhhbiA1IG1pbnV0ZXMgbG9uZyBoYXZlIGEgZ3JlYXRlciBwcm9iYWJpbGl0eSBvZiBhY2hpZXZpbmcgcG9wdWxhcml0eSBvbiBTcG90aWZ5IHRoYW4gdGhvc2Ugb2YgYW55IG90aGVyIGxlbmd0aHMgaW4gb3VyIGRhdGFzZXQuCgpPbiB0aGUgb3RoZXIgaGFuZCwgdGhlcmUgaXMgbm90IGV2aWRlbmNlIHRvIHN1Z2dlc3QgdGhhdCBhIHRyYWNrJ3MgZGFuY2VhYmlsaXR5IG9yIHNwZWVjaGluZXNzIGhhdmUgc3VjaCBhbiBhc3NvY2lhdGlvbiB3aXRoIGl0cyBwb3B1bGFyaXR5LgoKQWZ0ZXIgZXhhbWluaW5nIHRoZSBtb2RlbCBzdW1tYXJ5LCBJIGFsc28gY2hvc2UgdG8gcnVuIFZJRiBvbiB0aGlzIGZ1bGwgbW9kZWwsIHdoaWNoIGNhbiBiZSBzZWVuIGJlbG93LiBHaXZlbiB0aGF0IGFsbCBHVklGIGFyZSBiZWxvdyAxLjEsIHdlIGNhbiBzYWZlbHkgc2F5IHRoYXQgbXVsdGljb2xsaW5lYXJpdHkgaXMgbm90IHBlcnRpbmVudCB0byB0aGlzIGRhdGFzZXQuIFRoaXMgZmluZGluZyBpcyBpbiBsaW5lIHdpdGggdGhlIHRha2Vhd2F5IGZyb20gb3VyIHBhaXJ3aXNlIHNjYXR0ZXJwbG90IGVhcmxpZXIgb24uCmBgYHtyfQp2aWYoTXVsdGlwbGVfRnVsbF9Mb2dfTW9kZWwpCmBgYAoKIyMgTWFudWFsbHkgUmVkdWNlZCBNdWx0aXBsZSBMb2dpc3RpYyBNb2RlbApTaW5jZSBwYXJzaW1vbnkgKGhhdmluZyBhcyBsZWFzdCBhbW91bnQgb2YgdmFyaWFibGVzIGFzIHBvc3NpYmxlIHdpdGhvdXQgbG9zaW5nIHNpZ25pZmljYW50IGFjY3VyYWN5IGluIGFzc29jaWF0aW9uIGV4YW1pbmF0aW9uIG9yIHByZWRpY3Rpb24gYWNjdXJhY3kpIGlzIGFuIGltcG9ydGFudCBhc3BlY3Qgb2Ygc3RhdGlzdGljYWwgbW9kZWxpbmcsIEkgYWxzbyB0aGVuIGNob3NlIHRvIGNyZWF0ZSBhIHJlZHVjZWQgdmVyc2lvbiBvZiBteSBtdWx0aXBsZSBsb2dpc3RpYyBtb2RlbCBhYm92ZS4gSW4gdGhpcyBtb2RlbCwgSSBkaWQgbm90IGluY2x1ZGUgcHJlZGljdG9ycyB3aG9zZSBpbXBhY3Qgd2FzIHZlcnkgY2xlYXJseSBpbnNpZ25pZmljYW50IGFzIHBlciB0aGUgb3JpZ2luYWwgZnVsbCBtb2RlbCdzIHN1bW1hcnkgKGRhbmNlYWJpbGl0eSBhbmQgc3BlZWNoaW5lc3MpLiBUaGUgc3VtbWFyeSBmb3IgdGhpcyBuZXcgcmVkdWNlZCBtb2RlbCBpcyBiZWxvdy4KCmBgYHtyfQpNdWx0aXBsZV9SZWR1Y2VkX0xvZ19Nb2RlbCA9IGdsbShmb3JtdWxhID0gcG9wdWxhciB+IHRlbXBvICsgZ3JwLmluc3RydW1lbnRhbG5lc3MgKyBncnAuZHVyYXRpb25fbWlucywgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLCAKICAgIGRhdGEgPSBXb3JrX0RhdGEpCgppbnZpc2libGUoc3VtbWFyeShNdWx0aXBsZV9SZWR1Y2VkX0xvZ19Nb2RlbCkpCgpNdWx0aXBsZV9SZWR1Y2VkX0xvZ19Nb2RlbF9Db2VmX1N1bW1hcnkgPSBzdW1tYXJ5KE11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsKSRjb2VmCk11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsX0NvbmZpZGVuY2VfSW50ZXJ2YWwgPSBjb25maW50KE11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsKSAgCgpNdWx0aXBsZV9SZWR1Y2VkX1N1bW1hcnlfU3RhdHMgPSBjYmluZChNdWx0aXBsZV9SZWR1Y2VkX0xvZ19Nb2RlbF9Db2VmX1N1bW1hcnksIE11bHRpcGxlX1JlZHVjZWRfQ29uZmlkZW5jZV9JbnRlcnZhbC45NT1NdWx0aXBsZV9SZWR1Y2VkX0xvZ19Nb2RlbF9Db25maWRlbmNlX0ludGVydmFsKSAgICMgcm91bmRpbmcgb2ZmIGRlY2ltYWxzCgprYWJsZShNdWx0aXBsZV9SZWR1Y2VkX1N1bW1hcnlfU3RhdHMsY2FwdGlvbiA9ICJSZWR1Y2VkIE11bHRpcGxlIExvZ2lzdGljIFJlZ3Jlc3Npb24gTW9kZWwgU3VtbWFyeSIpIAoKYGBgCgpUaGUgcmVzdWx0cyBmcm9tIHRoaXMgbmV3IHJlZHVjZWQgbW9kZWwgbGFyZ2VseSBhbGlnbiB3aXRoIHRoZSBmaW5kaW5ncyBmcm9tIHRoZSBvcmlnaW5hbCBtdWx0aXBsZSBtb2RlbC4gSG93ZXZlciwganVzdCBhcyBvdmVyZml0dGluZyBhIG1vZGVsIHdpdGggbmVlZGxlc3MgaW5mb3JtYXRpb24gaXMgYSBwb29yIHByYWN0aWNlLCBzbyBpcyB1bmRlcmZpdHRpbmcgYSBtb2RlbCBieSBub3QgaW5jbHVkaW5nIGV2ZXJ5dGhpbmcgdGhhdCBpcyB0cnVseSBpbXBvcnRhbnQuIFRvIGVuc3VyZSB2YWxpZGl0eSBvZiB0aGlzIHJlZHVjZWQgbW9kZWwncyBzdHJ1Y3R1cmUsIGJlbG93IEkgcmFuIGF1dG9tYXRpYyBzdGVwd3dpc2Ugc2VsZWN0aW9uIHZpYSBSJ3MgQUlDIGZ1bmN0aW9uLiBUaGUgbW9kZWwncyBzdW1tYXJ5IHN0YXRpc3RpY3MgaGF2ZSBiZWVuIHByaW50ZWQuCgojIyBBbGdvcml0aG1pY2FsbHkgUmVkdWNlZCBNdWx0aXBsZSBMb2dpc3RpYyBNb2RlbApgYGB7cn0KbGlicmFyeShNQVNTKQpBSUNfTW9kZWwgPSBzdGVwQUlDKE11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsLCAKICAgICAgICAgICAgICAgICAgICAgIHNjb3BlID0gbGlzdChsb3dlcj1mb3JtdWxhKE11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsKSx1cHBlcj1mb3JtdWxhKE11bHRpcGxlX0Z1bGxfTG9nX01vZGVsKSksCiAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAiZm9yd2FyZCIsICAgIyBmb3J3YXJkIHNlbGVjdGlvbgogICAgICAgICAgICAgICAgICAgICAgdHJhY2UgPSAwICAgIyBkbyBub3Qgc2hvdyB0aGUgZGV0YWlscwogICAgICAgICAgICAgICAgICAgICAgKQoKa2FibGUoTXVsdGlwbGVfUmVkdWNlZF9TdW1tYXJ5X1N0YXRzLGNhcHRpb24gPSJBSUMtQ3JlYXRlZCBNdWx0aXBsZSBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsIFN1bW1hcnkiKQoKYGBgCgpXZSBjYW4gc2VlIGZyb20gb3VyIG1vZGVsIHN1bW1hcnkgdGhhdCB0aGUgQUlDLWNyZWF0ZWQgbW9kZWwgYW5kIHRoZSByZWR1Y2VkIG1vZGVsIEkgY29kZWQgaW4gdmlhIG1hbnVhbCB2YXJpYWJsZSBzZWxlY3Rpb24gYXJlIGlkZW50aWNhbC4gVGhpcyBpcyBub3Qgc3VycHJpc2luZyBkdWUgdG8gaG93IGNsZWFybHkgc2lnbmlmaWNhbnQgb3IgaW5zaWduaWZpY2FudCB0aGUgcHJlZGljdG9ycyB3ZXJlIGluIHRoZSBvcmlnaW5hbCBmdWxsIG1vZGVsLiBCZWxvdyBJIHdpbGwgcGVyZm9ybSBnbG9iYWwgR09GIG1lYXN1cmVzIG9uIHRoZSBtb2RlbCB0byBoYXZlIHJlY29yZCBvZiBhIGZvcm1hbCBjb21wYXJpc29uIG9mIGVhY2ggb25lJ3MgYWNjdXJhY3kuCgojIyBNb2RlbCBDb21wYXJpc29uIGFuZCBTZWxlY3Rpb24KYGBge3J9CgogIyBHT0YgRnVsbCBNdWx0aXBsZSBNb2RlbApNdWx0X0Z1bGxfUmVzaWR1YWxfRGV2aWFuY2UgPSBNdWx0aXBsZV9GdWxsX0xvZ19Nb2RlbCRkZXZpYW5jZQpNdWx0X0Z1bGxfTnVsbF9SZXNpZHVhbF9EZXZpYW5jZSA9IE11bHRpcGxlX0Z1bGxfTG9nX01vZGVsJG51bGwuZGV2aWFuY2UKTXVsdF9GdWxsX2FpYyA9IE11bHRpcGxlX0Z1bGxfTG9nX01vZGVsJGFpYwpNdWx0X0Z1bGxfR29vZG5lc3NfT2ZfRml0ID0gY2JpbmQoTXVsdF9GdWxsX1Jlc2lkdWFsX0RldmlhbmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTXVsdF9GdWxsX051bGxfUmVzaWR1YWxfRGV2aWFuY2UsIE11bHRfRnVsbF9haWMpCgogIyBHT0YgTWFudWFsbHkgUmVkdWNlZCBNdWx0aXBsZSBNb2RlbApNdWx0X1JlZHVjZWRfUmVzaWR1YWxfRGV2aWFuY2UgPSBNdWx0aXBsZV9SZWR1Y2VkX0xvZ19Nb2RlbCRkZXZpYW5jZQpNdWx0X1JlZHVjZWRfTnVsbF9SZXNpZHVhbF9EZXZpYW5jZSA9IE11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsJG51bGwuZGV2aWFuY2UKTXVsdF9SZWR1Y2VkX2FpYyA9IE11bHRpcGxlX1JlZHVjZWRfTG9nX01vZGVsJGFpYwpNdWx0X1JlZHVjZWRfR29vZG5lc3NfT2ZfRml0ID0gY2JpbmQoTXVsdF9SZWR1Y2VkX1Jlc2lkdWFsX0RldmlhbmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTXVsdF9SZWR1Y2VkX051bGxfUmVzaWR1YWxfRGV2aWFuY2UsIE11bHRfUmVkdWNlZF9haWMpCgogIyBHT0YgQUlDIFJlZHVjZWQgTW9kZWwKTXVsdF9BSUNfUmVzaWR1YWxfRGV2aWFuY2UgPSBBSUNfTW9kZWwkZGV2aWFuY2UKTXVsdF9BSUNfTnVsbF9SZXNpZHVhbF9EZXZpYW5jZSA9IEFJQ19Nb2RlbCRudWxsLmRldmlhbmNlCk11bHRfQUlDX2FpYyA9IEFJQ19Nb2RlbCRhaWMKTXVsdF9BSUNfR29vZG5lc3NfT2ZfRml0ID0gY2JpbmQoTXVsdF9BSUNfUmVzaWR1YWxfRGV2aWFuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNdWx0X0FJQ19OdWxsX1Jlc2lkdWFsX0RldmlhbmNlLCBNdWx0X0FJQ19haWMpCgpNb2RlbF9HT0ZzID0gcmJpbmQoTXVsdF9GdWxsX0dvb2RuZXNzX09mX0ZpdCwgTXVsdF9SZWR1Y2VkX0dvb2RuZXNzX09mX0ZpdCwKICAgICAgICAgICAgICAgICAgIE11bHRfQUlDX0dvb2RuZXNzX09mX0ZpdCkKcm93bmFtZXMoTW9kZWxfR09GcykgPSBjKCJGdWxsIE1vZGVsIiwgIk1hbnVhbGx5IFJlZHVjZWQgTW9kZWwiLCAiQUlDIFJlZHVjZWQgTW9kZWwiKQpjb2xuYW1lcyhNb2RlbF9HT0ZzKSA9IGMoIlJlc2lkdWFsIERldmlhbmNlIiwgIk51bGwgRGV2aWFuY2UiLCAiQUlDIikKCmthYmxlKE1vZGVsX0dPRnMsIGNhcHRpb24gPSJHT0YgU3VtbWFyeSBvZiBFYWNoIE1vZGVsIikKCgpgYGAKCkFzIHdlIGNhbiBzZWUgZnJvbSB0aGUgdGFibGUgYWJvdmUsIGFsbCB0aHJlZSBtb2RlbHMgcGVyZm9ybSBleHRyZW1lbHkgc2ltaWxhci4gU2luY2Ugb3VyIEFJQy1jcmVhdGVkIG1vZGVsIGhhcyB0aGUgbG93ZXN0IEFJQywgYW5kIGl0cyByZXNpZHVhbCBkZXZpYW5jZSBpcyBvbmx5IGEgZnJhY3Rpb24gZ3JlYXRlciB0aGFuIHRoYXQgb2Ygb3VyIGZ1bGwgbW9kZWwsIHdlIHdpbGwgYWNjZXB0IHRoZSBBSUMtY3JlYXRlZCBtb2RlbCBhcyBvdXIgZmluYWwgY2hvaWNlIHRvIHVzZSBmb3IgaW50ZXJwZXRhdGlvbiBvZiB0aGlzIGRhdGFzZXQuCgojIyBUYWtlYXdheXMgZnJvbSBNdWx0aXBsZSBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsaW5nIFByb2Nlc3MKQWZ0ZXIgdGhlIHNpbXBsZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsaW5nIHByb2Nlc3MgZWFybGllciwgd2UgY2FtZSBhd2F5IHdpdGggdGhlIGNvbmNsdXNpb24gdGhhdCBhIHRyYWNrJ3MgdGVtcG8gd2FzICd0ZWNobmljYWxseScgc2lnbmlmaWNhbnQgaW4gaXQncyBsaWtlbGlob29kIG9mIGJlaW5nIHBvcHVsYXIgb24gU3BvdGlmeSwgYnV0IHRoZSBwcmFjdGljYWwgbWFnbml0dWRlIG9mIGl0cyBpbXBhY3Qgd2FzIHNvIHNtYWxsIHRoYXQgaXQgd2FzIG5vdCBhIGZhY3RvciB0aGF0IGRlc2VydmVzIGEgZ3JlYXQgZGVhbCBvZiBlbXBoYXNpcyBpbiB0aGUgcmVhbCB3b3JsZC4gT3VyIEFJQy1jcmVhdGVkIG1vZGVsIGZvciB0aGUgbW9zdCBwYXJ0IGNvbmZpcm1zIHRoaXMgZmluZGluZywgKHAgfiAuMDU3MikuIAoKVGhlIG1vc3QgaW1wb3J0YW50IGZpbmRpbmdzIGZyb20gb3VyIG11bHRpcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gcHJvY2VzcyBjb21lIGZyb20gd2hhdCB3YXMgZGlzY292ZXJlZCBieSBvdXIgZGlzY3JldGl6ZWQgdmFyaWFibGVzLiBUcmFja3Mgd2l0aCB2ZXJ5IGhpZ2ggaW5zdHJ1bWVudGFsbmVzcyAob3ZlciAwLjcgb24gdGhpcyBkYXRhc2V0J3Mgc2NhbGUpIGhhdmUgYSBsZXNzZXIgbGlrZWxpaG9vZCBvZiBiZWluZyBwb3B1bGFyIG9uIFNwb3RpZnkgdGhhbiB0aG9zZSB0aGF0IGZhbGwgaW4gYmV0d2VlbiAwLjEgYW5kIDAuNyBvbiBzYWlkIHNjYWxlLiBBZGRpdGlvbmFsbHksIHRyYWNrcyB1bmRlciAwLjEgb24gdGhlIHNjYWxlIGFjdHVhbGx5IGhhdmUgYSBzbGlnaGx5IGhpZ2hlciBjaGFuY2Ugb2YgYmVpbmcgcG9wdWxhci4KClJlZ2FyZGluZyBhIHRyYWNrJ3MgbGVuZ3RoLCB0cmFja3MgYmVpbmcgdW5kZXIgNSBtaW51dGVzIGRvZXMgaGF2ZSBhIHNpZ25pZmljYW50IGFzc29jaWF0aW9uIHdpdGggaW5jcmVhc2VkIGxpa2VsaWhvb2Qgb2YgcG9wdWxhcml0eSB3aGVuIGNvbXBhcmVkIHRvIHRyYWNrcyByYW5naW5nIGZyb20gNSB0byAxMCBtaW51dGVzIGFuZCB0cmFja3MgYmV5b25kIDEwIG1pbnV0ZXMuIEhvd2V2ZXIsIHRoZXJlIGlzIG5vdCBzdWZmaWNpZW50IGV2aWRlbmNlIHRoYXQgdHJhY2tzIGdvaW5nIGFib3ZlIDEwIG1pbnV0ZXMgc2lnbmlmaWNhbnRseSBpbmNyZWFzZXMgb3IgcmVkdWNlcyB0aGVpciBjaGFuY2Ugb2YgYmVpbmcgcG9wdWxhciB3aGVuIGNvbXBhcmVkIHRvIHRob3NlIGluIHRoZSA1IHRvIDEwIG1pbnV0ZSBjYXRlZ29yeS4KCgpCZWxvdyBpcyBhIHZpc3VhbCBkaXNwbGF5aW5nIHRoZSBvZGRzIHJhdGlvcyBmb3IgcmVsZXZhbnQgdmFyaWFibGVzIGZyb20gbXkgQUlDLWNyZWF0ZWQgbW9kZWwsIHRoZXkgd2lsbCBiZSByZWZlcmVuY2VkIGluIG15IGZpbmFsIGNvbmNsdXNpb24uIFRoZSBleHRyZW1lIGVzdGltYXRlLCBzdGFuZGFyZCBlcnJvciBhbmQgb2RkcyByYXRpbyBmb3Igc3BlZWNoaW5lc3MgY2FuIGJlIGRpc3JlZ2FyZGVkIGFuZCBhdHRyaWJ1dGVkIGxhcmdlbHkgdG8gdGhlIHZhc3QgbWFqb3JpdHkgb2Ygb2JzZXJ2YXRpb25zIGZhbGxpbmcgYmVsb3cgMC41IG9uIHRoZSBzcGVlY2hpbmVzcyBzY2FsZS4gVGhhdCBhbG9uZyB3aXRoIHRoZSB2YXJpYWJsZSdzIGV4dHJlbWVseSBoaWdoIHAgdmFsdWUsIGFuZCBzdGFuZGFyZCBlcnJvciBiZWluZyBwcmFjdGljYWxseSBpZGVudGljYWwgdG8gdGhlIHN0YW5kYXJkIGVycm9yIG9mIHRoZSBtb2RlbCdzIG51bGwgaW50ZXJjZXB0IGxlYWQgdXMgdG8gYmVsaWV2ZSB0aGF0IHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHNwZWVjaGluZXNzIGNhbiBiZSBjaGFsa2VkIHVwIHRvIHJhbmRvbSBjaGFuY2UsIG5vdCB0cnVlIGxvZ2lzdGljIGFzc29jaWF0aW9uLgpgYGB7cn0KQUlDX01vZGVsX0NvZWZfU3VtbWFyeSA9IHN1bW1hcnkoQUlDX01vZGVsKSRjb2VmCkFJQ19PZGRzX1JhdGlvID0gZXhwKGNvZWYoQUlDX01vZGVsKSkKQUlDX291dC5zdGF0cyA9IGNiaW5kKEFJQ19Nb2RlbF9Db2VmX1N1bW1hcnksIG9kZHMucmF0aW8gPSBBSUNfT2Rkc19SYXRpbykgICAgICAgICAgICAgICAgIAprYWJsZShBSUNfb3V0LnN0YXRzLGNhcHRpb24gPSAiQUlDLUNyZWF0ZWQgTXVsdGlwbGUgUmVncmVzc2lvbiBNb2RlbCBDb2VmZmljaWVudHMgVy8gT2RkcyBSYXRpb3MiKQoKYGBgCgojIEZpbmFsIENvbmNsdXNpb24KVG8gY29uY2x1ZGUsIGluIHRoZSBtb3N0IHByYWN0aWNhbCBzZW5zZSB0aGVyZSBhcmUgdHdvIGZhY3RvcnMgdGhhdCBzZWVtIHRvIGhhdmUgdGhlIGdyZWF0ZXN0IGFzc29jaWF0aW9uIG9uIGEgdHJhY2sncyBjaGFuY2Ugb2YgYmVpbmcgcG9wdWxhciBvbiBTcG90aWZ5LiBUaG9zZSBiZWluZyBpdHMgaW5zdHJ1bWVudGFsbmVzcyBhbmQgbGVuZ3RoLiBUcmFja3MgdGhhdCBhcmUgdW5kZXIgNSBtaW51dGVzIGxvbmcgaGF2ZSBhYm91dCAqKnR3aWNlKiogdGhlIGxpa2VsaWhvb2Qgb2YgYmVpbmcgcG9wdWxhciB0aGFuIG5vdCwgd2hpbGUgdHJhY2tzIHRoYXQgYXJlIGxvbmdlciB0aGFuIDEwIG1pbnV0ZXMgZG8gbm90IGhhdmUgbmVhcmx5IGFzIGdyZWF0IGEgY2hhbmNlLiBUcmFja3MgdGhhdCBhcmUgbm90IHZlcnkgaW5zdHJ1bWVudGFsIChzIHVuZGVyIDAuMSkgYWxzbyBoYXZlIGNsb3NlIHRvIHR3aWNlIGFzIGdyZWF0IGEgY2hhbmNlIG9mIGJlaW5nIHBvcHVsYXIgdGhhbiBub3QuIE11Y2ggYmV0dGVyIG9kZHMgdGhhbiB0aGVpciB2ZXJ5IGluc3RydW1lbnRhbCAocyBvdmVyIDAuNykgYW5kIG1pbGRseSBpbnN0cnVtZW50YWwgKDAuMSA8IHMgPCAwLjcpIGNvdW50ZXJwYXJ0cy4KCgojIFJlZmVyZW5jZXM6CgpPcmlnaW5hbCBEYXRhc2V0IFNvdXJjZToKCi0gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9zb2xvbW9uYW1laC9zcG90aWZ5LW11c2ljLWRhdGFzZXQ/c2VsZWN0PWhpZ2hfcG9wdWxhcml0eV9zcG90aWZ5X2RhdGEuY3N2CgpEYXRhc2V0IERvd25sb2FkIExpbmtzIHZpYSBHaXRodWI6CgotIGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DaHJpc0IyMzIzL1NUQTMyMS9yZWZzL2hlYWRzL21haW4vaGlnaF9wb3B1bGFyaXR5X3Nwb3RpZnlfZGF0YS5jc3YKCi0gaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0NocmlzQjIzMjMvU1RBMzIxL3JlZnMvaGVhZHMvbWFpbi9sb3dfcG9wdWxhcml0eV9zcG90aWZ5X2RhdGEuY3N2Cg==