Think you really know your taste in music? Let’s take a deeper dive into your favorite songs using the R wrapper “spotifyr” that pulls track information using Spotify’s Web API.

Most Recently Played

Let’s start off with something simple. What are your 5 most recently played songs?

Sound familiar?

Your Top Artists

Current Rankings

Now let’s learn more about the artists that you listen to the most. Are you a dedicated listener to your Top 3?

Your Favorite Genres

Here are your favorite genres based on your favorite artists.

Error in `group_by()`:
! Must group by variables found in `.data`.
✖ Column `genres` is not found.
Backtrace:
  1. ... %>% relocate(Ranking)
 10. dplyr:::group_by.data.frame(., genres)

Song Features

Spotify’s database includes many features of music tracks, including the loudness, tempo, danceability, and energy. Some of these variables, such as loudness and tempo, are easily quantifiable. Others, such as danceability and valence, are impossible to measure, yet these features exist. Properties of the audio are utilized in order to engineer features that are not measurable have a deterministic output. For instance, valence is an abstract feature that Spotify has defined as indicating the “positiveness” of the song. A valence closer to 1.0 indicates that the track is more cheerful.

Here’s some more information about the features made available by the Spotify API:

  • Danceability: How likely are you to party to the song? The algorithm to calculate the danceability score of a track takes into account the tempo and beat strength. A stronger, more regular beat correlates to a higher danceability score.

  • Energy: The intensity of a track.

  • Speechiness: A score based on the amount of spoken word in the song versus singing.

  • Acousticness: How likely the song was recorded acoustically.

  • Instrumentalness: How likely the song is an instrumental one. A song with more prominent vocals will score lower on the instrumentalness scale.

  • Liveness: How likely the song was recorded live.

  • Valence: The “positiveness” of the track. Songs that have happier tones will score highly in this feature.

Keeping these thoughts in mind, let’s compare the average track features for your Top 3 artists.

Emotion Map

Super cool, right? Let’s take it a step further and classify individual songs from your favorite artists based on their emotional content. The next figure is based on Russell’s Circumplex Model of Emotion, which takes a 2D approach to display emotional categories based on the relationship between arousal and valence. Music emotion recognition (MER) is an important part of research when it comes to music information retrieval, and recommender systems, such those used for Spotify, rely on many different features in order to detect emotion in tracks and make similar suggestions. We will create a figure based on Russell’s Model that maps all tracks from your Top 3 into four different emotional quadrants: Happy, Angry, Sad, and Relaxed.

Take a moment to check out which tracks are in each category. Do you agree with the results? Your Top 3 artists collectively have 148 tracks categorized as angry, 83 as happy, 28 as sad, and 20 as relaxed. You’re into some pretty angry music!

Let’s do some quick calculations.

Looks like Panic! At The Disco is your Angriest Artist! Panic! At The Disco has the greatest number of songs in their discography categorized as angry based on the energy to valence ratio of the tracks compared to your other two top artists.

Sentiment Analysis

Let’s use the package geniusr to interact with the Genius API to identify the dominant sentiment present in the songs of your favorite artists. We will use the tidytext package to analyze the sentiment of the lyrics by identifying the sentiment content of the individual words. The general-purpose lexicon utilized to identify emotions is called bing, which contains thousands of words that are assigned emotions such as joy, anger, anticipation, and sadness. We will analyze the sentiment in the most recent album of your top artist from the past month.


Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine

Recommendations

A special playlist curated just for you has been uploaded to your Spotify account. Happy listening!

LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpemF0aW9uIHdpdGggU3BvdGlmeSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2sKLS0tCgpUaGluayB5b3UgcmVhbGx5IGtub3cgeW91ciB0YXN0ZSBpbiBtdXNpYz8gTGV0J3MgdGFrZSBhIGRlZXBlciBkaXZlIGludG8geW91cgpmYXZvcml0ZSBzb25ncyB1c2luZyB0aGUgUiB3cmFwcGVyICJzcG90aWZ5ciIgdGhhdCBwdWxscyB0cmFjayBpbmZvcm1hdGlvbiB1c2luZwpbU3BvdGlmeSdzIFdlYiBBUEldKGh0dHBzOi8vZGV2ZWxvcGVyLnNwb3RpZnkuY29tL2RvY3VtZW50YXRpb24vd2ViLWFwaS8pLiAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpIAojaHR0cHM6Ly9sYXRpbm11c2ljaGlzdG9yeS5naXRodWIuaW8vaW5kZXguaHRtbAojaW5zdGFsbC5wYWNrYWdlcygiZm9ybWF0dGFibGUiKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmxpYnJhcnkoc3BvdGlmeXIpCmxpYnJhcnkoaHR0cikKbGlicmFyeShkcGx5cikKbGlicmFyeShwdXJycikgCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobHVicmlkYXRlKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiMgYnJvd3NlVVJMKHBhc3RlMCgnaHR0cHM6Ly9hY2NvdW50cy5zcG90aWZ5LmNvbS9hdXRob3JpemU/Y2xpZW50X2lkPWY2NzZmYTdlYWYwZTRmNzlhMzQ0MmE0ZTI1ZDU0MGVlJywnJnJlc3BvbnNlX3R5cGU9Y29kZSZyZWRpcmVjdF91cmk9JywgJ2h0dHA6Ly9sb2NhbGhvc3Q6MTQxMC8nLCcvJnNjb3BlPXVzZXItcmVhZC1yZWNlbnRseS1wbGF5ZWQnKSxicm93c2VyID0gZ2V0T3B0aW9uKCJicm93c2VyIiksIGVuY29kZUlmTmVlZGVkID0gRkFMU0UpCiMgICAgIAojICAgICAjY29uc3RydWN0IGJvZHkgb2YgUE9TVCByZXF1ZXN0IEZJUlNUIFRJTUUKIyAgICAgcmVxdWVzdF9ib2R5IDwtIGxpc3QoZ3JhbnRfdHlwZT0nYXV0aG9yaXphdGlvbl9jb2RlJywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkaXJlY3RfdXJpPSdodHRwOi8vbG9jYWxob3N0OjE0MTAvJywgI2lucHV0IHlvdXIgZG9tYWluIG5hbWUKIyAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpZW50X2lkID0gJ2Y2NzZmYTdlYWYwZTRmNzlhMzQ0MmE0ZTI1ZDU0MGVlJywgI2lucHV0IHlvdXIgU3BvdGlmeSBDbGllbnQgSUQKIyAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpZW50X3NlY3JldCA9J2JmNTlhYzAyNjhhMzRjNzViYmExNzA3YjdiYzBlYTdiJykgI2lucHV0IHlvdXIgU3BvdGlmeSBDbGllbnQgU2VjcmV0CiMgICAgIAojICAgICAjZ2V0IHVzZXIgdG9rZW5zIEZJUlNUIFRJTUUKIyAgICAgYWNjZXNzX3Rva2VuIDwtIGh0dHI6OmNvbnRlbnQoaHR0cjo6UE9TVCgnaHR0cHM6Ly9hY2NvdW50cy5zcG90aWZ5LmNvbS9hcGkvdG9rZW4nLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5PXJlcXVlc3RfYm9keSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jb2RlPSdmb3JtJykpCgojIHJlc3BvbnNlID0gUE9TVCgKIyAgICdodHRwczovL2FjY291bnRzLnNwb3RpZnkuY29tL2FwaS90b2tlbicsCiMgICBhY2NlcHRfanNvbigpLAojICAgYXV0aGVudGljYXRlKCdmNjc2ZmE3ZWFmMGU0Zjc5YTM0NDJhNGUyNWQ1NDBlZScsICdiZjU5YWMwMjY4YTM0Yzc1YmJhMTcwN2I3YmMwZWE3YicpLAojICAgYm9keSA9IGxpc3QoZ3JhbnRfdHlwZSA9ICdjbGllbnRfY3JlZGVudGlhbHMnKSwKIyAgIGVuY29kZSA9ICdmb3JtJywKIyAgIHZlcmJvc2UoKQojICkKIyAKIyBhY2Nlc3NfdG9rZW4gPSBjb250ZW50KHJlc3BvbnNlKSRhY2Nlc3NfdG9rZW4KYGBgCgoKYGBge3IgZWNobz1GQUxTRX0KU3lzLnNldGVudihTUE9USUZZX0NMSUVOVF9JRCA9ICdmNjc2ZmE3ZWFmMGU0Zjc5YTM0NDJhNGUyNWQ1NDBlZScpClN5cy5zZXRlbnYoU1BPVElGWV9DTElFTlRfU0VDUkVUID0gJ2JmNTlhYzAyNjhhMzRjNzViYmExNzA3YjdiYzBlYTdiJykKCmFjY2Vzc190b2tlbiA8LSBnZXRfc3BvdGlmeV9hY2Nlc3NfdG9rZW4oKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9ClN5cy5zZXRlbnYoR0VOSVVTX0NMSUVOVF9JRCA9ICd6cDNoaHdpVkVWekdPNkhBb1Ixa19kY0R1MnJQX1k2azJVT0pXMXF1TlJsdmt0RmVKZGtzWjJxQ3BXNUswcHdEJykKU3lzLnNldGVudihHRU5JVVNfQ0xJRU5UX1NFQ1JFVCA9CiAgICAgICAgICAgICAnRS1CZjlHZWdLTk9QakM1ZWp6Wm00WFlmVm45ZEFLM1ZIa0pWMUxWLXVqWktRRi0zWUZfWDRuUlZLTVRvSDZ3a1BtRFozNUJVbXg0b0ZaTjlxUHFScmcnKQpgYGAKCgojIyBNb3N0IFJlY2VudGx5IFBsYXllZApMZXQncyBzdGFydCBvZmYgd2l0aCBzb21ldGhpbmcgc2ltcGxlLiBXaGF0IGFyZSB5b3VyIDUgbW9zdCByZWNlbnRseSBwbGF5ZWQgCnNvbmdzPwpgYGB7ciBlY2hvPUZBTFNFfQpsaWJyYXJ5KGZvcm1hdHRhYmxlKQptb3N0UmVjZW50bHlQbGF5ZWQgPC0gZ2V0X215X3JlY2VudGx5X3BsYXllZChsaW1pdCA9IDUpICU+JSAKICAgIG11dGF0ZShhcnRpc3QubmFtZSA9IG1hcF9jaHIodHJhY2suYXJ0aXN0cywgZnVuY3Rpb24oeCkgeCRuYW1lWzFdKSwKICAgICAgICAgICBwbGF5ZWRfYXQgPSBhc19kYXRldGltZShwbGF5ZWRfYXQpKQptb3N0UmVjZW50bHlQbGF5ZWRVcmkgPC0gc3Ryc3BsaXQobW9zdFJlY2VudGx5UGxheWVkJHRyYWNrLnVyaSwgc3BsaXQgPSAiOiIpCgp0b1BsYXkgPC0gbWF0cml4KHVubGlzdChtb3N0UmVjZW50bHlQbGF5ZWRVcmkpLCBuY29sPTMsIGJ5cm93PVRSVUUpCm1vc3RSZWNlbnRseVBsYXllZCA8LSBtb3N0UmVjZW50bHlQbGF5ZWQgJT4lCiAgc2VsZWN0KHRyYWNrLm5hbWUsIGFydGlzdC5uYW1lKSAlPiUKICByZW5hbWUoVHJhY2sgPSB0cmFjay5uYW1lLCBBcnRpc3QgPSBhcnRpc3QubmFtZSkKZm9ybWF0dGFibGUobW9zdFJlY2VudGx5UGxheWVkLCAKICAgICAgICAgICAgYWxpZ24gPSBjKCJsIiwgImwiKSkKYGBgCgpTb3VuZCBmYW1pbGlhcj8KYGBge2NzcywgZWNobz1GQUxTRX0KLmJveCB7IGRpc3BsYXk6aW5saW5lLWJsb2NrOyBtYXJnaW4tbGVmdDo3MHB4OyBtYXJnaW4tcmlnaHQ6NzBweCB9CmBgYAoKYGBgez1odG1sfQo8ZGl2IGFsaWduPSJjZW50ZXIiIGNsYXNzPSJib3giPgo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9vcGVuLnNwb3RpZnkuY29tL2VtYmVkL3RyYWNrL2ByIHRvUGxheVsxLDNdYCIgZnJhbWVCb3JkZXI9IjAiIGFsbG93dHJhbnNwYXJlbmN5PSJ0cnVlIiBhbGxvdz0iZW5jcnlwdGVkLW1lZGlhIiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4KPC9kaXY+CjxkaXYgYWxpZ249ImNlbnRlciIgY2xhc3M9ImJveCI+CjxpZnJhbWUgc3JjPSJodHRwczovL29wZW4uc3BvdGlmeS5jb20vZW1iZWQvdHJhY2svYHIgdG9QbGF5WzIsM11gIiBmcmFtZUJvcmRlcj0iMCIgYWxsb3d0cmFuc3BhcmVuY3k9InRydWUiIGFsbG93PSJlbmNyeXB0ZWQtbWVkaWEiIGRhdGEtZXh0ZXJuYWw9IjEiPjwvaWZyYW1lPgo8L2Rpdj4KYGBgCgojIyBZb3VyIFRvcCBBcnRpc3RzCiMjIyMgQ3VycmVudCBSYW5raW5ncwpOb3cgbGV0J3MgbGVhcm4gbW9yZSBhYm91dCB0aGUgYXJ0aXN0cyB0aGF0IHlvdSBsaXN0ZW4gdG8gdGhlIG1vc3QuIEFyZSB5b3UgYSBkZWRpY2F0ZWQgbGlzdGVuZXIgdG8geW91ciBUb3AgMz8KYGBge3IgZWNobz1GQUxTRX0KZ2V0UmFua2luZ3MgPC0gZnVuY3Rpb24odGltZSkgewogIGFzLmRhdGEuZnJhbWUoZ2V0X215X3RvcF9hcnRpc3RzX29yX3RyYWNrcygKICB0eXBlID0gImFydGlzdHMiLAogIGxpbWl0ID0gMTAsCiAgb2Zmc2V0ID0gMCwKICB0aW1lX3JhbmdlID0gdGltZSwKICBhdXRob3JpemF0aW9uID0gZ2V0X3Nwb3RpZnlfYXV0aG9yaXphdGlvbl9jb2RlKCksCiAgaW5jbHVkZV9tZXRhX2luZm8gPSBGQUxTRQopJG5hbWUpCn0KCmdldElEcyA8LSBmdW5jdGlvbih0aW1lKSB7CiAgYXMuZGF0YS5mcmFtZShnZXRfbXlfdG9wX2FydGlzdHNfb3JfdHJhY2tzKAogIHR5cGUgPSAiYXJ0aXN0cyIsCiAgbGltaXQgPSAxMCwKICBvZmZzZXQgPSAwLAogIHRpbWVfcmFuZ2UgPSB0aW1lLAogIGF1dGhvcml6YXRpb24gPSBnZXRfc3BvdGlmeV9hdXRob3JpemF0aW9uX2NvZGUoKSwKICBpbmNsdWRlX21ldGFfaW5mbyA9IEZBTFNFCikkaWQpCn0KCnRvcDEwQXJ0aXN0c05vdyA8LSBnZXRSYW5raW5ncygic2hvcnRfdGVybSIpCmNvbG5hbWVzKHRvcDEwQXJ0aXN0c05vdykgPC0gYygiUGFzdCBNb250aCIpCnRvcDEwQXJ0aXN0c05vdyA8LSB0b3AxMEFydGlzdHNOb3cgJT4lCiAgbXV0YXRlKFJhbmtpbmc9cm93X251bWJlcigpKSAlPiUKICByZWxvY2F0ZShSYW5raW5nKQoKdG9wMTBBcnRpc3RzNm1vIDwtIGdldFJhbmtpbmdzKCJtZWRpdW1fdGVybSIpCmNvbG5hbWVzKHRvcDEwQXJ0aXN0czZtbykgPC0gYygiUGFzdCA2IE1vbnRocyIpCnRvcDEwQXJ0aXN0czZtbyA8LSB0b3AxMEFydGlzdHM2bW8gJT4lCiAgbXV0YXRlKFJhbmtpbmc9cm93X251bWJlcigpKSAlPiUKICByZWxvY2F0ZShSYW5raW5nKQoKdG9wMTBBcnRpc3RzRXZlciA8LSBnZXRSYW5raW5ncygibG9uZ190ZXJtIikKY29sbmFtZXModG9wMTBBcnRpc3RzRXZlcikgPC0gYygiQWxsIFRpbWUiKQp0b3AxMEFydGlzdHNFdmVyIDwtIHRvcDEwQXJ0aXN0c0V2ZXIgJT4lCiAgbXV0YXRlKFJhbmtpbmc9cm93X251bWJlcigpKSAlPiUKICByZWxvY2F0ZShSYW5raW5nKQoKdG9wMTBBcnRpc3RzRXZlciA8LSB0b3AxMEFydGlzdHNFdmVyICU+JQogIGxlZnRfam9pbih0b3AxMEFydGlzdHM2bW8sIGJ5ID0gYygiUmFua2luZyIpKSAlPiUKICBsZWZ0X2pvaW4odG9wMTBBcnRpc3RzTm93LCBieSA9IGMoIlJhbmtpbmciKSkgCmBgYAoKCmBgYHtyIGVjaG89RkFMU0V9CmxpYnJhcnkoZm9ybWF0dGFibGUpCmZvcm1hdHRhYmxlKHRvcDEwQXJ0aXN0c0V2ZXIsIAogICAgICAgICAgICBhbGlnbiA9IGMoImMiLCAiYyIsICJjIiwgImMiKSwKICAgICAgICAgICAgbGlzdCgKICAgYEFsbCBUaW1lYCA9IGZvcm1hdHRlcigic3BhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlID0geCB+IGlmZWxzZSh4ID09IHRvcDEwQXJ0aXN0c0V2ZXJbMl1bMSwxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUoY29sb3IgPSAiYmx1ZSIsIGZvbnQud2VpZ2h0ID0gImJvbGQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoeCA9PSB0b3AxMEFydGlzdHNFdmVyWzJdWzIsMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZShjb2xvciA9ICJicm93biIsIGZvbnQud2VpZ2h0ID0gImJvbGQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSh4ID09IHRvcDEwQXJ0aXN0c0V2ZXJbMl1bMywxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZShjb2xvciA9ICJncmVlbiIsIGZvbnQud2VpZ2h0ID0iYm9sZCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICBgUGFzdCA2IE1vbnRoc2AgPSBmb3JtYXR0ZXIoInNwYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZSA9IHggfiBpZmVsc2UoeCA9PSB0b3AxMEFydGlzdHNFdmVyWzJdWzEsMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlKGNvbG9yID0gImJsdWUiLCBmb250LndlaWdodCA9ICJib2xkIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHggPT0gdG9wMTBBcnRpc3RzRXZlclsyXVsyLDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUoY29sb3IgPSAiYnJvd24iLCBmb250LndlaWdodCA9ICJib2xkIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoeCA9PSB0b3AxMEFydGlzdHNFdmVyWzJdWzMsMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUoY29sb3IgPSAiZ3JlZW4iLCBmb250LndlaWdodCA9ImJvbGQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgYFBhc3QgTW9udGhgID0gZm9ybWF0dGVyKCJzcGFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUgPSB4IH4gaWZlbHNlKHggPT0gdG9wMTBBcnRpc3RzRXZlclsyXVsxLDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZShjb2xvciA9ICJibHVlIiwgZm9udC53ZWlnaHQgPSAiYm9sZCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSh4ID09IHRvcDEwQXJ0aXN0c0V2ZXJbMl1bMiwxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlKGNvbG9yID0gImJyb3duIiwgZm9udC53ZWlnaHQgPSAiYm9sZCIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHggPT0gdG9wMTBBcnRpc3RzRXZlclsyXVszLDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlKGNvbG9yID0gImdyZWVuIiwgZm9udC53ZWlnaHQgPSJib2xkIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSkpKQogICAgICAgICAgICAgICAgICAgICAgICAgICkKKSkKYGBgCgojIyMjIFlvdXIgRmF2b3JpdGUgR2VucmVzCkhlcmUgYXJlIHlvdXIgZmF2b3JpdGUgZ2VucmVzIGJhc2VkIG9uIHlvdXIgZmF2b3JpdGUgYXJ0aXN0cy4KYGBge3IgZWNobz1GQUxTRX0KaWRzTm93IDwtIGdldElEcygic2hvcnRfdGVybSIpCmlkczZtbyA8LSBnZXRJRHMoIm1lZGl1bV90ZXJtIikKaWRzRXZlciA8LSBnZXRJRHMoImxvbmdfdGVybSIpCgppZHMgPC0gcmJpbmQoaWRzTm93LCBpZHM2bW8sIGlkc0V2ZXIpCmlkcyA8LSBkaXN0aW5jdChpZHMpCmNvbG5hbWVzKGlkcykgPC0gYygiYXJ0aXN0X2lkIikKCmdlbnJlcyA8LSBjKCkKZm9yIChpIGluIDE6bGVuZ3RoKGlkcyRhcnRpc3RfaWQpKSB7CiAgaW5mbyA8LSBzcG90aWZ5cjo6Z2V0X2FydGlzdChpZCA9IGlkcyRhcnRpc3RfaWRbaV0sIGF1dGhvcml6YXRpb24gPSBnZXRfc3BvdGlmeV9hY2Nlc3NfdG9rZW4oKSkKICBnZW5yZXMgPC0gYyhnZW5yZXMsIGluZm8kZ2VucmVzKQp9CmdlbnJlcyA8LSBhcy5kYXRhLmZyYW1lKGdlbnJlcykKZ2VucmVzIDwtIGdlbnJlcyAlPiUKICBncm91cF9ieShnZW5yZXMpICU+JQogIHN1bW1hcml6ZShjb3VudCA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKGNvdW50KSkgJT4lCiAgc2xpY2UoMTo1KSAlPiUKICBzZWxlY3QoZ2VucmVzKSAlPiUKICByZW5hbWUoR2VucmUgPSBnZW5yZXMpICU+JQogIG11dGF0ZShSYW5raW5nID0gcm93X251bWJlcigpKSAlPiUKICByZWxvY2F0ZShSYW5raW5nKQpmb3JtYXR0YWJsZShnZW5yZXMsIGFsaWduID0gYygibCIsICJsIikpIApgYGAKCiMjIyMgU29uZyBGZWF0dXJlcwpgYGB7ciBlY2hvPUZBTFNFfQp0b3BBcnRpc3QgPC0gZ2V0X215X3RvcF9hcnRpc3RzX29yX3RyYWNrcygKICB0eXBlID0gImFydGlzdHMiLAogIGxpbWl0ID0gMjAsCiAgb2Zmc2V0ID0gMCwKICB0aW1lX3JhbmdlID0gImxvbmdfdGVybSIsCiAgYXV0aG9yaXphdGlvbiA9IGdldF9zcG90aWZ5X2F1dGhvcml6YXRpb25fY29kZSgpLAogIGluY2x1ZGVfbWV0YV9pbmZvID0gRkFMU0UKKSAlPiUgCiAgc2xpY2UoMTozKQp0b3BBcnRpc3RVcmkxIDwtIHN0cnNwbGl0KHRvcEFydGlzdCR1cmksIHNwbGl0ID0gIjoiKVtbMV1dWzNdCnRvcEFydGlzdFVyaTIgPC0gc3Ryc3BsaXQodG9wQXJ0aXN0JHVyaSwgc3BsaXQgPSAiOiIpW1syXV1bM10KdG9wQXJ0aXN0VXJpMyA8LSBzdHJzcGxpdCh0b3BBcnRpc3QkdXJpLCBzcGxpdCA9ICI6IilbWzNdXVszXQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmNyZWF0ZVRyYWNrSW5mbyA8LSBmdW5jdGlvbihhcnRpc3RfdXJpKSB7CiAgIHRvcEFydGlzdFRyYWNrSW5mbyA8LSBnZXRfYXJ0aXN0X2F1ZGlvX2ZlYXR1cmVzKAogICAgYXJ0aXN0ID0gYXJ0aXN0X3VyaSwKICAgIGluY2x1ZGVfZ3JvdXBzID0gImFsYnVtIiwKICAgIHJldHVybl9jbG9zZXN0X2FydGlzdCA9IFRSVUUsCiAgICBkZWR1cGVfYWxidW1zID0gVFJVRSwKICAgIG1hcmtldCA9IE5VTEwsCiAgICBhdXRob3JpemF0aW9uID0gZ2V0X3Nwb3RpZnlfYWNjZXNzX3Rva2VuKCkKICApCiAgCiAgdG9wQXJ0aXN0VHJhY2tJbmZvIDwtIHRvcEFydGlzdFRyYWNrSW5mbyAlPiUKICAgIHNlbGVjdChhcnRpc3RfbmFtZSwgZGFuY2VhYmlsaXR5LCBlbmVyZ3ksIGtleSwgbG91ZG5lc3MsIHNwZWVjaGluZXNzLCAKICAgICAgICAgICBhY291c3RpY25lc3MsIGluc3RydW1lbnRhbG5lc3MsIGxpdmVuZXNzLCB2YWxlbmNlLCB0ZW1wbywgdHJhY2tfaWQsIAogICAgICAgICAgIHRyYWNrX25hbWUsIGFsYnVtX25hbWUsIGtleV9uYW1lLCBkdXJhdGlvbl9tcykgJT4lCiAgICBkaXN0aW5jdCh0cmFja19uYW1lLCAua2VlcF9hbGwgPSBUUlVFKQogIHJldHVybih0b3BBcnRpc3RUcmFja0luZm8pCn0KCmZpcnN0QXJ0aXN0IDwtIGNyZWF0ZVRyYWNrSW5mbyh0b3BBcnRpc3RVcmkxKQpzZWNvbmRBcnRpc3QgPC0gY3JlYXRlVHJhY2tJbmZvKHRvcEFydGlzdFVyaTIpCnRoaXJkQXJ0aXN0IDwtIGNyZWF0ZVRyYWNrSW5mbyh0b3BBcnRpc3RVcmkzKQoKdG9wMyA8LSByYmluZChmaXJzdEFydGlzdCwgc2Vjb25kQXJ0aXN0LCB0aGlyZEFydGlzdCkKYGBgCgpTcG90aWZ5J3MgZGF0YWJhc2UgaW5jbHVkZXMgbWFueSBmZWF0dXJlcyBvZiBtdXNpYyB0cmFja3MsIGluY2x1ZGluZyAKdGhlIGxvdWRuZXNzLCB0ZW1wbywgZGFuY2VhYmlsaXR5LCBhbmQgZW5lcmd5LiBTb21lIG9mIHRoZXNlIHZhcmlhYmxlcywgc3VjaCBhcwpsb3VkbmVzcyBhbmQgdGVtcG8sIGFyZSBlYXNpbHkgcXVhbnRpZmlhYmxlLiBPdGhlcnMsIHN1Y2ggYXMgZGFuY2VhYmlsaXR5IGFuZAp2YWxlbmNlLCBhcmUgaW1wb3NzaWJsZSB0byBtZWFzdXJlLCB5ZXQgdGhlc2UgZmVhdHVyZXMgZXhpc3QuIFByb3BlcnRpZXMgb2YgdGhlIAphdWRpbyBhcmUgdXRpbGl6ZWQgaW4gb3JkZXIgdG8gZW5naW5lZXIgZmVhdHVyZXMgdGhhdCBhcmUgbm90IG1lYXN1cmFibGUgaGF2ZSAKYSBkZXRlcm1pbmlzdGljIG91dHB1dC4gRm9yIGluc3RhbmNlLCB2YWxlbmNlIGlzIGFuIGFic3RyYWN0IGZlYXR1cmUgdGhhdCBTcG90aWZ5CmhhcyBkZWZpbmVkIGFzIGluZGljYXRpbmcgdGhlICJwb3NpdGl2ZW5lc3MiIG9mIHRoZSBzb25nLiBBIHZhbGVuY2UgY2xvc2VyIHRvIDEuMAppbmRpY2F0ZXMgdGhhdCB0aGUgdHJhY2sgaXMgbW9yZSBjaGVlcmZ1bC4gCgpIZXJlJ3Mgc29tZSBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBmZWF0dXJlcyBtYWRlIGF2YWlsYWJsZSBieSB0aGUgU3BvdGlmeSBBUEk6CgoqICoqRGFuY2VhYmlsaXR5OioqIEhvdyBsaWtlbHkgYXJlIHlvdSB0byBwYXJ0eSB0byB0aGUgc29uZz8gVGhlIGFsZ29yaXRobSB0byBjYWxjdWxhdGUgdGhlIGRhbmNlYWJpbGl0eSBzY29yZSBvZiBhIHRyYWNrIHRha2VzIGludG8gYWNjb3VudCB0aGUgdGVtcG8gYW5kIGJlYXQgc3RyZW5ndGguIEEgc3Ryb25nZXIsIG1vcmUgcmVndWxhciBiZWF0IGNvcnJlbGF0ZXMgdG8gYSBoaWdoZXIgZGFuY2VhYmlsaXR5IHNjb3JlLgoKKiAqKkVuZXJneToqKiBUaGUgaW50ZW5zaXR5IG9mIGEgdHJhY2suCgoqICoqU3BlZWNoaW5lc3M6KiogQSBzY29yZSBiYXNlZCBvbiB0aGUgYW1vdW50IG9mIHNwb2tlbiB3b3JkIGluIHRoZSBzb25nIHZlcnN1cyBzaW5naW5nLgoKKiAqKkFjb3VzdGljbmVzczoqKiBIb3cgbGlrZWx5IHRoZSBzb25nIHdhcyByZWNvcmRlZCBhY291c3RpY2FsbHkuCgoqICoqSW5zdHJ1bWVudGFsbmVzczoqKiBIb3cgbGlrZWx5IHRoZSBzb25nIGlzIGFuIGluc3RydW1lbnRhbCBvbmUuIEEgc29uZyB3aXRoIG1vcmUgcHJvbWluZW50IHZvY2FscyB3aWxsIHNjb3JlIGxvd2VyIG9uIHRoZSBpbnN0cnVtZW50YWxuZXNzIHNjYWxlLgoKKiAqKkxpdmVuZXNzOioqIEhvdyBsaWtlbHkgdGhlIHNvbmcgd2FzIHJlY29yZGVkIGxpdmUuCgoqICoqVmFsZW5jZToqKiBUaGUgInBvc2l0aXZlbmVzcyIgb2YgdGhlIHRyYWNrLiBTb25ncyB0aGF0IGhhdmUgaGFwcGllciB0b25lcyB3aWxsIHNjb3JlIGhpZ2hseSBpbiB0aGlzIGZlYXR1cmUuCgpLZWVwaW5nIHRoZXNlIHRob3VnaHRzIGluIG1pbmQsIGxldCdzIGNvbXBhcmUgdGhlIGF2ZXJhZ2UgdHJhY2sgZmVhdHVyZXMgZm9yIHlvdXIgVG9wIDMgYXJ0aXN0cy4gCgpgYGB7ciBlY2hvPUZBTFNFfQojIE5vYWggS2FoYW4sIEJsZWFjaGVycywgSG96aWVyCmxpYnJhcnkoZm1zYikKbGlicmFyeShjb2xvcm1hcCkKbWF4X21pbiA8LSBkYXRhLmZyYW1lKAogIGRhbmNlYWJpbGl0eSA9IGMoMSwgMCksIGVuZXJneSA9IGMoMSwgMCksCiAgc3BlZWNoaW5lc3MgPSBjKDEsIDApLCBhY291c3RpY25lc3MgPSBjKDEsIDApLCBpbnN0cnVtZW50YWxuZXNzID0gYygxLCAwKSwKICBsaXZlbmVzcyA9IGMoMSwgMCksIHZhbGVuY2UgPSBjKDEsIDApCikKcm93bmFtZXMobWF4X21pbikgPC0gYygiTWF4IiwgIk1pbiIpCgptZWFuVHJhY2tGZWF0dXJlcyA8LSB0b3AzICU+JQogIHNlbGVjdCgtdHJhY2tfaWQsIC10cmFja19uYW1lLCAtYWxidW1fbmFtZSwgLWtleV9uYW1lLCAta2V5LCAtbG91ZG5lc3MsIC10ZW1wbywgLWR1cmF0aW9uX21zKSAlPiUKICBncm91cF9ieShhcnRpc3RfbmFtZSkgJT4lCiAgc3VtbWFyaXNlX2FsbCgibWVhbiIpCgp0b3AzTmFtZXMgPC0gdG9wMyAlPiUKICBncm91cF9ieShhcnRpc3RfbmFtZSkgJT4lCiAgc3VtbWFyaXplKG4gPSBuKCkpCgptZWFuVHJhY2tGZWF0dXJlczEgPC0gbWVhblRyYWNrRmVhdHVyZXMKcm93bmFtZXMobWVhblRyYWNrRmVhdHVyZXMpIDwtIG1lYW5UcmFja0ZlYXR1cmVzJGFydGlzdF9uYW1lCm1lYW5UcmFja0ZlYXR1cmVzJGFydGlzdF9uYW1lIDwtIE5VTEwKbWVhblRyYWNrRmVhdHVyZXMgPC0gcmJpbmQobWF4X21pbiwgbWVhblRyYWNrRmVhdHVyZXMpCgpjcmVhdGVfcmFkYXJjaGFydCA8LSBmdW5jdGlvbihkYXRhLCBjb2xvciA9ICIjMDBBRkJCIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2bGFiZWxzID0gY29sbmFtZXMoZGF0YSksIHZsY2V4ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F4aXNsYWJlbHMgPSBOVUxMLCB0aXRsZSA9IE5VTEwsIC4uLil7CiAgcmFkYXJjaGFydCgKICAgIGRhdGEsIGF4aXN0eXBlID0gMSwKICAgICMgQ3VzdG9taXplIHRoZSBwb2x5Z29uCiAgICBwY29sID0gY29sb3IsIHBmY29sID0gc2NhbGVzOjphbHBoYShjb2xvciwgMC40KSwgcGx3ZCA9IDIsIHBsdHkgPSAxLAogICAgIyBDdXN0b21pemUgdGhlIGdyaWQKICAgIGNnbGNvbCA9ICJncmV5IiwgY2dsdHkgPSAxLCBjZ2x3ZCA9IDAuOCwKICAgICMgQ3VzdG9taXplIHRoZSBheGlzCiAgICBheGlzbGFiY29sID0gImdyZXkiLCAKICAgICMgVmFyaWFibGUgbGFiZWxzCiAgICB2bGNleCA9IHZsY2V4LCB2bGFiZWxzID0gdmxhYmVscywKICAgIGNheGlzbGFiZWxzID0gY2F4aXNsYWJlbHMsIHRpdGxlID0gdGl0bGUsIC4uLgogICkKfQoKIyBEZWZpbmUgY29sb3JzIGFuZCB0aXRsZXMKY29sb3JzIDwtIGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIsICIjRkM0RTA3IikKdGl0bGVzIDwtIGModG9wM05hbWVzJGFydGlzdF9uYW1lWzFdLCB0b3AzTmFtZXMkYXJ0aXN0X25hbWVbMl0sIHRvcDNOYW1lcyRhcnRpc3RfbmFtZVszXSkKCiMgUmVkdWNlIHBsb3QgbWFyZ2luIHVzaW5nIHBhcigpCiMgU3BsaXQgdGhlIHNjcmVlbiBpbiAzIHBhcnRzCm9wIDwtIHBhcihtYXIgPSBjKDEsIDEsIDEsIDEpKQpwYXIobWZyb3cgPSBjKDIsMikpCgojY29sb3JzX2JvcmRlcj1jb2xvcm1hcChjb2xvcm1hcD1jb2xvcm1hcHMkdmlyaWRpcywgbnNoYWRlcz02LCBhbHBoYT0xKQojY29sb3JzX2luPWNvbG9ybWFwKGNvbG9ybWFwPWNvbG9ybWFwcyR2aXJpZGlzLCBuc2hhZGVzPTYsIGFscGhhPTAuMykKCiMgQ3JlYXRlIHRoZSByYWRhciBjaGFydApmb3IoaSBpbiAxOjMpIHsKICBjcmVhdGVfcmFkYXJjaGFydCgKICAgIGRhdGEgPSBtZWFuVHJhY2tGZWF0dXJlc1tjKDEsIDIsIGkrMiksIF0sIGNheGlzbGFiZWxzID0gYygwLCAwLjI1LCAwLjUwLCAwLjc1LCAxLjApLAogICAgY29sb3IgPSBjb2xvcnNbaV0sIHRpdGxlID0gdGl0bGVzW2ldCiAgICApCn0KY3JlYXRlX3JhZGFyY2hhcnQoCiAgZGF0YSA9IG1lYW5UcmFja0ZlYXR1cmVzLCBjYXhpc2xhYmVscyA9IGMoMCwgMC4yNSwgMC41MCwgMC43NSwgMS4wKSwKICBjb2xvciA9IGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIsICIjRkM0RTA3IiksCiAgdGl0bGUgPSAiQWxsIDMgQXJ0aXN0cyIKKQoKcGFyKG9wKQpgYGAKIyMjIyBFbW90aW9uIE1hcApTdXBlciBjb29sLCByaWdodD8gTGV0J3MgdGFrZSBpdCBhIHN0ZXAgZnVydGhlciBhbmQgY2xhc3NpZnkgaW5kaXZpZHVhbCBzb25ncyAKZnJvbSB5b3VyIGZhdm9yaXRlIGFydGlzdHMgYmFzZWQgb24gdGhlaXIgZW1vdGlvbmFsIGNvbnRlbnQuIFRoZSBuZXh0IGZpZ3VyZSBpcyBiYXNlZCAKb24gW1J1c3NlbGzigJlzIENpcmN1bXBsZXggTW9kZWwgb2YgRW1vdGlvbl0oaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9maWd1cmUvUnVzc2VsbHMtY2lyY3VtcGxleC1tb2RlbC0xM19maWc1XzMwNzkwOTAyNCksCndoaWNoIHRha2VzIGEgMkQgYXBwcm9hY2ggdG8gZGlzcGxheSBlbW90aW9uYWwgY2F0ZWdvcmllcyBiYXNlZCBvbiB0aGUgcmVsYXRpb25zaGlwCmJldHdlZW4gYXJvdXNhbCBhbmQgdmFsZW5jZS4gTXVzaWMgZW1vdGlvbiByZWNvZ25pdGlvbiAoTUVSKSBpcyBhbiBpbXBvcnRhbnQgcGFydApvZiByZXNlYXJjaCB3aGVuIGl0IGNvbWVzIHRvIG11c2ljIGluZm9ybWF0aW9uIHJldHJpZXZhbCwgYW5kIHJlY29tbWVuZGVyIHN5c3RlbXMsCnN1Y2ggdGhvc2UgdXNlZCBmb3IgU3BvdGlmeSwgcmVseSBvbiBtYW55IGRpZmZlcmVudCBmZWF0dXJlcyBpbiBvcmRlciB0byBkZXRlY3QgCmVtb3Rpb24gaW4gdHJhY2tzIGFuZCBtYWtlIHNpbWlsYXIgc3VnZ2VzdGlvbnMuIFdlIHdpbGwgY3JlYXRlIGEgZmlndXJlIGJhc2VkIG9uClJ1c3NlbGwncyBNb2RlbCB0aGF0IG1hcHMgYWxsIHRyYWNrcyBmcm9tIHlvdXIgVG9wIDMgaW50byBmb3VyIGRpZmZlcmVudCBlbW90aW9uYWwKcXVhZHJhbnRzOiBIYXBweSwgQW5ncnksIFNhZCwgYW5kIFJlbGF4ZWQuCgpgYGB7ciBlY2hvPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGh0bWx3aWRnZXRzKQplbW90aW9uYWxRdWFkcmFudCA8LSBnZ3Bsb3QoZGF0YSA9IHRvcDMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB2YWxlbmNlLCB5ID0gZW5lcmd5LCBjb2xvciA9IGFydGlzdF9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBwYXN0ZSgiU29uZzoiLCB0cmFja19uYW1lLCAiXG5BcnRpc3Q6IiwgYXJ0aXN0X25hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbkVuZXJneToiLCBlbmVyZ3ksICJcblZhbGVuY2U6IiwgdmFsZW5jZSkpKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC41KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCksIGxpbWl0cyA9IGMoMCwgMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSwgbGltaXRzID0gYygwLCAxKSkgKwogIGFubm90YXRlKCd0ZXh0JywgMC4yNSAvIDIsIDAuOTUsIGxhYmVsID0gIkFuZ3J5IC8gVGVuc2UiKSArCiAgYW5ub3RhdGUoJ3RleHQnLCAxLjc1IC8gMiwgMC45NSwgbGFiZWwgPSAiSGFwcHkgLyBKb3lmdWwiKSArCiAgYW5ub3RhdGUoJ3RleHQnLCAxLjc1IC8gMiwgMC4wNSwgbGFiZWwgPSAiUmVsYXhlZCAvIENhbG0iKSArCiAgYW5ub3RhdGUoJ3RleHQnLCAwLjI1IC8gMiwgMC4wNSwgbGFiZWwgPSAiU2FkIC8gRGVwcmVzc2luZyIpICsKICBsYWJzKHggPSAiVmFsZW5jZSIsIHkgPSAiRW5lcmd5IiwgY29sb3IgPSAiQXJ0aXN0IE5hbWUiKSArCiAgZ2d0aXRsZSgiTXVzaWMgRW1vdGlvbiBNYXAgZm9yIFlvdXIgVG9wIDMgQXJ0aXN0cyBvZiBBbGwgVGltZSIsICJCYXNlZCBvbiBFbmVyZ3kgYW5kIFZhbGVuY2UiKSAgCgpxdWFkIDwtIGdncGxvdGx5KGVtb3Rpb25hbFF1YWRyYW50LCB0b29sdGlwID0gInRleHQiKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9Cmh0bWx3aWRnZXRzOjpzYXZlV2lkZ2V0KHF1YWQsICJpbmRleC5odG1sIikKCmh0bWx0b29sczo6dGFncyRpZnJhbWUoCiAgc3JjPWZpbGUucGF0aChnZXR3ZCgpLCAiaW5kZXguaHRtbCIpLAogIHdpZHRoPSIxMDAlIiwKICBoZWlnaHQ9IjYwMCIsCiAgc2Nyb2xsaW5nPSJubyIsCiAgc2VhbWxlc3M9InNlYW1sZXNzIiwKICBmcmFtZUJvcmRlcj0iMCIKKQoKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQpxdWFkcmFudF9udW0gPC0gYygxLCAyLCAzLCA0KQpuYW1lIDwtIGMoImhhcHB5IiwgImFuZ3J5IiwgInNhZCIsICJyZWxheGVkIikKZGYgPC0gZGF0YS5mcmFtZShxdWFkcmFudF9udW0sIG5hbWUpCgpxdWFkcmFudHMgPC0gdG9wMyAlPiUKICBzZWxlY3QoYXJ0aXN0X25hbWUsIGVuZXJneSwgdmFsZW5jZSkgJT4lCiAgbXV0YXRlKHF1YWRyYW50ID0gaWZlbHNlKGVuZXJneSA+PSAwLjUgJiB2YWxlbmNlID49IDAuNSwgMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlbmVyZ3kgPj0gMC41ICYgdmFsZW5jZSA8IDAuNSwgMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlbmVyZ3kgPCAwLjUgJiB2YWxlbmNlIDwgMC41LCAzLCA0KSkpKSAlPiUKICBncm91cF9ieShxdWFkcmFudCkgJT4lCiAgc3VtbWFyaXplKHF1YWRyYW50X2NvdW50ID0gbigpKSAlPiUKICBsZWZ0X2pvaW4oZGYsIGJ5ID0gYygicXVhZHJhbnQiID0gInF1YWRyYW50X251bSIpKSAlPiUKICBhcnJhbmdlKGRlc2MocXVhZHJhbnRfY291bnQpKQoKdG9wRW1vdGlvbiA8LSBxdWFkcmFudHMgJT4lCiAgc2xpY2UoMSkKdG9wRW1vdGlvbgpgYGAKVGFrZSBhIG1vbWVudCB0byBjaGVjayBvdXQgd2hpY2ggdHJhY2tzIGFyZSBpbiBlYWNoIGNhdGVnb3J5LiBEbyB5b3UgYWdyZWUgd2l0aCB0aGUgcmVzdWx0cz8KWW91ciBUb3AgMyBhcnRpc3RzIGNvbGxlY3RpdmVseSBoYXZlIGByIHF1YWRyYW50cyRxdWFkcmFudF9jb3VudFsxXWAgdHJhY2tzIGNhdGVnb3JpemVkIGFzCmByIHF1YWRyYW50cyRuYW1lWzFdYCwgYHIgcXVhZHJhbnRzJHF1YWRyYW50X2NvdW50WzJdYCBhcyBgciBxdWFkcmFudHMkbmFtZVsyXWAsIApgciBxdWFkcmFudHMkcXVhZHJhbnRfY291bnRbM11gIGFzIGByIHF1YWRyYW50cyRuYW1lWzNdYCwgYW5kIApgciBxdWFkcmFudHMkcXVhZHJhbnRfY291bnRbNF1gIGFzIGByIHF1YWRyYW50cyRuYW1lWzRdYC4gWW91J3JlIGludG8gc29tZSBwcmV0dHkKYHIgdG9wRW1vdGlvbiRuYW1lWzFdYCBtdXNpYyEKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CnRpdGxlRW1vdGlvbiA8LSBpZmVsc2UodG9wRW1vdGlvbiRuYW1lWzFdID09ICJoYXBweSIsICJIYXBwaWVzdCIsCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRvcEVtb3Rpb24kbmFtZVsxXSA9PSAiYW5ncnkiLCAiQW5ncmllc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UodG9wRW1vdGlvbiRuYW1lWzFdID09ICJzYWQiLCAiU2FkZGVzdCIsICJNb3N0IFJlbGF4ZWQiKSkpCnRpdGxlRW1vdGlvbgpgYGAKCkxldCdzIGRvIHNvbWUgcXVpY2sgY2FsY3VsYXRpb25zLgpgYGB7ciBlY2hvPUZBTFNFfQpzb25nQ291bnQgPC0gdG9wMyAlPiUKICBncm91cF9ieShhcnRpc3RfbmFtZSkgJT4lCiAgc3VtbWFyaXplKHRvdGFsU29uZ0NvdW50ID0gbigpKQoKcGVyY2VudGFnZSA8LSB0b3AzICU+JQogIHNlbGVjdChhcnRpc3RfbmFtZSwgZW5lcmd5LCB2YWxlbmNlLCBkdXJhdGlvbl9tcykgJT4lCiAgbXV0YXRlKHF1YWRyYW50ID0gaWZlbHNlKGVuZXJneSA+PSAwLjUgJiB2YWxlbmNlID49IDAuNSwgMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlbmVyZ3kgPj0gMC41ICYgdmFsZW5jZSA8IDAuNSwgMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlbmVyZ3kgPCAwLjUgJiB2YWxlbmNlIDwgMC41LCAzLCA0KSkpKSAlPiUKICBmaWx0ZXIocXVhZHJhbnQgJWluJSBjKHRvcEVtb3Rpb24kcXVhZHJhbnRbMV0pKSAlPiUKICBncm91cF9ieShhcnRpc3RfbmFtZSkgJT4lCiAgc3VtbWFyaXplKGNvdW50ID0gbigpKSAlPiUKICBsZWZ0X2pvaW4oc29uZ0NvdW50LCBieSA9IGMoImFydGlzdF9uYW1lIikpICU+JQogIG11dGF0ZShwZXJjSW5RdWFkID0gKGNvdW50IC8gdG90YWxTb25nQ291bnQpICogMTAwKSAlPiUKICBhcnJhbmdlKGRlc2MocGVyY0luUXVhZCkpICU+JQogIHNlbGVjdChhcnRpc3RfbmFtZSwgcGVyY0luUXVhZCkgJT4lCiAgcmVuYW1lKCJBcnRpc3QgTmFtZSIgPSBhcnRpc3RfbmFtZSwgIlBlcmNlbnQgb2YgYWxsIFNvbmdzIGluIFRvcCBRdWFkcmFudCIgPSBwZXJjSW5RdWFkKQoKZm9ybWF0dGFibGUocGVyY2VudGFnZSwgCiAgICAgICAgICAgIGFsaWduID0gYygibCIsICJsIikpCgphcnRpc3QgPC0gcGVyY2VudGFnZSRgQXJ0aXN0IE5hbWVgWzFdCmBgYApMb29rcyBsaWtlICoqYHIgYXJ0aXN0YCoqIGlzIHlvdXIgYHIgdGl0bGVFbW90aW9uYCBBcnRpc3QhIGByIGFydGlzdGAgaGFzIHRoZSBncmVhdGVzdApudW1iZXIgb2Ygc29uZ3MgaW4gdGhlaXIgZGlzY29ncmFwaHkgY2F0ZWdvcml6ZWQgYXMgYHIgdG9wRW1vdGlvbiRuYW1lWzFdYCBiYXNlZCBvbgp0aGUgZW5lcmd5IHRvIHZhbGVuY2UgcmF0aW8gb2YgdGhlIHRyYWNrcyBjb21wYXJlZCB0byB5b3VyIG90aGVyIHR3byB0b3AgYXJ0aXN0cy4gIAoKIyMjIyBTZW50aW1lbnQgQW5hbHlzaXMKTGV0J3MgdXNlIHRoZSBwYWNrYWdlICpnZW5pdXNyKiB0byBpbnRlcmFjdCB3aXRoIHRoZSBbR2VuaXVzIEFQSV0oaHR0cHM6Ly9kb2NzLmdlbml1cy5jb20pCnRvIGlkZW50aWZ5IHRoZSBkb21pbmFudCBzZW50aW1lbnQgcHJlc2VudCBpbiB0aGUgc29uZ3Mgb2YgeW91ciBmYXZvcml0ZSBhcnRpc3RzLiBXZSB3aWxsCnVzZSB0aGUgKnRpZHl0ZXh0KiBwYWNrYWdlIHRvIGFuYWx5emUgdGhlIHNlbnRpbWVudCBvZiB0aGUgbHlyaWNzIGJ5IGlkZW50aWZ5aW5nIHRoZSAKc2VudGltZW50IGNvbnRlbnQgb2YgdGhlIGluZGl2aWR1YWwgd29yZHMuIFRoZSBnZW5lcmFsLXB1cnBvc2UgbGV4aWNvbiB1dGlsaXplZCB0byBpZGVudGlmeQplbW90aW9ucyBpcyBjYWxsZWQgKmJpbmcqLCB3aGljaCBjb250YWlucyB0aG91c2FuZHMgb2Ygd29yZHMgdGhhdCBhcmUgYXNzaWduZWQgZW1vdGlvbnMgc3VjaAphcyBqb3ksIGFuZ2VyLCBhbnRpY2lwYXRpb24sIGFuZCBzYWRuZXNzLiBXZSB3aWxsIGFuYWx5emUgdGhlIHNlbnRpbWVudCBpbiB0aGUgbW9zdCByZWNlbnQKYWxidW0gb2YgeW91ciB0b3AgYXJ0aXN0IGZyb20gdGhlIHBhc3QgbW9udGguIAoKYGBge3IgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShnZW5pdXNyKQoKZ2VuaXVzX2FjY2Vzc190b2tlbiA9ICJVeHN5alJreWFWYVc2cGZ4YncyNHIzQ0pfTGJtUTBhNFlwY3F5SnFtZ01oeWJoQlRhNXBRTkstVFYzbGN4X3B1IgoKcG9wdWxhckFydGlzdElkIDwtIHNlYXJjaF9zcG90aWZ5KAogIHEgPSB0b3AxMEFydGlzdHNFdmVyJGBQYXN0IE1vbnRoYFsxXSwKICB0eXBlID0gYygiYXJ0aXN0IiksCiAgbWFya2V0ID0gTlVMTCwKICBsaW1pdCA9IDEsCiAgb2Zmc2V0ID0gMCwKICBpbmNsdWRlX2V4dGVybmFsID0gTlVMTCwKICBhdXRob3JpemF0aW9uID0gZ2V0X3Nwb3RpZnlfYWNjZXNzX3Rva2VuKCksCiAgaW5jbHVkZV9tZXRhX2luZm8gPSBGQUxTRSkkaWQKCmFsYnVtIDwtIGdldF9hcnRpc3RfYWxidW1zKAogIGlkID0gcG9wdWxhckFydGlzdElkLAogIGluY2x1ZGVfZ3JvdXBzID0gYygiYWxidW0iLCAic2luZ2xlIiksCiAgbWFya2V0ID0gIlVTIiwKICBsaW1pdCA9IDIwLAogIG9mZnNldCA9IDAsCiAgYXV0aG9yaXphdGlvbiA9IGdldF9zcG90aWZ5X2FjY2Vzc190b2tlbigpLAogIGluY2x1ZGVfbWV0YV9pbmZvID0gRkFMU0UpCgp0cmFja3MgPC0gZ2V0X2FsYnVtX3RyYWNrcygKICBpZCA9IGFsYnVtJGlkWzFdLAogIGxpbWl0ID0gMjAsCiAgb2Zmc2V0ID0gMCwKICBtYXJrZXQgPSBOVUxMLAogIGF1dGhvcml6YXRpb24gPSBnZXRfc3BvdGlmeV9hY2Nlc3NfdG9rZW4oKSwKICBpbmNsdWRlX21ldGFfaW5mbyA9IEZBTFNFKQoKYXJ0aXN0X2lkIDwtIHNlYXJjaF9hcnRpc3QodG9wMTBBcnRpc3RzRXZlciRgUGFzdCBNb250aGBbMV0sIG5fcmVzdWx0cyA9IDEwLCBhY2Nlc3NfdG9rZW4gPSBnZW5pdXNfYWNjZXNzX3Rva2VuKSRhcnRpc3RfaWRbMV0KCnNvbmdzIDwtIGdldF9hcnRpc3Rfc29uZ3NfZGYoCiAgYXJ0aXN0X2lkLAogIHNvcnQgPSBjKCJ0aXRsZSIsICJwb3B1bGFyaXR5IiksCiAgaW5jbHVkZV9mZWF0dXJlcyA9IEZBTFNFLAogIGFjY2Vzc190b2tlbiA9IGdlbml1c19hY2Nlc3NfdG9rZW4pCgpzb25nc0ZpbmFsIDwtIHNvbmdzICU+JQogIGlubmVyX2pvaW4odHJhY2tzLCBieSA9IGMoInNvbmdfbmFtZSIgPSAibmFtZSIpKSAlPiUKICBzZWxlY3Qoc29uZ19pZCwgaWQsIHNvbmdfbmFtZSwgZHVyYXRpb25fbXMsIHNvbmdfbHlyaWNzX3VybCkgJT4lCiAgcmVuYW1lKGdlbml1c19pZCA9IHNvbmdfaWQsIHNwb3RpZnlfaWQgPSBpZCkKYGBgCgpgYGB7ciBpbmNsdWRlPUZBTFNFfQpseXJpY3MgPC0gYygpCmZvciAoaSBpbiAxOjE1KSB7CiAgI2ZvciAoaSBpbiAxOmxlbmd0aChzb25nc0ZpbmFsJHNvbmdfbmFtZSkpIHsKICBjdXJyZW50IDwtIGdldF9seXJpY3NfaWQoc29uZ3NGaW5hbCRnZW5pdXNfaWRbaV0sIGFjY2Vzc190b2tlbiA9IGdlbml1c19hY2Nlc3NfdG9rZW4pCiAgI3ByaW50KGN1cnJlbnQpCiAgY3VycmVudCA8LSBjdXJyZW50ICU+JQogICAgc2VsZWN0KGxpbmUsIHNvbmdfbmFtZSkKICBwcmludChjdXJyZW50KQogIGlmIChpcy5uYShjdXJyZW50JGxpbmVbMV0pKSB7CiAgICBuZXh0CiAgfSBlbHNlIHsKICAgIGx5cmljcyA8LSByYmluZChseXJpY3MsIGN1cnJlbnQpCiAgfQp9Cmx5cmljcwpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkodGV4dGRhdGEpCgpucmMgPC0gZ2V0X3NlbnRpbWVudHMoIm5yYyIpCmJpbmcgPC0gZ2V0X3NlbnRpbWVudHMoImJpbmciKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmxpYnJhcnkoZm9yY2F0cykKdG9rZW5pemVkIDwtIGx5cmljcyAlPiUKICB1bm5lc3RfdG9rZW5zKHdvcmQsIGxpbmUpCgpucmNfc2VudGltZW50cyA8LSBucmMgJT4lCiAgZmlsdGVyKCFzZW50aW1lbnQgJWluJSBjKCJwb3NpdGl2ZSIsICJuZWdhdGl2ZSIpKSAKCnRvcDNTZW50aW1lbnRzIDwtIHRva2VuaXplZCAlPiUKICBpbm5lcl9qb2luKG5yY19zZW50aW1lbnRzLCBieSA9IGMoIndvcmQiKSkgJT4lCiAgZ3JvdXBfYnkoc2VudGltZW50KSAlPiUKICBzdW1tYXJpemUoY291bnQgPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhjb3VudCkpICU+JQogIHNsaWNlKDE6MykKCm1ha2VHcmFwaHMgPC0gZnVuY3Rpb24oaSkgewogIAp9CgpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShncmlkKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobGF0dGljZSkKcGxvdHMgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTozKSB7CiAgbmFtIDwtIHBhc3RlKCJBIiwgaSwgc2VwID0gIiIpCiAgcCA8LSB0b2tlbml6ZWQgJT4lCiAgICBpbm5lcl9qb2luKG5yY19zZW50aW1lbnRzLCBieSA9IGMoIndvcmQiKSkgJT4lCiAgICBmaWx0ZXIoc2VudGltZW50ICVpbiUgYyh0b3AzU2VudGltZW50cyRzZW50aW1lbnRbaV0pKSAlPiUKICAgIGdyb3VwX2J5KHNvbmdfbmFtZSkgJT4lCiAgICBzdW1tYXJpemUoY291bnQgPSBuKCkpICU+JQogICAgYXJyYW5nZShjb3VudCkgJT4lIAogICAgdW5ncm91cCgpICU+JQogICAgZ2dwbG90KGFlcyhjb3VudCwgZmN0X2lub3JkZXIoc29uZ19uYW1lKSkpICsKICAgICAgZ2VvbV9jb2woKSArCiAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKwogICAgICBsYWJzKHggPSAiQ291bnQiLAogICAgICAgICAgIHkgPSAiU29uZ3MiLAogICAgICAgICAgIHRpdGxlID0gcGFzdGUoIkNvdW50cyBvZiB3b3JkcyB3aXRoIiwgdG9wM1NlbnRpbWVudHMkc2VudGltZW50W2ldLCAic2VudGltZW50XG4gaW4gdHJhY2tzIGZyb20iLAogICAgICAgICAgICAgICAgICAgICAgICAgYWxidW0kbmFtZSwgc2VwID0gIiAiLCBjb2xsYXBzZSA9IE5VTEwpKSArIAogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTgpKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogICAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKwogICAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICAKICBhc3NpZ24obmFtLCBwKQp9CmdyaWQuYXJyYW5nZShBMSwgQTIsIEEzLCBucm93ID0gMikKYGBgCgojIyMjIFJlY29tbWVuZGF0aW9ucwpBIHNwZWNpYWwgcGxheWxpc3QgY3VyYXRlZCBqdXN0IGZvciB5b3UgaGFzIGJlZW4gdXBsb2FkZWQgdG8geW91ciBTcG90aWZ5IGFjY291bnQuCkhhcHB5IGxpc3RlbmluZyEKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CnRvcFRyYWNrcyA8LSBnZXRfbXlfdG9wX2FydGlzdHNfb3JfdHJhY2tzKAogIHR5cGUgPSAidHJhY2tzIiwKICBsaW1pdCA9IDI1LAogIG9mZnNldCA9IDAsCiAgdGltZV9yYW5nZSA9ICJtZWRpdW1fdGVybSIsCiAgYXV0aG9yaXphdGlvbiA9IGdldF9zcG90aWZ5X2F1dGhvcml6YXRpb25fY29kZSgpLAogIGluY2x1ZGVfbWV0YV9pbmZvID0gRkFMU0UpCgpyZWNzIDwtIGdldF9yZWNvbW1lbmRhdGlvbnNfYWxsKHRyYWNrX2lkcyA9IHRvcFRyYWNrcyRpZCkKbXlJRCA8LSBnZXRfbXlfcHJvZmlsZShhdXRob3JpemF0aW9uID0gZ2V0X3Nwb3RpZnlfYXV0aG9yaXphdGlvbl9jb2RlKCkpJGlkCgpwbGF5bGlzdElEIDwtIGNyZWF0ZV9wbGF5bGlzdCgKICB1c2VyX2lkID0gbXlJRCwKICBuYW1lID0gIkEgc3BlY2lhbCBwbGF5bGlzdCBqdXN0IGZvciB5b3UhIiwKICBwdWJsaWMgPSBUUlVFLAogIGNvbGxhYm9yYXRpdmUgPSBGQUxTRSwKICBkZXNjcmlwdGlvbiA9ICJIYXBweSBsaXN0ZW5pbmchIDwzIEFuZ2VsYSIsCiAgYXV0aG9yaXphdGlvbiA9IGdldF9zcG90aWZ5X2F1dGhvcml6YXRpb25fY29kZSgpKSRpZAoKYWRkX3RyYWNrc190b19wbGF5bGlzdCgKICBwbGF5bGlzdF9pZCA9IHBsYXlsaXN0SUQsCiAgdXJpcyA9IHJlY3MkaWQsCiAgcG9zaXRpb24gPSBOVUxMLAogIGF1dGhvcml6YXRpb24gPSBnZXRfc3BvdGlmeV9hdXRob3JpemF0aW9uX2NvZGUoKSkKYGBgCgoKYGBge3IgaW5jbHVkZT1GQUxTRX0KI1NvdXJjZXMKI2h0dHBzOi8vbXNtaXRoNzE2MS5naXRodWIuaW8vd2hhdC1pcy1zcGVlY2hpbmVzcy8KI2h0dHBzOi8vd3d3LmRhdGFub3ZpYS5jb20vZW4vYmxvZy9iZWF1dGlmdWwtcmFkYXItY2hhcnQtaW4tci11c2luZy1mbXNiLWFuZC1nZ3Bsb3QtcGFja2FnZXMvCiNodHRwczovL3d3dzguZ3NiLmNvbHVtYmlhLmVkdS9hcnRpY2xlcy9wcm9qZWN0cy93aGF0LW1ha2VzLWEtaGl0LwojaHR0cHM6Ly9pbnRybzJyLmNvbS9yLW1hcmtkb3duLWFuYXRvbXkuaHRtbAojaHR0cHM6Ly93d3cuZGF0YS10by12aXouY29tL2NhdmVhdC9zcGlkZXIuaHRtbAojaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL3VkYWNpdHktaG9zdGVkLWRvd25sb2Fkcy91ZDY1MS9HZW9ncmFwaHlPZkFtZXJpY2FuTXVzaWMuaHRtbAojaHR0cHM6Ly93d3cucnN0dWRpby5jb20vYmxvZy9yLW1hcmtkb3duLXRpcHMtdHJpY2tzLTQtbG9va3MtYmV0dGVyLXdvcmtzLWJldHRlci8KI2h0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9leHBsb3JlLXlvdXItYWN0aXZpdHktb24tc3BvdGlmeS13aXRoLXItYW5kLXNwb3RpZnlyLWhvdy10by1hbmFseXplLWFuZC12aXN1YWxpemUteW91ci1zdHJlYW0tZGVlNDFjYjYzNTI2CiNodHRwczovL2VkZW4uZGVpLnVjLnB0L35ydWlwZWRyby9wdWJsaWNhdGlvbnMvQ29uZmVyZW5jZXMvU01DXzIwMjFfUGFuZGEucGRmCiNodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vZXhwbG9yZS15b3VyLWFjdGl2aXR5LW9uLXNwb3RpZnktd2l0aC1yLWFuZC1zcG90aWZ5ci1ob3ctdG8tYW5hbHl6ZS1hbmQtdmlzdWFsaXplLXlvdXItc3RyZWFtLWRlZTQxY2I2MzUyNgojaHR0cHM6Ly9pZWVleHBsb3JlLmllZWUub3JnL2Fic3RyYWN0L2RvY3VtZW50Lzk4MjM1MzUvZmlndXJlcyNmaWd1cmVzCiNodHRwczovL2xpbmsuc3ByaW5nZXIuY29tL2NoYXB0ZXIvMTAuMTAwNy85NzgtMy0zMTktNDUzNzgtMV82MAojaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DODg2MDUxOC8KI2h0dHBzOi8vbWVkaXVtLmNvbS9tY2QtdW5pc29uL3VzaW5nLXRoZS1odHRyLXBhY2thZ2UtaW4tci10by1nZXQtYXVkaW8tZmVhdHVyZXMtZnJvbS1zcG90aWZ5LWFwaS02ODU4NzI2MmIyYzcKI2h0dHBzOi8vd3d3LnRpZHl0ZXh0bWluaW5nLmNvbS9zZW50aW1lbnQuaHRtbApgYGAKCgoKCgoKCgoKCgoKCgoKCgoK