Setup Packages
library(tidyverse) # For data wrangling purposes and ggplot
library(tidytuesdayR) # For TT data
library(papaja) # For APA theme
Load the Data
Download the weekly data and make available in the tt object.
# Extract data using instructions from TT readme file
tt <- tt_load("2021-09-14")
# Assign each data set to a new data frame
billboard <- tt$billboard
audio_features <- tt$audio_features
Wrangle
Select a subset of interesting variables. In this case, I want to know if song danceability is associated with song popularity. I can select the appropriate variables from the data set using the select() function and remove all rows containing NAs in either danceability or popularity by using drop_na().
# From audio_features data set, select interesting variables and drop the rows which contain NAs for danceability and popularity.
audio <- audio_features %>%
select(song, performer, spotify_genre, danceability, spotify_track_popularity) %>%
drop_na(danceability, spotify_track_popularity)
glimpse(audio)
## Rows: 24,330
## Columns: 5
## $ song <chr> "......And Roses And Roses", "...And Then The…
## $ performer <chr> "Andy Williams", "Sandy Nelson", "Britney Spe…
## $ spotify_genre <chr> "['adult standards', 'brill building pop', 'e…
## $ danceability <dbl> 0.154, 0.588, 0.759, 0.613, 0.647, 0.450, 0.8…
## $ spotify_track_popularity <dbl> 38, 11, 77, 73, 40, 31, 29, 42, 42, 10, 70, 2…
Visualise
I want to visualise a relationship between two numeric variables, so a scatterplot would be appropriate. But, since there are over 24,000 individual data points, a plain scatterplot will be messy and uninformative. Instead of using geom_point(), I can use stat_binhex() which bins the data points into hexagons, which are coloured across a gradient according to how many data points they represent. I chose the specific gradient colours using sclae_fill_gradient() and assigning the ‘low’ and ‘high’ colours according to the ggplot colour cheat-sheet. I also apply the theme_apa() layer from the papaja package to make the plot APA style (-ish).
dance_plot <- ggplot(audio, mapping = aes(x = danceability, y = spotify_track_popularity)) +
stat_binhex(alpha = 0.8) +
scale_fill_gradient(low = "navyblue", high = "red2") +
theme_apa() +
ylab("Track Popularity") +
xlab("Track Danceability")
print(dance_plot)

This plot is okay but I think I can do better.
Re-Visualise
I might try to create a series of box plots showing the popularity of songs that fall into different bins of danceability. First, I must create a new character object containing the labels of my bins. Whilst danceability in this data set is coded from 0-1, I think I might code my tags as 1-10 because lots of decimal values will just crowd the x-axis of a plot.
tags <- c("(0-1)","(1-2)", "(2-3)", "(3-4)", "(4-5)",
"(5-6)","(6-7)", "(7-8)","(8-9)", "(9-10)")
After creating my tags, it is time to create a new data frame containing all of my relevant variables. First, I select danceability and popularity and put them together in a new data frame called dance. Then, I use the mutate() function to create a new variable called ‘tag’. The case_when() function is used to effective say “when danceability falls between x and y, assign it the nth tag from my object tags” which I created above. For example, looking at the first case, when danceability is less than 0.1, the row is assigned the first tag in the list (which would be “0-1”). If the danceability is between 0.1 and 0.2, it is assigned the second tag in the list (which would be “1-2”). This allows me to bin my danceability scores into 10 bins.
dance <- audio %>%
select(danceability, spotify_track_popularity)
dance <- as_tibble(dance) %>%
mutate(tag = case_when(
danceability < 0.1 ~ tags[1],
danceability >= 0.1 & danceability < 0.2 ~ tags[2],
danceability >= 0.2 & danceability < 0.3 ~ tags[3],
danceability >= 0.3 & danceability < 0.4 ~ tags[4],
danceability >= 0.4 & danceability < 0.5 ~ tags[5],
danceability >= 0.5 & danceability < 0.6 ~ tags[6],
danceability >= 0.6 & danceability < 0.7 ~ tags[7],
danceability >= 0.7 & danceability < 0.8 ~ tags[8],
danceability >= 0.8 & danceability < 0.9 ~ tags[9],
danceability >= 0.9 & danceability < 1.0 ~ tags[10]))
Right now the tag variable is a character variable. I must transform it into a factor variable before using it to create multiple boxplots. This is done using the factor() function. Instead of writing out each level of the factor individually, I simply assign the tags I created earlier as the levels. To avoid R from re-ordering any of my factors, I set ‘ordered = FALSE’. Notice each danceability score now has a corresponding tag.
dance$tag <- factor(dance$tag,
levels = tags,
ordered = FALSE)
glimpse(dance)
## Rows: 24,330
## Columns: 3
## $ danceability <dbl> 0.154, 0.588, 0.759, 0.613, 0.647, 0.450, 0.8…
## $ spotify_track_popularity <dbl> 38, 11, 77, 73, 40, 31, 29, 42, 42, 10, 70, 2…
## $ tag <fct> (1-2), (5-6), (7-8), (6-7), (6-7), (4-5), (8-…
Now it is time to create the plot. Using ggplot, I can assign my tag (danceability bin) to the x-axis and the track popularity to the y-axis. Because there will still be thousands of data points in each bin, I use geom_jitter() to add some small amount of noise to the data to make it easier to look at. I then add my boxplot layer with geom_boxplot(), choosing my fill and outline colours. The ‘alpha’ argument simply changes the transparency of the element. I want the boxplots to be more visible than the individual data points, so I assign it a higher alpha level. I then assign axis labels using the labs() function, and use guides(colour = FALSE) to simply remove the useless legend on the side of the plot. Finally, I add the APA theme using theme_apa().
ggplot(data = dance, mapping = aes(x = tag, y = spotify_track_popularity)) +
geom_jitter(aes(color = 'blue'),
alpha = 0.1) +
geom_boxplot(fill = "bisque",
color = "black",
alpha = 0.7) +
labs(x = 'Track Danceability (x10)',
y = "Track Popularity") +
guides(color = FALSE) +
theme_apa()

