Prior Work
Since my dataset has changed since the last draft, so has my research. In Determinig how I would find research on my topic I simply googled “predicting hit songs”. To my suprise there was quite a few hits and many, if not all, were computer science related. The extent of the predictions ranged from simple varaible analysis, similar to what I am doing, to professional startups using machine learning and all the other tools to predict whether or not a song would be a hit “to an atonishing accuracy”. Also suprisingly was the fact that many of the studies used a similar dataset coming from spotify, with more extensive one using a greater amount then 100. While most of the information I found was too shallow or too deep, I understand that predictive technology like this is a frontier for buisnessess, mathematicians, and computer scientist.
https://www.digitalmusicnews.com/2018/01/31/hyperlive-hit-song-prediction-algorithm/
Title: Startup Says It Can Predict Whether a Song Will Become a Hit — With 84% Accuracy
Author: Daniel Sanchez
Year: Jan 31, 2018
Description: A company known as Hyperlive has made an algorithm based on a range of neurobiobehavioral responses to music as well as underpinning psychological processes in order to predict the success of a song.
https://towardsdatascience.com/song-popularity-predictor-1ef69735e380
Title: Song Popularity Predictor
Author: Mohamed Nasreldin
Year: May 4, 2018
Description: Using machine learning a group of students try to gauge whether the success of a song can be predicted based off past data analysis of hit songs. The students came to the conclusio that they could succesfully predict whether or not a song would be a hit to a higher degree then expected at random, but they also cite how it is not perfect and that it is much easier to predict whether or not a song will not be a hit. They list possible limitations due to dataset, cleaning of data, and lack of more variables.
https://pdfs.semanticscholar.org/e6cc/edb50d2c2b01bca108cb090943e86fb58135.pdf
Title: Predicting Hit Songs with Machine Learning
Author: MINNA REIMAN, PHILIPPA ÖRNELL
Year: May 30, 2018
Description: Two students attempt to gauge if machine learning of audio features in hit songs are good enough to predict the success of a new song based off the analysis of the same audio features. The students came to the conclusion that “results do not indicate that it is possible to pre- dict hit songs on our particular dataset.” They also go on to detail limitations of there dataset most of which stem from lack of meta data, time, or skill needed to do other optimizing tasks.
Data
Quoted Directly from Site
“Original Data Source:
The audio features for each song were extracted using the Spotify Web API and the spotipy Python library. Credit goes to Spotify for calculating the audio feature values.
Data Description: There is one .csv file in the dataset. (top2018.csv) This file includes:
Spotify URI for the song
Name of the song
Artist(s) of the song
Audio features for the song (such as danceability, tempo, key etc.)
A more detailed explanation of the audio features can be found in the Metadata tab."
Possible limatations of the dataset is the quality of subjective variable, small sample size, and the fact these top songs were “top tracks of Spotify” and may not be descriptive or inclusive of other forms of media such as youtube, cd, apple, and etc..
URL : https://www.kaggle.com/nadintamer/top-spotify-tracks-of-2018
Results
library(ggplot2)
library(dplyr)
library(gridExtra)
library(RColorBrewer)
library(corrplot)
library(ggthemes)
library(fmsb)
library(gridExtra)
library(tidyverse)
library(corrr)
library(devtools)
library(ggbiplot)
library("devtools")
library("factoextra")
base <- read.csv("top2018.csv")
base <- base[,-1]
Differentiating Groups
Rap_Songs <- base[c(1:7, 12:13, 16, 19:20, 22, 29, 31, 33, 39, 41, 43, 49, 50, 51, 54, 56, 59, 62:63, 73:77, 79, 80, 82:84, 88, 92, 95, 98),]
Edm_Songs <- base[c(8,21,32, 38, 40, 52, 57, 58, 65, 91, 97 ),]
Pop_Songs <- base[c(9,10,11,14, 15, 17, 23,24, 25, 26,27, 28, 30,34,36,37, 44, 46, 47, 48, 53, 55, 61,64, 66, 68, 69, 71, 72,78, 81,85, 87, 93, 94,96, 99,100 ),]
Latin_Songs <- base[c(18,35,42,45, 60, 67,70, 86,89,90 ),]
Rap_Songs$type <- "Rap"
Edm_Songs$type <- "Edm"
Pop_Songs$type <- "Pop"
Latin_Songs$type <- "Latin"
base_new <- rbind(Rap_Songs, Edm_Songs, Pop_Songs, Latin_Songs)
table(base_new$type)
Edm Latin Pop Rap
11 10 38 41
Correlation Matrix
corrplot(cor(base[c(3,4,6,8,9,10,11,12,13,14)]), method="color", type = "upper", col=brewer.pal(n=10, name="RdBu"),
tl.col="black",tl.srt=90, addCoef.col = "gray8", diag = T, number.cex = 0.65)
Reveals a strong positive correlation between loudness and energy of a hit song, while also highlighting a strong negative correlation between energy and acousticness of a hit song. These findings make sense as energy has a direct relationship with loudness and songs which are acoustic heavy tend to lack in energy because the use of natural sound producing instrument is generally never louder than an electric instuments. (ex: acoustic guitar vs electric guitar). Other correlations are pretty weak with most of them being significantly lower than .4.
Correlation Network
res.cor <- as.tibble(base)
res.cor2 <- res.cor %>% select(3:15)
res.cor2 %>% fashion()
res.cor2 %>% correlate() %>%
network_plot(min_cor = 0.1, color = c("firebrick", "darkturquoise"))
Correlation method: 'pearson'
Missing treated using: 'pairwise.complete.obs'
Correlation network highlights same aspects of correlation matrix with both the previous relationships mentioned in last section being the most saturated(correlated) connections.
Principal Component Analysis
mtcars.pca <- prcomp(base_new[,c(3:14)], center = TRUE,scale. = TRUE)
fviz_eig(mtcars.pca,addlabels=TRUE)
fviz_pca_ind(mtcars.pca, col.ind = base_new[,c(16)])
ggbiplot(mtcars.pca, groups = base_new[,c(16)], ellipse = true()) + theme_solarized() +
scale_color_manual(name="Variety", values=c("black", "darkseagreen", "sienna2", "blue"))
The principal components of the PCA is a lot more distibuted then other datasets I have seen. With the first and second component only accounting for about 35% of the explained variance. The genres EDM and Latin make decently defined clusters while Pop and Rap have a spread that is far too great too consider a cluster. This means that the features of EDM and Latin hit songs are very similar to one another while those of Pop and Rap origin are disimalar and have a greater variety(variance) then other groups.
- I am not for sure if this is correct because understanding of PCA is weak.
Histograms, Normal Curves, and Median of Variables
Energy
p7 <- ggplot(base, aes(x = energy), binwidth = .1) +
scale_x_continuous(name = "Energy ",
breaks = seq(.2, 1, .2),
limits=c(.2, 1)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 11, 1),
limits=c(0, 11)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"energy"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7 <- p7 + stat_function(fun=dnorm,
color="red",
args=list(mean=mean(base$energy),
sd=sd(base$energy)))
p7
summary(base[,c(4)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.2960 0.5620 0.6780 0.6591 0.7722 0.9090
Energy shows negatively skewed graph with a median energy level of about .68. Meaning most songs are energetic as a death metal bands are classified as 1 while bach would be classified as a .2.
Danceability
p7 <- ggplot(base, aes(x = danceability), binwidth = .1) +
scale_x_continuous(name = "Danceability",
breaks = seq(.2, 1, .2),
limits=c(.2, 1)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 11, 1),
limits=c(0, 11)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"danceability"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7 <- p7 + stat_function(fun=dnorm,
color="red",
args=list(mean=mean(base$danceability),
sd=sd(base$danceability)))
p7
summary(base[,c(3)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.2580 0.6355 0.7330 0.7165 0.7983 0.9640
Danceability shows negatively skewed graph with a median danceability of about .72. Meaning most songs are danceable to.
Speechiness
p7 <- ggplot(base, aes(x = speechiness), binwidth = .1) +
scale_x_continuous(name = "speechiness ",
breaks = seq(0, 1, .1),
limits=c(0, 1)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 11, 1),
limits=c(0, 11)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"speechiness"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7 <- p7 + stat_function(fun=dnorm,
color="red",
args=list(mean=mean(base$speechiness),
sd=sd(base$speechiness)))
p7
summary(base[,c(9)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000282 0.040225 0.109000 0.195701 0.247750 0.934000
Speechiness shows positively skewed graph with median of about .1. Meaning most songs have sections of speech but time spent talking is far less then instrumental time comparitevly.Values below 0.33 most likely represent music and other non-speech-like tracks.
Acousticness
p7 <- ggplot(base, aes(x = acousticness), binwidth = .1) +
scale_x_continuous(name = "acousticness ",
breaks = seq(0, 1, .1),
limits=c(0, 1)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 11, 1),
limits=c(0, 11)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"acousticness"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7 <- p7 + stat_function(fun=dnorm,
color="red",
args=list(mean=mean(base$acousticness),
sd=sd(base$acousticness)))
p7
summary(base[,c(10)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000e+00 0.000e+00 0.000e+00 1.584e-03 3.088e-05 1.340e-01
Acousticness shows positively skewed graph with a median of about .11.This makes sense as most hit songs use electric instruments to produce sound instead of acoustic one which would probably be limited to alternative, some pop, and country genres.
Key
p7 <- ggplot(base, aes(x = key), binwidth = .1) +
scale_x_continuous(name = "Key ",
breaks = seq(0, 10, 1),
limits=c(0, 10)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 20, 2),
limits=c(0, 20)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"key"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7
summary(base[,c(5)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.00 1.75 5.00 5.33 8.25 11.00
Key shows a rugged plateau graph with the most frequent key being C.
Loudness
p7 <- ggplot(base, aes(x = loudness), binwidth = .1) +
scale_x_continuous(name = "Loudness ",
breaks = seq(-10, 0, 1),
limits=c(-10, 0)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 11, 1),
limits=c(0, 11)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"loudness"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7 <- p7 + stat_function(fun=dnorm,
color="red",
args=list(mean=mean(base$loudness),
sd=sd(base$loudness)))
p7
summary(base[,c(6)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
-10.109 -6.651 -5.566 -5.678 -4.364 -2.384
Loudness has kind of a normal distributionwith median being about -5.5.
Liveness
p7 <- ggplot(base, aes(x = liveness), binwidth = .1) +
scale_x_continuous(name = "liveness ",
breaks = seq(0, 1, .1),
limits=c(0, 1)) +
scale_y_continuous(name = "Count",
breaks = seq(0, 11, 1),
limits=c(0, 11)) +
geom_histogram(fill= "black") +
theme_solarized() +
geom_vline(xintercept = median(base[,"liveness"]), size = .5, colour = "gold1",
linetype = "dashed") +
geom_density( fill = "orange")
p7 <- p7 + stat_function(fun=dnorm,
color="red",
args=list(mean=mean(base$liveness),
sd=sd(base$liveness)))
p7
summary(base[,c(11)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.02150 0.09467 0.11850 0.15830 0.17075 0.63600
Liveness shows positively skewed graph with median of about .1.Detects the presence of an audience in the recording.Most songs are not recorded live and generally do not include audience in background so liveness is really mean and median liveness is really low. Measure of how live as in audience wise the song is.
Tempo
summary(base[,c(13)])
Min. 1st Qu. Median Mean 3rd Qu. Max.
64.93 95.73 120.12 119.90 140.02 198.07
Most songs are of high tempo with over 75% of songs being andante, allegro, or presto. All of those tempos are pretty fast, especially allegro and presto.
Group Boxplots Based off Genre
ch1 <- ggplot(base_new, aes(type, danceability, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Danceability")+
theme_solarized()+
theme(legend.position = "none")
ch2 <- ggplot(base_new, aes(type, energy, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Energy")+
theme_solarized()+
theme(legend.position = "none")
ch3 <- ggplot(base_new, aes(type, loudness, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Loudness")+
theme_solarized()+
theme(legend.position = "none")
ch4 <- ggplot(base_new, aes(type, speechiness, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Speechiness")+
theme_solarized()+
theme(legend.position = "none")
grid.arrange(ch1, ch2, ch3, ch4, ncol=2)
ch5 <- ggplot(base_new, aes(type, acousticness, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Acousticness")+
theme_solarized()+
theme(legend.position = "none")
ch6 <- ggplot(base_new, aes(type, liveness, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Liveness")+
theme_solarized()+
theme(legend.position = "none")
ch7 <- ggplot(base_new, aes(type, valence, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Valence")+
theme_solarized()+
theme(legend.position = "none")
ch8 <- ggplot(base_new, aes(type, tempo, fill = type))+
geom_boxplot(outlier.size = 1.7, outlier.shape = 20, lwd = 0.8, fatten = 1.2)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "", y = "Tempo")+
theme_solarized()+
theme(legend.position = "none")
grid.arrange(ch5, ch6, ch7, ch8, ncol=2)
Median for most variables between groups tend to be the same besides large differences between Latin and other groups in areas such as valence and tempo. While most medians tend to be very similar the range of the upper and lower quartile for each genre can vary considerably in each variable. Such a case is evident in tempo, liveness, Energy, and etc..
ggplot(base_new, aes((duration_ms/1000)/60, fill = type))+
geom_density(alpha = 0.85)+
scale_fill_brewer(palette = "YlOrRd")+
labs(x = "Duration (in minutes)", y = "Destinity")+
scale_x_continuous(limits = c(0,8), breaks = seq(0,8,1))+
theme_solarized()+
theme(legend.position = c(0.8, 0.85))+
guides(fill = guide_legend(title = "Type of song"))
Most songs tend to be 3.4 minutes long besides rap which is about 3.6 minutes long. This is probably because people tend to lose focus or thing of songs longer then 3.5 minutes as being a more arduos task then listening to a quick song. I can personally atest because when I see a video longer then 4 minutes I generally consider it a long video and too long to view in a single sitting, similarly this concept applies to songs too.
Discussion
During this project I attempted to discern notable characteristics of a top hit song and determine whether or not I could predict if a song would be hit based off those characteristics. What I learned from this project is that most hit songs are relatively short, fast tempo, have little acoustics, have great energy, easily danceable too, and are of normal conversational loudness. What I also learned, or did not learn, is that being able to use data from this analysis in predicting other hit songs is currently out of my skill level but would require use of machine learning and statistical tools. Another aspect of hit songs I learned was there is a positive correlation between loudness and energy, probably because loudness is a property of energy and also, based off opinionated judgement, louder songs just tend to have more energy.
Limitations of the data included the small sample size(100), lack of more audio variables(more = better and more precise), and the lack of accounting for extraneous variables such as advertisement, artist popularity, and etc which can be influential in the success of a song.
Taking note of the previously mentioned limitations of the study the best data would be of a large sample size, have more audio variable(genre, feeling, etc..), and take into account variables such as release date, marketing, and artist popularity to more accurately predict whether a song will be a top hit. Holistically though that data would be very expensive to completely amalgamate so just having a few more audio characteristics and greater sample size would be good enough to predict whether or not a song will be hit based off auditory characteristics alone. This idea would probably be best achieved through a similar study such as the one done in my third citation regarding “Predicting Hit Songs with Machine Learning”.
In finality, the project was fun and helped introduce me to a few new packages, a few new data repositories, a few new visualization, but most importantly a greater appreciation for people like Peter and the TA’s who deal with this at a higher level in order to do learn something crazy everyday.
- Included previous discussion that was not in the previous draft you saw to show why I moved from previous dataset to this one
Maybe for better or worse this discussion reveals the weakness of my data and foresight. First I will detail the weakness of the dataset. The dataset was too simple and didn’t give enough information about attributes such as roles, genders, and participation which would’ve have allowed me to discern details of the network in a more critical manner. Because of the lack thereof such attributes the only comparisons I could make were based off the graphs of each other, random models, and what my opinion of what each network would look like based off their description ( e.g. family model would be highly connected). These comparisons would only yield “results” had there been a stark difference. Sadly, the results of my visualizations reveal no such difference and simply shows that there is a greater connectivity to the network then expected at random when compared to gnm and gmp erdos renyi models.
Second my inability to distinguish this dataset as a good model was caused by hopefulness, distraction by idea of dataset, and procrastination. Had I been more critical and more pragmatic of the possibilities of a simple undirected network with so few nodes and no attributes I would’ve realized beforehand the sheer hopelessness this data presented. Also it would’ve helped if the reference was not in a book I could not buy.
On a high note I learned some interesting facts about real networks such as online networks tend to have a lot of nodes with a few edges and a few nodes with a lot of edges. Also I have come to a better understanding of what good data looks like. Finally the killer study would still focus on what I had thought in the beginning but would overcome the downfalls I listed about the dataset and include more groups, so results could be extrapolated to wider audience.
LS0tCnRpdGxlOiAnKkZpbmFsIFByb2plY3RbMV06IENoYXJhY3RlcmlzdGljcyBvZiBhIFRvcCAxMDAgU29uZyonCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQpCeTogTGVvbiBMYXNoCgojIypQcmlvciBXb3JrKgoKU2luY2UgbXkgZGF0YXNldCBoYXMgY2hhbmdlZCBzaW5jZSB0aGUgbGFzdCBkcmFmdCwgc28gaGFzIG15IHJlc2VhcmNoLiBJbiBEZXRlcm1pbmlnIGhvdyBJIHdvdWxkIGZpbmQgcmVzZWFyY2ggb24gbXkgdG9waWMgSSBzaW1wbHkgZ29vZ2xlZCAicHJlZGljdGluZyBoaXQgc29uZ3MiLiBUbyBteSBzdXByaXNlIHRoZXJlIHdhcyBxdWl0ZSBhIGZldyBoaXRzIGFuZCBtYW55LCBpZiBub3QgYWxsLCB3ZXJlIGNvbXB1dGVyIHNjaWVuY2UgcmVsYXRlZC4gVGhlIGV4dGVudCBvZiB0aGUgcHJlZGljdGlvbnMgcmFuZ2VkIGZyb20gc2ltcGxlIHZhcmFpYmxlIGFuYWx5c2lzLCBzaW1pbGFyIHRvIHdoYXQgSSBhbSBkb2luZywgdG8gcHJvZmVzc2lvbmFsIHN0YXJ0dXBzIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgYW5kIGFsbCB0aGUgb3RoZXIgdG9vbHMgdG8gcHJlZGljdCB3aGV0aGVyIG9yIG5vdCBhIHNvbmcgd291bGQgYmUgYSBoaXQgInRvIGFuIGF0b25pc2hpbmcgYWNjdXJhY3kiLiBBbHNvIHN1cHJpc2luZ2x5IHdhcyB0aGUgZmFjdCB0aGF0IG1hbnkgb2YgdGhlIHN0dWRpZXMgdXNlZCBhIHNpbWlsYXIgZGF0YXNldCBjb21pbmcgZnJvbSBzcG90aWZ5LCB3aXRoIG1vcmUgZXh0ZW5zaXZlIG9uZSB1c2luZyBhIGdyZWF0ZXIgYW1vdW50IHRoZW4gMTAwLiBXaGlsZSBtb3N0IG9mIHRoZSBpbmZvcm1hdGlvbiBJIGZvdW5kIHdhcyB0b28gc2hhbGxvdyBvciB0b28gZGVlcCwgSSB1bmRlcnN0YW5kIHRoYXQgcHJlZGljdGl2ZSB0ZWNobm9sb2d5IGxpa2UgdGhpcyBpcyBhIGZyb250aWVyIGZvciBidWlzbmVzc2VzcywgbWF0aGVtYXRpY2lhbnMsIGFuZCBjb21wdXRlciBzY2llbnRpc3QuICAKCmh0dHBzOi8vd3d3LmRpZ2l0YWxtdXNpY25ld3MuY29tLzIwMTgvMDEvMzEvaHlwZXJsaXZlLWhpdC1zb25nLXByZWRpY3Rpb24tYWxnb3JpdGhtLwoKVGl0bGU6IFN0YXJ0dXAgU2F5cyBJdCBDYW4gUHJlZGljdCBXaGV0aGVyIGEgU29uZyBXaWxsIEJlY29tZSBhIEhpdCDigJQgV2l0aCA4NCUgQWNjdXJhY3kKCkF1dGhvcjogRGFuaWVsIFNhbmNoZXoKClllYXI6IEphbiAzMSwgMjAxOAoKRGVzY3JpcHRpb246IEEgY29tcGFueSBrbm93biBhcyBIeXBlcmxpdmUgaGFzIG1hZGUgYW4gYWxnb3JpdGhtIGJhc2VkIG9uIGEgcmFuZ2Ugb2YgbmV1cm9iaW9iZWhhdmlvcmFsIHJlc3BvbnNlcyB0byBtdXNpYyBhcyB3ZWxsIGFzIHVuZGVycGlubmluZyBwc3ljaG9sb2dpY2FsIHByb2Nlc3NlcyBpbiBvcmRlciB0byBwcmVkaWN0IHRoZSBzdWNjZXNzIG9mIGEgc29uZy4gCgpodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vc29uZy1wb3B1bGFyaXR5LXByZWRpY3Rvci0xZWY2OTczNWUzODAKClRpdGxlOiBTb25nIFBvcHVsYXJpdHkgUHJlZGljdG9yCgpBdXRob3I6IE1vaGFtZWQgTmFzcmVsZGluCgpZZWFyOiBNYXkgNCwgMjAxOAoKRGVzY3JpcHRpb246IFVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgYSBncm91cCBvZiBzdHVkZW50cyB0cnkgdG8gZ2F1Z2Ugd2hldGhlciB0aGUgc3VjY2VzcyBvZiBhIHNvbmcgY2FuIGJlIHByZWRpY3RlZCBiYXNlZCBvZmYgcGFzdCBkYXRhIGFuYWx5c2lzIG9mIGhpdCBzb25ncy4gVGhlIHN0dWRlbnRzIGNhbWUgdG8gdGhlIGNvbmNsdXNpbyB0aGF0IHRoZXkgY291bGQgc3VjY2VzZnVsbHkgcHJlZGljdCB3aGV0aGVyIG9yIG5vdCBhIHNvbmcgd291bGQgYmUgYSBoaXQgdG8gYSBoaWdoZXIgZGVncmVlIHRoZW4gZXhwZWN0ZWQgYXQgcmFuZG9tLCBidXQgdGhleSBhbHNvIGNpdGUgaG93IGl0IGlzIG5vdCBwZXJmZWN0IGFuZCB0aGF0IGl0IGlzIG11Y2ggZWFzaWVyIHRvIHByZWRpY3Qgd2hldGhlciBvciBub3QgYSBzb25nIHdpbGwgbm90IGJlIGEgaGl0LiBUaGV5IGxpc3QgcG9zc2libGUgbGltaXRhdGlvbnMgZHVlIHRvIGRhdGFzZXQsIGNsZWFuaW5nIG9mIGRhdGEsIGFuZCBsYWNrIG9mIG1vcmUgdmFyaWFibGVzLiAKCmh0dHBzOi8vcGRmcy5zZW1hbnRpY3NjaG9sYXIub3JnL2U2Y2MvZWRiNTBkMmMyYjAxYmNhMTA4Y2IwOTA5NDNlODZmYjU4MTM1LnBkZgoKVGl0bGU6IFByZWRpY3RpbmcgSGl0IFNvbmdzIHdpdGggTWFjaGluZSBMZWFybmluZwoKQXV0aG9yOiBNSU5OQSBSRUlNQU4sIFBISUxJUFBBIMOWUk5FTEwKClllYXI6IE1heSAzMCwgMjAxOAoKRGVzY3JpcHRpb246IFR3byBzdHVkZW50cyBhdHRlbXB0IHRvIGdhdWdlIGlmIG1hY2hpbmUgbGVhcm5pbmcgb2YgYXVkaW8gZmVhdHVyZXMgaW4gaGl0IHNvbmdzIGFyZSBnb29kIGVub3VnaCB0byBwcmVkaWN0IHRoZSBzdWNjZXNzIG9mIGEgbmV3IHNvbmcgYmFzZWQgb2ZmIHRoZSBhbmFseXNpcyBvZiB0aGUgc2FtZSBhdWRpbyBmZWF0dXJlcy4gVGhlIHN0dWRlbnRzIGNhbWUgdG8gdGhlIGNvbmNsdXNpb24gdGhhdCAicmVzdWx0cyBkbyBub3QgaW5kaWNhdGUgdGhhdCBpdCBpcyBwb3NzaWJsZSB0byBwcmUtIGRpY3QgaGl0IHNvbmdzIG9uIG91ciBwYXJ0aWN1bGFyIGRhdGFzZXQuIiBUaGV5IGFsc28gZ28gb24gdG8gZGV0YWlsIGxpbWl0YXRpb25zIG9mIHRoZXJlIGRhdGFzZXQgbW9zdCBvZiB3aGljaCBzdGVtIGZyb20gbGFjayBvZiBtZXRhIGRhdGEsIHRpbWUsIG9yIHNraWxsIG5lZWRlZCB0byBkbyBvdGhlciBvcHRpbWl6aW5nIHRhc2tzLgoKCgojIypJbnRyb2R1Y3Rpb24qCgpJIGFtIGFuYWx5emluZyBhIGRhdGFzZXQgZnJvbSBLYWdnbGUgdGhhdCBpcyBjb21wb3NlZCBvZiB0aGUgInRvcCAxMDAgc3BvdGlmeSB0cmFja3Mgb2YgMjAxOCIuIFRoZSBkYXRhc2V0IGluY2x1ZGVzIHRoZSB0b3AgMTAwIHNvbmdzIG9uIHNwb3RpZnkgYW5kIHZhcmlhYmxlcyByZWdhcmRpbmcgdGhlIHNvbmcgc3VjaCBhcyBkYW5jZWJpbGl0eSwgdGVtcG8sIGxpdmVuZXNzLCBhbmQgZXRjLiBUaGUgZGF0YXNldCBpcyBvZiBpbnRlcmVzdCB0byBtZSBiZWNhdXNlIEkgd2FudCB0byBzZWUgaWYgdGhlIGNoYXJhY3RlcmlzdGljcyBvZiBhIHRvcCBzb25nIHNoYXJlIGdlbmVyYWwgY2hhcmFjdGVyaXN0aWNzIHdpdGggZWFjaCBvdGhlciBhbmQgd2hldGhlciBvciBub3QgeW91IGNhbiBwcmVkaWN0IGlmIGEgc29uZyB3aWxsIGJlIGEgaGl0IGJhc2VkIG9mZiB0aG9zZSBmYWN0b3JzLiBJbiBjb21wbGV0aW5nIHRoaXMgcHJvamVjdCBJIHdhbnQgdG8gZXhwYW5kIG15IHVzZSBvZiBSIHBhY2thZ2VzIGFuZCBleHBsb3JhdGlvbiBvZiB2aXN1YWxpemF0aW9ucy4gCgoKIyMqRGF0YSoKClF1b3RlZCBEaXJlY3RseSBmcm9tIFNpdGUKCiJPcmlnaW5hbCBEYXRhIFNvdXJjZTogCgpUaGUgYXVkaW8gZmVhdHVyZXMgZm9yIGVhY2ggc29uZyB3ZXJlIGV4dHJhY3RlZCB1c2luZyB0aGUgU3BvdGlmeSBXZWIgQVBJIGFuZCB0aGUgc3BvdGlweSBQeXRob24gbGlicmFyeS4gQ3JlZGl0IGdvZXMgdG8gU3BvdGlmeSBmb3IgY2FsY3VsYXRpbmcgdGhlIGF1ZGlvIGZlYXR1cmUgdmFsdWVzLgoKRGF0YSBEZXNjcmlwdGlvbjogVGhlcmUgaXMgb25lIC5jc3YgZmlsZSBpbiB0aGUgZGF0YXNldC4gKHRvcDIwMTguY3N2KSBUaGlzIGZpbGUgaW5jbHVkZXM6CgpTcG90aWZ5IFVSSSBmb3IgdGhlIHNvbmcKCgpOYW1lIG9mIHRoZSBzb25nCgoKQXJ0aXN0KHMpIG9mIHRoZSBzb25nCgoKQXVkaW8gZmVhdHVyZXMgZm9yIHRoZSBzb25nIChzdWNoIGFzIGRhbmNlYWJpbGl0eSwgdGVtcG8sIGtleSBldGMuKQoKCkEgbW9yZSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgYXVkaW8gZmVhdHVyZXMgY2FuIGJlIGZvdW5kIGluIHRoZSBNZXRhZGF0YSB0YWIuIgoKUG9zc2libGUgbGltYXRhdGlvbnMgb2YgdGhlIGRhdGFzZXQgaXMgdGhlIHF1YWxpdHkgb2Ygc3ViamVjdGl2ZSB2YXJpYWJsZSwgc21hbGwgc2FtcGxlIHNpemUsIGFuZCB0aGUgZmFjdCB0aGVzZSB0b3Agc29uZ3Mgd2VyZSAidG9wIHRyYWNrcyBvZiBTcG90aWZ5IiBhbmQgbWF5IG5vdCBiZSBkZXNjcmlwdGl2ZSBvciBpbmNsdXNpdmUgb2Ygb3RoZXIgZm9ybXMgb2YgbWVkaWEgc3VjaCBhcyB5b3V0dWJlLCBjZCwgYXBwbGUsIGFuZCBldGMuLgoKVVJMIDogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9uYWRpbnRhbWVyL3RvcC1zcG90aWZ5LXRyYWNrcy1vZi0yMDE4CgoKCiMjKk1ldGhvZHMqCgpUaGUgbWV0aG9kcyBJIHBsYW4gdG8gdXNlIGZvciBkYXRhIGFuYWx5c2lzIGluY2x1ZGU6CgoKICAqIEhpc3RvZ3JhbXMKICArIE5vcm1hbCBDdXJ2ZSBHcmFwaHMKICArIENvcnJlbGF0aW9uIE1hdHJpeAogICsgQ29ycmVsYXRpb24gTmV0d29yawogICsgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcwogICsgQm94IFBsb3RzICAgCgoKCkFmdGVyIG9idGFpbmluZyBpbmZvIG9uIGVhY2ggc29uZy9ncm91cCwgSSB3aWxsIGNvbXBhcmUgdGhlaXIgcmVzdWx0IHdpdGggZWFjaCBvdGhlciBhbmQgY29tZSB1cCB3aXRoIGFuIGNvbmNsdXNpb24uCgoKIyMqUmVzdWx0cyoKCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoY29ycnBsb3QpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoZm1zYikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkodGlkeXZlcnNlKSAgCmxpYnJhcnkoY29ycnIpCmxpYnJhcnkoZGV2dG9vbHMpCmxpYnJhcnkoZ2diaXBsb3QpCmxpYnJhcnkoImRldnRvb2xzIikKbGlicmFyeSgiZmFjdG9leHRyYSIpCmBgYAoKYGBge3J9CmJhc2UgPC0gcmVhZC5jc3YoInRvcDIwMTguY3N2IikKYmFzZSA8LSBiYXNlWywtMV0KCgpgYGAKCiMjIyBEaWZmZXJlbnRpYXRpbmcgR3JvdXBzCmBgYHtyfQpSYXBfU29uZ3MgPC0gYmFzZVtjKDE6NywgMTI6MTMsIDE2LCAxOToyMCwgMjIsIDI5LCAzMSwgMzMsIDM5LCA0MSwgNDMsIDQ5LCA1MCwgNTEsIDU0LCA1NiwgNTksIDYyOjYzLCA3Mzo3NywgNzksICA4MCwgODI6ODQsIDg4LCA5MiwgOTUsIDk4KSxdCkVkbV9Tb25ncyA8LSBiYXNlW2MoOCwyMSwzMiwgMzgsIDQwLCA1MiwgNTcsIDU4LCA2NSwgOTEsIDk3ICApLF0KUG9wX1NvbmdzIDwtIGJhc2VbYyg5LDEwLDExLDE0LCAxNSwgMTcsIDIzLDI0LCAyNSwgMjYsMjcsIDI4LCAzMCwzNCwzNiwzNywgNDQsIDQ2LCA0NywgNDgsIDUzLCA1NSwgNjEsNjQsIDY2LCA2OCwgNjksIDcxLCA3Miw3OCwgODEsODUsIDg3LCA5MywgOTQsOTYsIDk5LDEwMCAgICksXQpMYXRpbl9Tb25ncyA8LSBiYXNlW2MoMTgsMzUsNDIsNDUsIDYwLCA2Nyw3MCwgODYsODksOTAgICksXQoKUmFwX1NvbmdzJHR5cGUgPC0gIlJhcCIKRWRtX1NvbmdzJHR5cGUgPC0gIkVkbSIKUG9wX1NvbmdzJHR5cGUgPC0gIlBvcCIKTGF0aW5fU29uZ3MkdHlwZSA8LSAiTGF0aW4iCgpiYXNlX25ldyA8LSAgcmJpbmQoUmFwX1NvbmdzLCBFZG1fU29uZ3MsIFBvcF9Tb25ncywgTGF0aW5fU29uZ3MpCnRhYmxlKGJhc2VfbmV3JHR5cGUpCmBgYAoKIyMjIENvcnJlbGF0aW9uIE1hdHJpeApgYGB7cn0KY29ycnBsb3QoY29yKGJhc2VbYygzLDQsNiw4LDksMTAsMTEsMTIsMTMsMTQpXSksIG1ldGhvZD0iY29sb3IiLCB0eXBlID0gInVwcGVyIiwgY29sPWJyZXdlci5wYWwobj0xMCwgbmFtZT0iUmRCdSIpLCAKICAgICAgICAgdGwuY29sPSJibGFjayIsdGwuc3J0PTkwLCBhZGRDb2VmLmNvbCA9ICJncmF5OCIsIGRpYWcgPSBULCBudW1iZXIuY2V4ID0gMC42NSkKYGBgClJldmVhbHMgYSBzdHJvbmcgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBsb3VkbmVzcyBhbmQgZW5lcmd5IG9mIGEgaGl0IHNvbmcsIHdoaWxlIGFsc28gaGlnaGxpZ2h0aW5nIGEgc3Ryb25nIG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gZW5lcmd5IGFuZCBhY291c3RpY25lc3Mgb2YgYSBoaXQgc29uZy4gVGhlc2UgZmluZGluZ3MgbWFrZSBzZW5zZSBhcyBlbmVyZ3kgaGFzIGEgZGlyZWN0IHJlbGF0aW9uc2hpcCB3aXRoIGxvdWRuZXNzIGFuZCBzb25ncyB3aGljaCBhcmUgYWNvdXN0aWMgaGVhdnkgdGVuZCB0byBsYWNrIGluIGVuZXJneSBiZWNhdXNlIHRoZSB1c2Ugb2YgbmF0dXJhbCBzb3VuZCBwcm9kdWNpbmcgaW5zdHJ1bWVudCBpcyBnZW5lcmFsbHkgbmV2ZXIgbG91ZGVyIHRoYW4gYW4gZWxlY3RyaWMgaW5zdHVtZW50cy4gKGV4OiBhY291c3RpYyBndWl0YXIgdnMgZWxlY3RyaWMgZ3VpdGFyKS4gT3RoZXIgY29ycmVsYXRpb25zIGFyZSBwcmV0dHkgd2VhayB3aXRoIG1vc3Qgb2YgdGhlbSBiZWluZyBzaWduaWZpY2FudGx5IGxvd2VyIHRoYW4gLjQuCgojIyMgQ29ycmVsYXRpb24gTmV0d29yawoKYGBge3J9CnJlcy5jb3IgPC0gYXMudGliYmxlKGJhc2UpCnJlcy5jb3IyIDwtIHJlcy5jb3IgJT4lIHNlbGVjdCgzOjE1KQpyZXMuY29yMiAlPiUgZmFzaGlvbigpCnJlcy5jb3IyICU+JSBjb3JyZWxhdGUoKSAlPiUgCiAgbmV0d29ya19wbG90KG1pbl9jb3IgPSAwLjEsIGNvbG9yID0gYygiZmlyZWJyaWNrIiwgImRhcmt0dXJxdW9pc2UiKSkgCmBgYApDb3JyZWxhdGlvbiBuZXR3b3JrIGhpZ2hsaWdodHMgc2FtZSBhc3BlY3RzIG9mIGNvcnJlbGF0aW9uIG1hdHJpeCB3aXRoIGJvdGggdGhlIHByZXZpb3VzIHJlbGF0aW9uc2hpcHMgbWVudGlvbmVkIGluIGxhc3Qgc2VjdGlvbiBiZWluZyB0aGUgbW9zdCBzYXR1cmF0ZWQoY29ycmVsYXRlZCkgY29ubmVjdGlvbnMuCgojIyMgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyAKCmBgYHtyfQptdGNhcnMucGNhIDwtIHByY29tcChiYXNlX25ld1ssYygzOjE0KV0sIGNlbnRlciA9IFRSVUUsc2NhbGUuID0gVFJVRSkKZnZpel9laWcobXRjYXJzLnBjYSxhZGRsYWJlbHM9VFJVRSkKZnZpel9wY2FfaW5kKG10Y2Fycy5wY2EsIGNvbC5pbmQgPSBiYXNlX25ld1ssYygxNildKQoKCmdnYmlwbG90KG10Y2Fycy5wY2EsIGdyb3VwcyA9IGJhc2VfbmV3WyxjKDE2KV0sIGVsbGlwc2UgPSB0cnVlKCkpICsgdGhlbWVfc29sYXJpemVkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPSJWYXJpZXR5IiwgdmFsdWVzPWMoImJsYWNrIiwgImRhcmtzZWFncmVlbiIsICJzaWVubmEyIiwgImJsdWUiKSkKCmBgYApUaGUgcHJpbmNpcGFsIGNvbXBvbmVudHMgb2YgdGhlIFBDQSBpcyBhIGxvdCBtb3JlIGRpc3RpYnV0ZWQgdGhlbiBvdGhlciBkYXRhc2V0cyBJIGhhdmUgc2Vlbi4gV2l0aCB0aGUgZmlyc3QgYW5kIHNlY29uZCBjb21wb25lbnQgb25seSBhY2NvdW50aW5nIGZvciBhYm91dCAzNSUgb2YgdGhlIGV4cGxhaW5lZCB2YXJpYW5jZS4gVGhlIGdlbnJlcyBFRE0gYW5kIExhdGluIG1ha2UgZGVjZW50bHkgZGVmaW5lZCBjbHVzdGVycyB3aGlsZSBQb3AgYW5kIFJhcCBoYXZlIGEgc3ByZWFkIHRoYXQgaXMgZmFyIHRvbyBncmVhdCB0b28gY29uc2lkZXIgYSBjbHVzdGVyLiBUaGlzIG1lYW5zIHRoYXQgdGhlIGZlYXR1cmVzIG9mIEVETSBhbmQgTGF0aW4gaGl0IHNvbmdzIGFyZSB2ZXJ5IHNpbWlsYXIgdG8gb25lIGFub3RoZXIgd2hpbGUgdGhvc2Ugb2YgUG9wIGFuZCBSYXAgb3JpZ2luIGFyZSBkaXNpbWFsYXIgYW5kIGhhdmUgYSBncmVhdGVyIHZhcmlldHkodmFyaWFuY2UpIHRoZW4gb3RoZXIgZ3JvdXBzLgoKKiBJIGFtIG5vdCBmb3Igc3VyZSBpZiB0aGlzIGlzIGNvcnJlY3QgYmVjYXVzZSB1bmRlcnN0YW5kaW5nIG9mIFBDQSBpcyB3ZWFrLgoKCgojIyMgSGlzdG9ncmFtcywgTm9ybWFsIEN1cnZlcywgYW5kIE1lZGlhbiBvZiBWYXJpYWJsZXMgCgoKIyMjIyNFbmVyZ3kKYGBge3J9CnA3IDwtIGdncGxvdChiYXNlLCBhZXMoeCA9IGVuZXJneSksIGJpbndpZHRoID0gLjEpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIkVuZXJneSAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoLjIsIDEsIC4yKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoLjIsIDEpKSArCiAgICAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQ291bnQiLAogICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMTEsIDEpLAogICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCAxMSkpICsKICAgICAgICBnZW9tX2hpc3RvZ3JhbShmaWxsPSAiYmxhY2siKSArCiAgICAgICAgdGhlbWVfc29sYXJpemVkKCkgKwogICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWRpYW4oYmFzZVssImVuZXJneSJdKSwgc2l6ZSA9IC41LCBjb2xvdXIgPSAiZ29sZDEiLAogICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgICsKICBnZW9tX2RlbnNpdHkoIGZpbGwgPSAib3JhbmdlIikKCnA3IDwtIHA3ICsgc3RhdF9mdW5jdGlvbihmdW49ZG5vcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj0icmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3M9bGlzdChtZWFuPW1lYW4oYmFzZSRlbmVyZ3kpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkPXNkKGJhc2UkZW5lcmd5KSkpCgoKCiAgICAgICAgCiAgICAgICAgICAKcDcKc3VtbWFyeShiYXNlWyxjKDQpXSkKYGBgCkVuZXJneSBzaG93cyBuZWdhdGl2ZWx5IHNrZXdlZCBncmFwaCB3aXRoIGEgbWVkaWFuIGVuZXJneSBsZXZlbCBvZiBhYm91dCAuNjguIE1lYW5pbmcgbW9zdCBzb25ncyBhcmUgZW5lcmdldGljIGFzIGEgZGVhdGggbWV0YWwgYmFuZHMgYXJlIGNsYXNzaWZpZWQgYXMgMSB3aGlsZSBiYWNoIHdvdWxkIGJlIGNsYXNzaWZpZWQgYXMgYSAuMi4KCiMjIyMjIERhbmNlYWJpbGl0eQoKYGBge3J9CnA3IDwtIGdncGxvdChiYXNlLCBhZXMoeCA9IGRhbmNlYWJpbGl0eSksIGJpbndpZHRoID0gLjEpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIkRhbmNlYWJpbGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSguMiwgMSwgLjIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YyguMiwgMSkpICsKICAgICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJDb3VudCIsCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxMSwgMSksCiAgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsIDExKSkgKwogICAgICAgIGdlb21faGlzdG9ncmFtKGZpbGw9ICJibGFjayIpICsKICAgICAgICB0aGVtZV9zb2xhcml6ZWQoKSArCiAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lZGlhbihiYXNlWywiZGFuY2VhYmlsaXR5Il0pLCBzaXplID0gLjUsIGNvbG91ciA9ICJnb2xkMSIsCiAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9kZW5zaXR5KCBmaWxsID0gIm9yYW5nZSIpCgpwNyA8LSBwNyArIHN0YXRfZnVuY3Rpb24oZnVuPWRub3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9InJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzPWxpc3QobWVhbj1tZWFuKGJhc2UkZGFuY2VhYmlsaXR5KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZD1zZChiYXNlJGRhbmNlYWJpbGl0eSkpKSAKCgogICAgICAgIAogICAgICAgICAgCnA3CnN1bW1hcnkoYmFzZVssYygzKV0pCmBgYApEYW5jZWFiaWxpdHkgc2hvd3MgbmVnYXRpdmVseSBza2V3ZWQgZ3JhcGggd2l0aCBhIG1lZGlhbiBkYW5jZWFiaWxpdHkgb2YgYWJvdXQgLjcyLiBNZWFuaW5nIG1vc3Qgc29uZ3MgYXJlIGRhbmNlYWJsZSB0by4KCiMjIyMjIFNwZWVjaGluZXNzCgoKYGBge3J9CnA3IDwtIGdncGxvdChiYXNlLCBhZXMoeCA9IHNwZWVjaGluZXNzKSwgYmlud2lkdGggPSAuMSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAic3BlZWNoaW5lc3MgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIC4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgMSkpICsKICAgICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJDb3VudCIsCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxMSwgMSksCiAgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsIDExKSkgKwogICAgICAgIGdlb21faGlzdG9ncmFtKGZpbGw9ICJibGFjayIpICsKICAgICAgICB0aGVtZV9zb2xhcml6ZWQoKSArCiAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lZGlhbihiYXNlWywic3BlZWNoaW5lc3MiXSksIHNpemUgPSAuNSwgY29sb3VyID0gImdvbGQxIiwKICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2RlbnNpdHkoIGZpbGwgPSAib3JhbmdlIikKCnA3IDwtIHA3ICsgc3RhdF9mdW5jdGlvbihmdW49ZG5vcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj0icmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3M9bGlzdChtZWFuPW1lYW4oYmFzZSRzcGVlY2hpbmVzcyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Q9c2QoYmFzZSRzcGVlY2hpbmVzcykpKQoKCiAgICAgICAgCiAgICAgICAgICAKcDcKc3VtbWFyeShiYXNlWyxjKDkpXSkKYGBgClNwZWVjaGluZXNzIHNob3dzIHBvc2l0aXZlbHkgc2tld2VkIGdyYXBoIHdpdGggbWVkaWFuIG9mIGFib3V0IC4xLiBNZWFuaW5nIG1vc3Qgc29uZ3MgaGF2ZSBzZWN0aW9ucyBvZiBzcGVlY2ggYnV0IHRpbWUgc3BlbnQgdGFsa2luZyBpcyBmYXIgbGVzcyB0aGVuIGluc3RydW1lbnRhbCB0aW1lIGNvbXBhcml0ZXZseS5WYWx1ZXMgYmVsb3cgMC4zMyBtb3N0IGxpa2VseSByZXByZXNlbnQgbXVzaWMgYW5kIG90aGVyIG5vbi1zcGVlY2gtbGlrZSB0cmFja3MuCgojIyMjIyBBY291c3RpY25lc3MKCgoKYGBge3J9CnA3IDwtIGdncGxvdChiYXNlLCBhZXMoeCA9IGFjb3VzdGljbmVzcyksIGJpbndpZHRoID0gLjEpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gImFjb3VzdGljbmVzcyAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCAxKSkgKwogICAgIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkNvdW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDExLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgMTEpKSArCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oZmlsbD0gImJsYWNrIikgKwogICAgICAgIHRoZW1lX3NvbGFyaXplZCgpICsKICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVkaWFuKGJhc2VbLCJhY291c3RpY25lc3MiXSksIHNpemUgPSAuNSwgY29sb3VyID0gImdvbGQxIiwKICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2RlbnNpdHkoIGZpbGwgPSAib3JhbmdlIikKCnA3IDwtIHA3ICsgc3RhdF9mdW5jdGlvbihmdW49ZG5vcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj0icmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3M9bGlzdChtZWFuPW1lYW4oYmFzZSRhY291c3RpY25lc3MpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkPXNkKGJhc2UkYWNvdXN0aWNuZXNzKSkpCgoKICAgICAgICAKICAgICAgICAgIApwNwpzdW1tYXJ5KGJhc2VbLGMoMTApXSkKYGBgCkFjb3VzdGljbmVzcyBzaG93cyBwb3NpdGl2ZWx5IHNrZXdlZCBncmFwaCB3aXRoIGEgbWVkaWFuIG9mIGFib3V0IC4xMS5UaGlzIG1ha2VzIHNlbnNlIGFzIG1vc3QgaGl0IHNvbmdzIHVzZSBlbGVjdHJpYyBpbnN0cnVtZW50cyB0byBwcm9kdWNlIHNvdW5kIGluc3RlYWQgb2YgYWNvdXN0aWMgb25lIHdoaWNoIHdvdWxkIHByb2JhYmx5IGJlIGxpbWl0ZWQgdG8gYWx0ZXJuYXRpdmUsIHNvbWUgcG9wLCBhbmQgY291bnRyeSBnZW5yZXMuCgoKIyMjIyMgS2V5CgoKCmBgYHtyfQpwNyA8LSBnZ3Bsb3QoYmFzZSwgYWVzKHggPSBrZXkpLCBiaW53aWR0aCA9IC4xKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJLZXkgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEwLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgMTApKSArCiAgICAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiQ291bnQiLAogICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMjAsIDIpLAogICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCAyMCkpICsKICAgICAgICBnZW9tX2hpc3RvZ3JhbShmaWxsPSAiYmxhY2siKSArCiAgICAgICAgdGhlbWVfc29sYXJpemVkKCkgKwogICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWRpYW4oYmFzZVssImtleSJdKSwgc2l6ZSA9IC41LCBjb2xvdXIgPSAiZ29sZDEiLAogICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fZGVuc2l0eSggZmlsbCA9ICJvcmFuZ2UiKQoKCgogICAgICAgIAogICAgICAgICAgCnA3CnN1bW1hcnkoYmFzZVssYyg1KV0pCmBgYApLZXkgc2hvd3MgYSBydWdnZWQgcGxhdGVhdSBncmFwaCB3aXRoIHRoZSBtb3N0IGZyZXF1ZW50IGtleSBiZWluZyBDLgoKIyMjIyNMb3VkbmVzcwpgYGB7cn0KcDcgPC0gZ2dwbG90KGJhc2UsIGFlcyh4ID0gbG91ZG5lc3MpLCBiaW53aWR0aCA9IC4xKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJMb3VkbmVzcyAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoLTEwLCAwLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoLTEwLCAwKSkgKwogICAgIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkNvdW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDExLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgMTEpKSArCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oZmlsbD0gImJsYWNrIikgKwogICAgICAgIHRoZW1lX3NvbGFyaXplZCgpICsKICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVkaWFuKGJhc2VbLCJsb3VkbmVzcyJdKSwgc2l6ZSA9IC41LCBjb2xvdXIgPSAiZ29sZDEiLAogICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fZGVuc2l0eSggZmlsbCA9ICJvcmFuZ2UiKQpwNyA8LSBwNyArIHN0YXRfZnVuY3Rpb24oZnVuPWRub3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9InJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzPWxpc3QobWVhbj1tZWFuKGJhc2UkbG91ZG5lc3MpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkPXNkKGJhc2UkbG91ZG5lc3MpKSkKCgpwNwpzdW1tYXJ5KGJhc2VbLGMoNildKQpgYGAKTG91ZG5lc3MgaGFzIGtpbmQgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9ud2l0aCBtZWRpYW4gYmVpbmcgYWJvdXQgLTUuNS4KCgoKIyMjIyNMaXZlbmVzcwpgYGB7cn0KcDcgPC0gZ2dwbG90KGJhc2UsIGFlcyh4ID0gbGl2ZW5lc3MpLCBiaW53aWR0aCA9IC4xKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJsaXZlbmVzcyAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCAxKSkgKwogICAgIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIkNvdW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDExLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgMTEpKSArCiAgICAgICAgZ2VvbV9oaXN0b2dyYW0oZmlsbD0gImJsYWNrIikgKwogICAgICAgIHRoZW1lX3NvbGFyaXplZCgpICsKICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVkaWFuKGJhc2VbLCJsaXZlbmVzcyJdKSwgc2l6ZSA9IC41LCBjb2xvdXIgPSAiZ29sZDEiLAogICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fZGVuc2l0eSggZmlsbCA9ICJvcmFuZ2UiKQoKcDcgPC0gcDcgKyBzdGF0X2Z1bmN0aW9uKGZ1bj1kbm9ybSwKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPSJyZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgYXJncz1saXN0KG1lYW49bWVhbihiYXNlJGxpdmVuZXNzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZD1zZChiYXNlJGxpdmVuZXNzKSkpCgoKICAgICAgICAKICAgICAgICAgIApwNwpzdW1tYXJ5KGJhc2VbLGMoMTEpXSkKYGBgCkxpdmVuZXNzIHNob3dzIHBvc2l0aXZlbHkgc2tld2VkIGdyYXBoIHdpdGggbWVkaWFuIG9mIGFib3V0IC4xLkRldGVjdHMgdGhlIHByZXNlbmNlIG9mIGFuIGF1ZGllbmNlIGluIHRoZSByZWNvcmRpbmcuTW9zdCBzb25ncyBhcmUgbm90IHJlY29yZGVkIGxpdmUgYW5kIGdlbmVyYWxseSBkbyBub3QgaW5jbHVkZSBhdWRpZW5jZSBpbiBiYWNrZ3JvdW5kIHNvIGxpdmVuZXNzIGlzIHJlYWxseSBtZWFuIGFuZCBtZWRpYW4gbGl2ZW5lc3MgaXMgcmVhbGx5IGxvdy4gTWVhc3VyZSBvZiBob3cgbGl2ZSBhcyBpbiBhdWRpZW5jZSB3aXNlIHRoZSBzb25nIGlzLgoKIyMjIyBUZW1wbwpgYGB7cn0Kc3VtbWFyeShiYXNlWyxjKDEzKV0pCmBgYApNb3N0IHNvbmdzIGFyZSBvZiBoaWdoIHRlbXBvIHdpdGggb3ZlciA3NSUgb2Ygc29uZ3MgYmVpbmcgYW5kYW50ZSwgYWxsZWdybywgb3IgcHJlc3RvLiBBbGwgb2YgdGhvc2UgdGVtcG9zIGFyZSBwcmV0dHkgZmFzdCwgZXNwZWNpYWxseSBhbGxlZ3JvIGFuZCBwcmVzdG8uCgoKIyMjIEdyb3VwIEJveHBsb3RzIEJhc2VkIG9mZiBHZW5yZQpgYGB7cn0KY2gxIDwtIGdncGxvdChiYXNlX25ldywgYWVzKHR5cGUsIGRhbmNlYWJpbGl0eSwgZmlsbCA9IHR5cGUpKSsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplID0gMS43LCBvdXRsaWVyLnNoYXBlID0gMjAsIGx3ZCA9IDAuOCwgZmF0dGVuID0gMS4yKSsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIllsT3JSZCIpKwogIGxhYnMoeCA9ICIiLCB5ID0gIkRhbmNlYWJpbGl0eSIpKwogIHRoZW1lX3NvbGFyaXplZCgpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmNoMiA8LSBnZ3Bsb3QoYmFzZV9uZXcsIGFlcyh0eXBlLCBlbmVyZ3ksIGZpbGwgPSB0eXBlKSkrCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDEuNywgb3V0bGllci5zaGFwZSA9IDIwLCBsd2QgPSAwLjgsIGZhdHRlbiA9IDEuMikrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJZbE9yUmQiKSsKICBsYWJzKHggPSAiIiwgeSA9ICJFbmVyZ3kiKSsKICB0aGVtZV9zb2xhcml6ZWQoKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpjaDMgPC0gZ2dwbG90KGJhc2VfbmV3LCBhZXModHlwZSwgbG91ZG5lc3MsIGZpbGwgPSB0eXBlKSkrCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDEuNywgb3V0bGllci5zaGFwZSA9IDIwLCBsd2QgPSAwLjgsIGZhdHRlbiA9IDEuMikrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJZbE9yUmQiKSsKICBsYWJzKHggPSAiIiwgeSA9ICJMb3VkbmVzcyIpKwogIHRoZW1lX3NvbGFyaXplZCgpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmNoNCA8LSBnZ3Bsb3QoYmFzZV9uZXcsIGFlcyh0eXBlLCBzcGVlY2hpbmVzcywgZmlsbCA9IHR5cGUpKSsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplID0gMS43LCBvdXRsaWVyLnNoYXBlID0gMjAsIGx3ZCA9IDAuOCwgZmF0dGVuID0gMS4yKSsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIllsT3JSZCIpKwogIGxhYnMoeCA9ICIiLCB5ID0gIlNwZWVjaGluZXNzIikrCiAgdGhlbWVfc29sYXJpemVkKCkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ3JpZC5hcnJhbmdlKGNoMSwgY2gyLCBjaDMsIGNoNCwgbmNvbD0yKQpgYGAKCmBgYHtyfQpjaDUgPC0gZ2dwbG90KGJhc2VfbmV3LCBhZXModHlwZSwgYWNvdXN0aWNuZXNzLCBmaWxsID0gdHlwZSkpKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAxLjcsIG91dGxpZXIuc2hhcGUgPSAyMCwgbHdkID0gMC44LCBmYXR0ZW4gPSAxLjIpKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiWWxPclJkIikrCiAgbGFicyh4ID0gIiIsIHkgPSAiQWNvdXN0aWNuZXNzIikrCiAgdGhlbWVfc29sYXJpemVkKCkrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKY2g2IDwtIGdncGxvdChiYXNlX25ldywgYWVzKHR5cGUsIGxpdmVuZXNzLCBmaWxsID0gdHlwZSkpKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAxLjcsIG91dGxpZXIuc2hhcGUgPSAyMCwgbHdkID0gMC44LCBmYXR0ZW4gPSAxLjIpKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiWWxPclJkIikrCiAgbGFicyh4ID0gIiIsIHkgPSAiTGl2ZW5lc3MiKSsKICB0aGVtZV9zb2xhcml6ZWQoKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpjaDcgPC0gZ2dwbG90KGJhc2VfbmV3LCBhZXModHlwZSwgdmFsZW5jZSwgZmlsbCA9IHR5cGUpKSsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplID0gMS43LCBvdXRsaWVyLnNoYXBlID0gMjAsIGx3ZCA9IDAuOCwgZmF0dGVuID0gMS4yKSsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIllsT3JSZCIpKwogIGxhYnMoeCA9ICIiLCB5ID0gIlZhbGVuY2UiKSsKICB0aGVtZV9zb2xhcml6ZWQoKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpjaDggPC0gZ2dwbG90KGJhc2VfbmV3LCBhZXModHlwZSwgdGVtcG8sIGZpbGwgPSB0eXBlKSkrCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDEuNywgb3V0bGllci5zaGFwZSA9IDIwLCBsd2QgPSAwLjgsIGZhdHRlbiA9IDEuMikrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJZbE9yUmQiKSsKICBsYWJzKHggPSAiIiwgeSA9ICJUZW1wbyIpKwogIHRoZW1lX3NvbGFyaXplZCgpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmdyaWQuYXJyYW5nZShjaDUsIGNoNiwgY2g3LCBjaDgsIG5jb2w9MikKYGBgCk1lZGlhbiBmb3IgbW9zdCB2YXJpYWJsZXMgYmV0d2VlbiBncm91cHMgdGVuZCB0byBiZSB0aGUgc2FtZSBiZXNpZGVzIGxhcmdlIGRpZmZlcmVuY2VzIGJldHdlZW4gTGF0aW4gYW5kIG90aGVyIGdyb3VwcyBpbiBhcmVhcyBzdWNoIGFzIHZhbGVuY2UgYW5kIHRlbXBvLiBXaGlsZSBtb3N0IG1lZGlhbnMgdGVuZCB0byBiZSB2ZXJ5IHNpbWlsYXIgdGhlIHJhbmdlIG9mIHRoZSB1cHBlciBhbmQgbG93ZXIgcXVhcnRpbGUgZm9yIGVhY2ggZ2VucmUgY2FuIHZhcnkgY29uc2lkZXJhYmx5IGluIGVhY2ggdmFyaWFibGUuIFN1Y2ggYSBjYXNlIGlzIGV2aWRlbnQgaW4gdGVtcG8sIGxpdmVuZXNzLCBFbmVyZ3ksIGFuZCBldGMuLgoKYGBge3J9CmdncGxvdChiYXNlX25ldywgYWVzKChkdXJhdGlvbl9tcy8xMDAwKS82MCwgZmlsbCA9IHR5cGUpKSsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjg1KSsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIllsT3JSZCIpKwogIGxhYnMoeCA9ICJEdXJhdGlvbiAoaW4gbWludXRlcykiLCB5ID0gIkRlc3Rpbml0eSIpKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsOCksIGJyZWFrcyA9IHNlcSgwLDgsMSkpKwogIHRoZW1lX3NvbGFyaXplZCgpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjg1KSkrCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiVHlwZSBvZiBzb25nIikpCgpgYGAKCk1vc3Qgc29uZ3MgdGVuZCB0byBiZSAzLjQgbWludXRlcyBsb25nIGJlc2lkZXMgcmFwIHdoaWNoIGlzIGFib3V0IDMuNiBtaW51dGVzIGxvbmcuIFRoaXMgaXMgcHJvYmFibHkgYmVjYXVzZSBwZW9wbGUgdGVuZCB0byBsb3NlIGZvY3VzIG9yIHRoaW5nIG9mIHNvbmdzIGxvbmdlciB0aGVuIDMuNSBtaW51dGVzIGFzIGJlaW5nIGEgbW9yZSBhcmR1b3MgdGFzayB0aGVuIGxpc3RlbmluZyB0byBhIHF1aWNrIHNvbmcuIEkgY2FuIHBlcnNvbmFsbHkgYXRlc3QgYmVjYXVzZSB3aGVuIEkgc2VlIGEgdmlkZW8gbG9uZ2VyIHRoZW4gNCBtaW51dGVzIEkgZ2VuZXJhbGx5IGNvbnNpZGVyIGl0IGEgbG9uZyB2aWRlbyBhbmQgdG9vIGxvbmcgdG8gdmlldyBpbiBhIHNpbmdsZSBzaXR0aW5nLCBzaW1pbGFybHkgdGhpcyBjb25jZXB0IGFwcGxpZXMgdG8gc29uZ3MgdG9vLiAKCgoKCiMjKkRpc2N1c3Npb24qCgoKRHVyaW5nIHRoaXMgcHJvamVjdCBJIGF0dGVtcHRlZCB0byBkaXNjZXJuIG5vdGFibGUgY2hhcmFjdGVyaXN0aWNzIG9mIGEgdG9wIGhpdCBzb25nIGFuZCBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgSSBjb3VsZCBwcmVkaWN0IGlmIGEgc29uZyB3b3VsZCBiZSBoaXQgYmFzZWQgb2ZmIHRob3NlIGNoYXJhY3RlcmlzdGljcy4gV2hhdCBJIGxlYXJuZWQgZnJvbSB0aGlzIHByb2plY3QgaXMgdGhhdCBtb3N0IGhpdCBzb25ncyBhcmUgcmVsYXRpdmVseSBzaG9ydCwgZmFzdCB0ZW1wbywgaGF2ZSBsaXR0bGUgYWNvdXN0aWNzLCBoYXZlIGdyZWF0IGVuZXJneSwgZWFzaWx5IGRhbmNlYWJsZSB0b28sIGFuZCBhcmUgb2Ygbm9ybWFsIGNvbnZlcnNhdGlvbmFsIGxvdWRuZXNzLiAKV2hhdCBJIGFsc28gbGVhcm5lZCwgb3IgZGlkIG5vdCBsZWFybiwgaXMgdGhhdCBiZWluZyBhYmxlIHRvIHVzZSBkYXRhIGZyb20gdGhpcyBhbmFseXNpcyBpbiBwcmVkaWN0aW5nIG90aGVyIGhpdCBzb25ncyBpcyBjdXJyZW50bHkgb3V0IG9mIG15IHNraWxsIGxldmVsIGJ1dCB3b3VsZCByZXF1aXJlIHVzZSBvZiBtYWNoaW5lIGxlYXJuaW5nIGFuZCBzdGF0aXN0aWNhbCB0b29scy4gQW5vdGhlciBhc3BlY3Qgb2YgaGl0IHNvbmdzIEkgbGVhcm5lZCB3YXMgdGhlcmUgaXMgYSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxvdWRuZXNzIGFuZCBlbmVyZ3ksIHByb2JhYmx5IGJlY2F1c2UgbG91ZG5lc3MgaXMgYSBwcm9wZXJ0eSBvZiBlbmVyZ3kgYW5kIGFsc28sIGJhc2VkIG9mZiBvcGluaW9uYXRlZCBqdWRnZW1lbnQsIGxvdWRlciBzb25ncyBqdXN0IHRlbmQgdG8gaGF2ZSBtb3JlIGVuZXJneS4gCgpMaW1pdGF0aW9ucyBvZiB0aGUgZGF0YSBpbmNsdWRlZCB0aGUgc21hbGwgc2FtcGxlIHNpemUoMTAwKSwgbGFjayBvZiBtb3JlIGF1ZGlvIHZhcmlhYmxlcyhtb3JlID0gYmV0dGVyIGFuZCBtb3JlIHByZWNpc2UpLCBhbmQgdGhlIGxhY2sgb2YgYWNjb3VudGluZyBmb3IgZXh0cmFuZW91cyB2YXJpYWJsZXMgc3VjaCBhcyBhZHZlcnRpc2VtZW50LCBhcnRpc3QgcG9wdWxhcml0eSwgYW5kIGV0YyB3aGljaCBjYW4gYmUgaW5mbHVlbnRpYWwgaW4gdGhlIHN1Y2Nlc3Mgb2YgYSBzb25nLiAKClRha2luZyBub3RlIG9mIHRoZSBwcmV2aW91c2x5IG1lbnRpb25lZCBsaW1pdGF0aW9ucyBvZiB0aGUgc3R1ZHkgdGhlIGJlc3QgZGF0YSB3b3VsZCBiZSBvZiBhIGxhcmdlIHNhbXBsZSBzaXplLCBoYXZlIG1vcmUgYXVkaW8gdmFyaWFibGUoZ2VucmUsIGZlZWxpbmcsIGV0Yy4uKSwgYW5kIHRha2UgaW50byBhY2NvdW50IHZhcmlhYmxlcyBzdWNoIGFzIHJlbGVhc2UgZGF0ZSwgbWFya2V0aW5nLCBhbmQgYXJ0aXN0IHBvcHVsYXJpdHkgdG8gbW9yZSBhY2N1cmF0ZWx5IHByZWRpY3Qgd2hldGhlciBhIHNvbmcgd2lsbCBiZSBhIHRvcCBoaXQuIEhvbGlzdGljYWxseSB0aG91Z2ggdGhhdCBkYXRhIHdvdWxkIGJlIHZlcnkgZXhwZW5zaXZlIHRvIGNvbXBsZXRlbHkgYW1hbGdhbWF0ZSBzbyBqdXN0IGhhdmluZyBhIGZldyBtb3JlIGF1ZGlvIGNoYXJhY3RlcmlzdGljcyBhbmQgIGdyZWF0ZXIgc2FtcGxlIHNpemUgd291bGQgYmUgZ29vZCBlbm91Z2ggdG8gcHJlZGljdCB3aGV0aGVyIG9yIG5vdCBhIHNvbmcgd2lsbCBiZSBoaXQgYmFzZWQgb2ZmIGF1ZGl0b3J5IGNoYXJhY3RlcmlzdGljcyBhbG9uZS4gVGhpcyBpZGVhIHdvdWxkIHByb2JhYmx5IGJlIGJlc3QgYWNoaWV2ZWQgdGhyb3VnaCBhIHNpbWlsYXIgc3R1ZHkgc3VjaCBhcyB0aGUgb25lIGRvbmUgaW4gbXkgdGhpcmQgY2l0YXRpb24gcmVnYXJkaW5nIOKAnFByZWRpY3RpbmcgSGl0IFNvbmdzIHdpdGggTWFjaGluZSBMZWFybmluZ+KAnS4gCgpJbiBmaW5hbGl0eSwgdGhlIHByb2plY3Qgd2FzIGZ1biBhbmQgaGVscGVkIGludHJvZHVjZSBtZSB0byBhIGZldyBuZXcgcGFja2FnZXMsIGEgZmV3IG5ldyBkYXRhIHJlcG9zaXRvcmllcywgYSBmZXcgbmV3IHZpc3VhbGl6YXRpb24sIGJ1dCBtb3N0IGltcG9ydGFudGx5IGEgZ3JlYXRlciBhcHByZWNpYXRpb24gZm9yIHBlb3BsZSBsaWtlIFBldGVyIGFuZCB0aGUgVEHigJlzIHdobyBkZWFsIHdpdGggdGhpcyBhdCBhIGhpZ2hlciBsZXZlbCBpbiBvcmRlciB0byBkbyBsZWFybiBzb21ldGhpbmcgY3JhenkgZXZlcnlkYXkuCgoKKiBJbmNsdWRlZCBwcmV2aW91cyBkaXNjdXNzaW9uIHRoYXQgd2FzIG5vdCBpbiB0aGUgcHJldmlvdXMgZHJhZnQgeW91IHNhdyB0byBzaG93IHdoeSBJIG1vdmVkIGZyb20gcHJldmlvdXMgZGF0YXNldCB0byB0aGlzIG9uZSAKCk1heWJlIGZvciBiZXR0ZXIgb3Igd29yc2UgdGhpcyBkaXNjdXNzaW9uIHJldmVhbHMgdGhlIHdlYWtuZXNzIG9mIG15IGRhdGEgYW5kIGZvcmVzaWdodC4gRmlyc3QgSSB3aWxsIGRldGFpbCB0aGUgd2Vha25lc3Mgb2YgdGhlIGRhdGFzZXQuIFRoZSBkYXRhc2V0IHdhcyB0b28gc2ltcGxlIGFuZCBkaWRu4oCZdCBnaXZlIGVub3VnaCBpbmZvcm1hdGlvbiBhYm91dCBhdHRyaWJ1dGVzIHN1Y2ggYXMgcm9sZXMsIGdlbmRlcnMsIGFuZCBwYXJ0aWNpcGF0aW9uIHdoaWNoIHdvdWxk4oCZdmUgaGF2ZSBhbGxvd2VkIG1lIHRvIGRpc2Nlcm4gZGV0YWlscyBvZiB0aGUgbmV0d29yayBpbiBhIG1vcmUgY3JpdGljYWwgbWFubmVyLiBCZWNhdXNlIG9mIHRoZSBsYWNrIHRoZXJlb2Ygc3VjaCBhdHRyaWJ1dGVzIHRoZSBvbmx5IGNvbXBhcmlzb25zIEkgY291bGQgbWFrZSB3ZXJlIGJhc2VkIG9mZiB0aGUgZ3JhcGhzIG9mIGVhY2ggb3RoZXIsIHJhbmRvbSBtb2RlbHMsIGFuZCB3aGF0IG15IG9waW5pb24gb2Ygd2hhdCBlYWNoIG5ldHdvcmsgd291bGQgbG9vayBsaWtlIGJhc2VkIG9mZiB0aGVpciBkZXNjcmlwdGlvbiAoIGUuZy4gZmFtaWx5IG1vZGVsIHdvdWxkIGJlIGhpZ2hseSBjb25uZWN0ZWQpLiBUaGVzZSBjb21wYXJpc29ucyB3b3VsZCBvbmx5IHlpZWxkIOKAnHJlc3VsdHPigJ0gaGFkIHRoZXJlIGJlZW4gYSBzdGFyayBkaWZmZXJlbmNlLiBTYWRseSwgdGhlIHJlc3VsdHMgb2YgbXkgdmlzdWFsaXphdGlvbnMgcmV2ZWFsIG5vIHN1Y2ggZGlmZmVyZW5jZSBhbmQgc2ltcGx5IHNob3dzIHRoYXQgdGhlcmUgaXMgYSBncmVhdGVyIGNvbm5lY3Rpdml0eSB0byB0aGUgbmV0d29yayB0aGVuIGV4cGVjdGVkIGF0IHJhbmRvbSB3aGVuIGNvbXBhcmVkIHRvIGdubSBhbmQgZ21wIGVyZG9zIHJlbnlpIG1vZGVscy4KClNlY29uZCBteSBpbmFiaWxpdHkgdG8gZGlzdGluZ3Vpc2ggdGhpcyBkYXRhc2V0IGFzIGEgZ29vZCBtb2RlbCB3YXMgY2F1c2VkIGJ5IGhvcGVmdWxuZXNzLCBkaXN0cmFjdGlvbiBieSBpZGVhIG9mIGRhdGFzZXQsIGFuZCBwcm9jcmFzdGluYXRpb24uIEhhZCBJIGJlZW4gbW9yZSBjcml0aWNhbCBhbmQgbW9yZSBwcmFnbWF0aWMgb2YgdGhlIHBvc3NpYmlsaXRpZXMgb2YgYSBzaW1wbGUgdW5kaXJlY3RlZCBuZXR3b3JrIHdpdGggc28gZmV3IG5vZGVzIGFuZCBubyBhdHRyaWJ1dGVzIEkgd291bGTigJl2ZSByZWFsaXplZCBiZWZvcmVoYW5kIHRoZSBzaGVlciBob3BlbGVzc25lc3MgdGhpcyBkYXRhIHByZXNlbnRlZC4gQWxzbyBpdCB3b3VsZOKAmXZlIGhlbHBlZCBpZiB0aGUgcmVmZXJlbmNlIHdhcyBub3QgaW4gYSBib29rIEkgY291bGQgbm90IGJ1eS4KCk9uIGEgaGlnaCBub3RlIEkgbGVhcm5lZCBzb21lIGludGVyZXN0aW5nIGZhY3RzIGFib3V0IHJlYWwgbmV0d29ya3Mgc3VjaCBhcyBvbmxpbmUgbmV0d29ya3MgdGVuZCB0byBoYXZlIGEgbG90IG9mIG5vZGVzIHdpdGggYSBmZXcgZWRnZXMgYW5kIGEgZmV3IG5vZGVzIHdpdGggYSBsb3Qgb2YgZWRnZXMuIEFsc28gSSBoYXZlIGNvbWUgdG8gYSBiZXR0ZXIgdW5kZXJzdGFuZGluZyBvZiB3aGF0IGdvb2QgZGF0YSBsb29rcyBsaWtlLiBGaW5hbGx5IHRoZSBraWxsZXIgc3R1ZHkgd291bGQgc3RpbGwgZm9jdXMgb24gd2hhdCBJIGhhZCB0aG91Z2h0IGluIHRoZSBiZWdpbm5pbmcgYnV0IHdvdWxkIG92ZXJjb21lIHRoZSBkb3duZmFsbHMgSSBsaXN0ZWQgYWJvdXQgdGhlICBkYXRhc2V0IGFuZCBpbmNsdWRlIG1vcmUgZ3JvdXBzLCBzbyByZXN1bHRzIGNvdWxkIGJlIGV4dHJhcG9sYXRlZCB0byB3aWRlciBhdWRpZW5jZS4gCgo=