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.
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