This plot is much nicer to look at. It seems that popularity might on average increase slightly as danceability increases. However, the box plots reveal that popularity ranges from both extremes at each level of danceability. Interestingly enough, very few songs have almost no danceability. If you want to download the raw Rmd file for this doc click the ‘code’ button at the top right of the document.
LS0tCnRpdGxlOiAiVFRXSzM4IC0gQmlsbGJvYXJkcyIKZGF0ZTogMTUtMDktMjAyMQpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKIyBTZXR1cCBQYWNrYWdlcwoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRQopCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpICMgRm9yIGRhdGEgd3JhbmdsaW5nIHB1cnBvc2VzIGFuZCBnZ3Bsb3QKbGlicmFyeSh0aWR5dHVlc2RheVIpICMgRm9yIFRUIGRhdGEKbGlicmFyeShwYXBhamEpICMgRm9yIEFQQSB0aGVtZQpgYGAKCiMgTG9hZCB0aGUgRGF0YQoKRG93bmxvYWQgdGhlIHdlZWtseSBkYXRhIGFuZCBtYWtlIGF2YWlsYWJsZSBpbiB0aGUgYHR0YCBvYmplY3QuCgpgYGB7ciBMb2FkLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KIyBFeHRyYWN0IGRhdGEgdXNpbmcgaW5zdHJ1Y3Rpb25zIGZyb20gVFQgcmVhZG1lIGZpbGUKdHQgPC0gdHRfbG9hZCgiMjAyMS0wOS0xNCIpCgojIEFzc2lnbiBlYWNoIGRhdGEgc2V0IHRvIGEgbmV3IGRhdGEgZnJhbWUKYmlsbGJvYXJkIDwtIHR0JGJpbGxib2FyZAphdWRpb19mZWF0dXJlcyA8LSB0dCRhdWRpb19mZWF0dXJlcwpgYGAKCiMgV3JhbmdsZQoKU2VsZWN0IGEgc3Vic2V0IG9mIGludGVyZXN0aW5nIHZhcmlhYmxlcy4gSW4gdGhpcyBjYXNlLCBJIHdhbnQgdG8ga25vdyBpZiBzb25nICAqKmRhbmNlYWJpbGl0eSoqIGlzIGFzc29jaWF0ZWQgd2l0aCBzb25nICoqcG9wdWxhcml0eSoqLiBJIGNhbiBzZWxlY3QgdGhlIGFwcHJvcHJpYXRlIHZhcmlhYmxlcyBmcm9tIHRoZSBkYXRhIHNldCB1c2luZyB0aGUgYHNlbGVjdCgpYCBmdW5jdGlvbiBhbmQgcmVtb3ZlIGFsbCByb3dzIGNvbnRhaW5pbmcgTkFzIGluIGVpdGhlciBkYW5jZWFiaWxpdHkgb3IgcG9wdWxhcml0eSBieSB1c2luZyBgZHJvcF9uYSgpYC4gCgpgYGB7ciBXcmFuZ2xlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIEZyb20gYXVkaW9fZmVhdHVyZXMgZGF0YSBzZXQsIHNlbGVjdCBpbnRlcmVzdGluZyB2YXJpYWJsZXMgYW5kIGRyb3AgdGhlIHJvd3Mgd2hpY2ggY29udGFpbiBOQXMgZm9yIGRhbmNlYWJpbGl0eSBhbmQgcG9wdWxhcml0eS4KCmF1ZGlvIDwtIGF1ZGlvX2ZlYXR1cmVzICU+JQogIHNlbGVjdChzb25nLCBwZXJmb3JtZXIsIHNwb3RpZnlfZ2VucmUsIGRhbmNlYWJpbGl0eSwgc3BvdGlmeV90cmFja19wb3B1bGFyaXR5KSAlPiUKICBkcm9wX25hKGRhbmNlYWJpbGl0eSwgc3BvdGlmeV90cmFja19wb3B1bGFyaXR5KQoKZ2xpbXBzZShhdWRpbykKYGBgCiMgVmlzdWFsaXNlCgpJIHdhbnQgdG8gdmlzdWFsaXNlIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIG51bWVyaWMgdmFyaWFibGVzLCBzbyBhIHNjYXR0ZXJwbG90IHdvdWxkIGJlIGFwcHJvcHJpYXRlLiBCdXQsIHNpbmNlIHRoZXJlIGFyZSBvdmVyIDI0LDAwMCBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzLCBhIHBsYWluIHNjYXR0ZXJwbG90IHdpbGwgYmUgbWVzc3kgYW5kIHVuaW5mb3JtYXRpdmUuIEluc3RlYWQgb2YgdXNpbmcgYGdlb21fcG9pbnQoKWAsIEkgY2FuIHVzZSBgc3RhdF9iaW5oZXgoKWAgd2hpY2ggYmlucyB0aGUgZGF0YSBwb2ludHMgaW50byBoZXhhZ29ucywgd2hpY2ggYXJlIGNvbG91cmVkIGFjcm9zcyBhIGdyYWRpZW50IGFjY29yZGluZyB0byBob3cgbWFueSBkYXRhIHBvaW50cyB0aGV5IHJlcHJlc2VudC4gSSBjaG9zZSB0aGUgc3BlY2lmaWMgZ3JhZGllbnQgY29sb3VycyB1c2luZyBgc2NsYWVfZmlsbF9ncmFkaWVudCgpYCBhbmQgYXNzaWduaW5nIHRoZSAnbG93JyBhbmQgJ2hpZ2gnIGNvbG91cnMgYWNjb3JkaW5nIHRvIHRoZSBbZ2dwbG90IGNvbG91ciBjaGVhdC1zaGVldF0oaHR0cDovL3NhcGUuaW5mLnVzaS5jaC9xdWljay1yZWZlcmVuY2UvZ2dwbG90Mi9jb2xvdXIpLiBJIGFsc28gYXBwbHkgdGhlIGB0aGVtZV9hcGEoKWAgbGF5ZXIgZnJvbSB0aGUgKipwYXBhamEqKiBwYWNrYWdlIHRvIG1ha2UgdGhlIHBsb3QgQVBBIHN0eWxlICgtaXNoKS4KCmBgYHtyIFZpc3VhbGl6ZX0KZGFuY2VfcGxvdCA8LSBnZ3Bsb3QoYXVkaW8sIG1hcHBpbmcgPSBhZXMoeCA9IGRhbmNlYWJpbGl0eSwgeSA9IHNwb3RpZnlfdHJhY2tfcG9wdWxhcml0eSkpICsKICBzdGF0X2JpbmhleChhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIm5hdnlibHVlIiwgaGlnaCA9ICJyZWQyIikgKwogIHRoZW1lX2FwYSgpICsKICB5bGFiKCJUcmFjayBQb3B1bGFyaXR5IikgKwogIHhsYWIoIlRyYWNrIERhbmNlYWJpbGl0eSIpCgpwcmludChkYW5jZV9wbG90KQpgYGAKICAKICAKVGhpcyBwbG90IGlzIG9rYXkgYnV0IEkgdGhpbmsgSSBjYW4gZG8gYmV0dGVyLiAKCiMgUmUtVmlzdWFsaXNlIAoKSSBtaWdodCB0cnkgdG8gY3JlYXRlIGEgc2VyaWVzIG9mIGJveCBwbG90cyBzaG93aW5nIHRoZSBwb3B1bGFyaXR5IG9mIHNvbmdzIHRoYXQgZmFsbCBpbnRvIGRpZmZlcmVudCBiaW5zIG9mIGRhbmNlYWJpbGl0eS4gRmlyc3QsIEkgbXVzdCBjcmVhdGUgYSBuZXcgY2hhcmFjdGVyIG9iamVjdCBjb250YWluaW5nIHRoZSBsYWJlbHMgb2YgbXkgYmlucy4gV2hpbHN0IGRhbmNlYWJpbGl0eSBpbiB0aGlzIGRhdGEgc2V0IGlzIGNvZGVkIGZyb20gMC0xLCBJIHRoaW5rIEkgbWlnaHQgY29kZSBteSB0YWdzIGFzIDEtMTAgYmVjYXVzZSBsb3RzIG9mIGRlY2ltYWwgdmFsdWVzIHdpbGwganVzdCBjcm93ZCB0aGUgeC1heGlzIG9mIGEgcGxvdC4KCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0YWdzIDwtIGMoIigwLTEpIiwiKDEtMikiLCAiKDItMykiLCAiKDMtNCkiLCAiKDQtNSkiLCAKICAgICAgICAgICIoNS02KSIsIig2LTcpIiwgIig3LTgpIiwiKDgtOSkiLCAiKDktMTApIikKYGBgCgoKQWZ0ZXIgY3JlYXRpbmcgbXkgdGFncywgaXQgaXMgdGltZSB0byBjcmVhdGUgYSBuZXcgZGF0YSBmcmFtZSBjb250YWluaW5nIGFsbCBvZiBteSByZWxldmFudCB2YXJpYWJsZXMuIEZpcnN0LCBJIHNlbGVjdCBkYW5jZWFiaWxpdHkgYW5kIHBvcHVsYXJpdHkgYW5kIHB1dCB0aGVtIHRvZ2V0aGVyIGluIGEgbmV3IGRhdGEgZnJhbWUgY2FsbGVkICoqZGFuY2UqKi4gVGhlbiwgSSB1c2UgdGhlIGBtdXRhdGUoKWAgZnVuY3Rpb24gdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCAndGFnJy4gVGhlIGBjYXNlX3doZW4oKWAgZnVuY3Rpb24gaXMgdXNlZCB0byBlZmZlY3RpdmUgc2F5ICoid2hlbiBkYW5jZWFiaWxpdHkgZmFsbHMgYmV0d2VlbiB4IGFuZCB5LCBhc3NpZ24gaXQgdGhlIG50aCB0YWcgZnJvbSBteSBvYmplY3QgKip0YWdzKioiKiB3aGljaCBJIGNyZWF0ZWQgYWJvdmUuIEZvciBleGFtcGxlLCBsb29raW5nIGF0IHRoZSBmaXJzdCBjYXNlLCB3aGVuIGRhbmNlYWJpbGl0eSBpcyBsZXNzIHRoYW4gMC4xLCB0aGUgcm93IGlzIGFzc2lnbmVkIHRoZSBmaXJzdCB0YWcgaW4gdGhlIGxpc3QgKHdoaWNoIHdvdWxkIGJlICIwLTEiKS4gSWYgdGhlIGRhbmNlYWJpbGl0eSBpcyBiZXR3ZWVuIDAuMSBhbmQgMC4yLCBpdCBpcyBhc3NpZ25lZCB0aGUgc2Vjb25kIHRhZyBpbiB0aGUgbGlzdCAod2hpY2ggd291bGQgYmUgIjEtMiIpLiBUaGlzIGFsbG93cyBtZSB0byBiaW4gbXkgZGFuY2VhYmlsaXR5IHNjb3JlcyBpbnRvIDEwIGJpbnMuCgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGFuY2UgPC0gYXVkaW8gJT4lCiAgc2VsZWN0KGRhbmNlYWJpbGl0eSwgc3BvdGlmeV90cmFja19wb3B1bGFyaXR5KQoKZGFuY2UgPC0gYXNfdGliYmxlKGRhbmNlKSAlPiUgCiAgbXV0YXRlKHRhZyA9IGNhc2Vfd2hlbigKICAgIGRhbmNlYWJpbGl0eSA8IDAuMSB+IHRhZ3NbMV0sCiAgICBkYW5jZWFiaWxpdHkgPj0gMC4xICYgZGFuY2VhYmlsaXR5IDwgMC4yIH4gdGFnc1syXSwKICAgIGRhbmNlYWJpbGl0eSA+PSAwLjIgJiBkYW5jZWFiaWxpdHkgPCAwLjMgfiB0YWdzWzNdLAogICAgZGFuY2VhYmlsaXR5ID49IDAuMyAmIGRhbmNlYWJpbGl0eSA8IDAuNCB+IHRhZ3NbNF0sCiAgICBkYW5jZWFiaWxpdHkgPj0gMC40ICYgZGFuY2VhYmlsaXR5IDwgMC41IH4gdGFnc1s1XSwKICAgIGRhbmNlYWJpbGl0eSA+PSAwLjUgJiBkYW5jZWFiaWxpdHkgPCAwLjYgfiB0YWdzWzZdLAogICAgZGFuY2VhYmlsaXR5ID49IDAuNiAmIGRhbmNlYWJpbGl0eSA8IDAuNyB+IHRhZ3NbN10sCiAgICBkYW5jZWFiaWxpdHkgPj0gMC43ICYgZGFuY2VhYmlsaXR5IDwgMC44IH4gdGFnc1s4XSwKICAgIGRhbmNlYWJpbGl0eSA+PSAwLjggJiBkYW5jZWFiaWxpdHkgPCAwLjkgfiB0YWdzWzldLAogICAgZGFuY2VhYmlsaXR5ID49IDAuOSAmIGRhbmNlYWJpbGl0eSA8IDEuMCB+IHRhZ3NbMTBdKSkKYGBgCgoKUmlnaHQgbm93IHRoZSAqKnRhZyoqIHZhcmlhYmxlIGlzIGEgY2hhcmFjdGVyIHZhcmlhYmxlLiBJIG11c3QgdHJhbnNmb3JtIGl0IGludG8gYSBmYWN0b3IgdmFyaWFibGUgYmVmb3JlIHVzaW5nIGl0IHRvIGNyZWF0ZSBtdWx0aXBsZSBib3hwbG90cy4gVGhpcyBpcyBkb25lIHVzaW5nIHRoZSBgZmFjdG9yKClgIGZ1bmN0aW9uLiBJbnN0ZWFkIG9mIHdyaXRpbmcgb3V0IGVhY2ggbGV2ZWwgb2YgdGhlIGZhY3RvciBpbmRpdmlkdWFsbHksIEkgc2ltcGx5IGFzc2lnbiB0aGUgdGFncyBJIGNyZWF0ZWQgZWFybGllciBhcyB0aGUgbGV2ZWxzLiBUbyBhdm9pZCBSIGZyb20gcmUtb3JkZXJpbmcgYW55IG9mIG15IGZhY3RvcnMsIEkgc2V0ICdvcmRlcmVkID0gRkFMU0UnLiBOb3RpY2UgZWFjaCBkYW5jZWFiaWxpdHkgc2NvcmUgbm93IGhhcyBhIGNvcnJlc3BvbmRpbmcgdGFnLgoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRhbmNlJHRhZyA8LSBmYWN0b3IoZGFuY2UkdGFnLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHRhZ3MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IEZBTFNFKQoKZ2xpbXBzZShkYW5jZSkKYGBgCiAgCiAgCk5vdyBpdCBpcyB0aW1lIHRvIGNyZWF0ZSB0aGUgcGxvdC4gVXNpbmcgZ2dwbG90LCBJIGNhbiBhc3NpZ24gbXkgdGFnIChkYW5jZWFiaWxpdHkgYmluKSB0byB0aGUgeC1heGlzIGFuZCB0aGUgdHJhY2sgcG9wdWxhcml0eSB0byB0aGUgeS1heGlzLiBCZWNhdXNlIHRoZXJlIHdpbGwgc3RpbGwgYmUgdGhvdXNhbmRzIG9mIGRhdGEgcG9pbnRzIGluIGVhY2ggYmluLCBJIHVzZSBgZ2VvbV9qaXR0ZXIoKWAgdG8gYWRkIHNvbWUgc21hbGwgYW1vdW50IG9mIG5vaXNlIHRvIHRoZSBkYXRhIHRvIG1ha2UgaXQgZWFzaWVyIHRvIGxvb2sgYXQuIEkgdGhlbiBhZGQgbXkgYm94cGxvdCBsYXllciB3aXRoIGBnZW9tX2JveHBsb3QoKWAsIGNob29zaW5nIG15IGZpbGwgYW5kIG91dGxpbmUgY29sb3Vycy4gVGhlICdhbHBoYScgYXJndW1lbnQgc2ltcGx5IGNoYW5nZXMgdGhlIHRyYW5zcGFyZW5jeSBvZiB0aGUgZWxlbWVudC4gSSB3YW50IHRoZSBib3hwbG90cyB0byBiZSBtb3JlIHZpc2libGUgdGhhbiB0aGUgaW5kaXZpZHVhbCBkYXRhIHBvaW50cywgc28gSSBhc3NpZ24gaXQgYSBoaWdoZXIgYWxwaGEgbGV2ZWwuIEkgdGhlbiBhc3NpZ24gYXhpcyBsYWJlbHMgdXNpbmcgdGhlIGBsYWJzKClgIGZ1bmN0aW9uLCBhbmQgdXNlIGBndWlkZXMoY29sb3VyID0gRkFMU0UpYCB0byBzaW1wbHkgcmVtb3ZlIHRoZSB1c2VsZXNzIGxlZ2VuZCBvbiB0aGUgc2lkZSBvZiB0aGUgcGxvdC4gRmluYWxseSwgSSBhZGQgdGhlIEFQQSB0aGVtZSB1c2luZyBgdGhlbWVfYXBhKClgLgogIAogIApgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoZGF0YSA9IGRhbmNlLCBtYXBwaW5nID0gYWVzKHggPSB0YWcsIHkgPSBzcG90aWZ5X3RyYWNrX3BvcHVsYXJpdHkpKSArIAogIGdlb21faml0dGVyKGFlcyhjb2xvciA9ICdibHVlJyksIAogICAgICAgICAgICAgIGFscGhhID0gMC4xKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAiYmlzcXVlIiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGFscGhhID0gMC43KSArIAogIGxhYnMoeCA9ICdUcmFjayBEYW5jZWFiaWxpdHkgKHgxMCknLCAKICAgICAgIHkgPSAiVHJhY2sgUG9wdWxhcml0eSIpICsKICBndWlkZXMoY29sb3IgPSBGQUxTRSkgKwogIHRoZW1lX2FwYSgpCmBgYAoKVGhpcyBwbG90IGlzIG11Y2ggbmljZXIgdG8gbG9vayBhdC4gSXQgc2VlbXMgdGhhdCBwb3B1bGFyaXR5IG1pZ2h0IG9uIGF2ZXJhZ2UgaW5jcmVhc2Ugc2xpZ2h0bHkgYXMgZGFuY2VhYmlsaXR5IGluY3JlYXNlcy4gSG93ZXZlciwgdGhlIGJveCBwbG90cyByZXZlYWwgdGhhdCBwb3B1bGFyaXR5IHJhbmdlcyBmcm9tIGJvdGggZXh0cmVtZXMgYXQgZWFjaCBsZXZlbCBvZiBkYW5jZWFiaWxpdHkuIEludGVyZXN0aW5nbHkgZW5vdWdoLCB2ZXJ5IGZldyBzb25ncyBoYXZlIGFsbW9zdCBubyBkYW5jZWFiaWxpdHkuIElmIHlvdSB3YW50IHRvIGRvd25sb2FkIHRoZSByYXcgUm1kIGZpbGUgZm9yIHRoaXMgZG9jIGNsaWNrIHRoZSAnY29kZScgYnV0dG9uIGF0IHRoZSB0b3AgcmlnaHQgb2YgdGhlIGRvY3VtZW50Lgo=