Introduction

This document is to explore a bit more what the students experience might be like, in terms of “releasing songs.” It adopts the conceit that all songs are released on the same day, and so you can go back in time and release more songs on that day. More on this later – not yet making an argument for it, just I didn’t have time to code a simulation with different release dates.

What is modeled here:

  1. there are three genres, pop, rock, and jazz. Each has a different value for its first week listens and its duration in number of weeks. Then noise is added, so the individual songs vary.

  2. Songs can be “on trend” or not. As it stands, a trend kicks in on week 6 and lasts for 4 weeks, and it favors “sad” songs. So sad songs get a boost during that time.

  3. There are two types of plots, one type with individual songs and another that averages by genre. The code for averaging by genre doesn’t seem to be working right, and I haven’t had time to fix it. But at least you can look at the graph.

The command “make song data” is like building and releasing a song.

Just to be clear, I don’t really care if we end up using my model or not. I just want to get to a place where I believe we can create semi-random songs with discernable patterns to them, based on their characteristics.

Constants

This next section is setting up constants used in the simulations. There are three genres of songs, POP, ROCK, and JAZZ. Each starts wwith a different number of listens on week 1: 50 for POP, 25 for ROCK, and 20 for JAZZ. Each has a duration in weeks that it lasts. This is set to 8, 12, and 4 weeks respectively. The simulation can easily be modified by changing these parameters.

POP <- "pop"
JAZZ <- "jazz"
ROCK <- "rock"
HAPPY <- "happy"
SAD  <- "sad"
name_vector <- c(POP,ROCK,JAZZ)
starts <- c(50, 25, 20)
names(starts) <- name_vector
durations <- c(8,12,4)
names(durations) <- name_vector

Simulation set up

The code in here is based on my first file, so if you want to understand how it works, go there. Otherwise skip over this.

library(tidyverse)
# maximum number of weeks a song lasts, e.g. the length of the simulation in weeks
MAX_DURATION <- 16 
# standard deviation, around a mean value of 1, for the amount of noise
# .25 seems to be a pretty good value
RANDOMNESS_FACTOR <- .25
# creates a declining slope to 0
generate_decline <- function(last_week,max_weeks) {
  # initialize to all zeros
  result <- rep(0,max_weeks) 
  # add the declining sequence, needs to be one longer, because the decline includes zero
  result[1:(last_week+1)] <- seq(1,0,length.out=(last_week+1))
  result
}
# trend boost vector, starting in the 6th week and lasting four weeks
trend_boost <- c(rep(1,length.out=5),
                 rep(3,length.out=4),
                 rep(1,length.out=MAX_DURATION - 9))
clear_song_data <- function() {
  data.frame(song_name=character(),
             song_trend=logical(),
             song_genre=character(),
             week=integer(),
             listens = integer(), 
             cumulative_listens=integer())
}
make_song_data <- function (name,genre,trend) {
  
  # retrieve parameters from the vector, based on the genre.
  start_at <- starts[genre]
  duration <- durations[genre]
 # randomness is a vector with a random multiplier for each week
 randomness <- rnorm(MAX_DURATION,mean=1,sd=RANDOMNESS_FACTOR)
 
 # this is a vector of declining values
 declining <- generate_decline(duration,MAX_DURATION)
 
 # our vector of listens multiplies a flat initial value by randomness by declining
 listens <- start_at * randomness * declining
 
 # add the effect of the trend, if the song is effected by the trend, again multiplying
 if (trend) listens <- trend_boost * listens
 
 #make these into integers
 listens <- floor (listens)
                      
 # we use this built-in R function, cumsum, to accumulate the listens
 cum_listens <- cumsum(listens)
 #ok, now we can make a dataframe for this song, and add it to our overall dataframe
 data.frame(song_name = name,
            song_genre = genre,
            song_trend = trend,
            week = 1:MAX_DURATION,
            listens = listens,
            cumulative_listens = cum_listens)
}
plot_songs <- function (song_data) {
  ggplot() +
        geom_col(data=song_data,aes(x=week,y=listens,fill=song_genre)) + 
        geom_smooth(data=song_data,aes(x=week,y=listens,fill=song_name),
                    fill=NA,color="dimgray",method="loess") +
        geom_col(data=trend_df,aes(x=week,y=trend)) +
        coord_cartesian(ylim=c(0,80)) +
        facet_wrap( ~ song_name)
}
 
plot_genre <- function (song_data) {
  
   grouped_data <-  song_data %>% 
                  group_by(song_genre, week) %>%
                  summarize(mean_listens = mean(listens))
 ggplot() +
        geom_col(data=grouped_data,aes(x=week,y=mean_listens,fill=song_genre)) + 
        geom_smooth(data=grouped_data,aes(x=week,y=mean_listens),
                    fill=NA,color="dimgray",method="loess") +
        geom_col(data=trend_df,aes(x=week,y=trend)) +
        coord_cartesian(ylim=c(0,80)) +
        facet_wrap( ~ song_genre)
 
}

let’s start exploring

First, I’ll make one pop song, called “pop yer”, with genre “pop” and no response to trend And also one rock song. And one jazz song.

Can you see which genre of song tends to have more initial listens? Which lasts longer on the charts?

song_listens_df= suppressWarnings(
  bind_rows(
      make_song_data("pop yer",POP,FALSE),
      make_song_data("rock on",ROCK,FALSE),
      make_song_data("jazzy jones",JAZZ,FALSE)
  ))
plot_songs(song_listens_df)

An Idea: pop songs are better.

Since I’m going to add release more pop songs to see if they seem all to be taller…

song_listens_df= suppressWarnings(
  bind_rows(
      song_listens_df,
      make_song_data("pop wop",POP,FALSE),
      make_song_data("pop a lot",POP,FALSE),
      make_song_data("pop be gone ",POP,FALSE),
  ))
plot_songs(song_listens_df)

yes, it seems to me that pop songs all follow a similar pattern. and it looks different from rock songs.

But just to be sure, let’s plot ALL the pop songs (on average vs. our rock song). Please note that this did not seem to work quite right. I’m not sure why, but the averages for pop should be higher. Anyway, the point is a plot by genre type.

plot_genre(song_listens_df)

So that last plot above is the AVERAGE of all the POP song listens against the average of all the rock and jazz song listens – but there’s only one rock and one jazz song.

Reflections

Based on this experiment, I am thinking we need to be careful about the level of pattern finding we are expecting of students. There’s a lot going on in these graphs, and they aren’t necessarily all that easy to read. Just reading one features off the graphs might be an accomplishment.

I do somewhat favor using bars for the number of song listens in a week, rather than going immediately to lines. I think a tall bar for a lot of listens may be easier for a kid to make sense of. I find the smoothed lines summarizing each bar very helpful to my interpretation – much better than lines connecting the tops.

I didn’t yet make a simulation that shows songs being released at different times, but you can imagine it my mentally shifting some of the plots to the right. That being said, it may be asking quite a lot of students for them to make sense of data based on phenomena that start at different points in time. I am wondering whether there should be:

  1. a game context which has a turn-by-turn flow of time, and this is where you earn dollars/followers/scores

  2. but a simpler context wtih a simpler flow of time where you can conduct experiments with less going on. The idea would be that what you learn from b might inform a.

I also wondered about the complexity of our thoughts about trends. We may need to simply this so that only certain trends (changing in time during the game) matter and there are just a few. I was thinking that the properties of genres stay pretty fixed. All the variability would be in response to mood or topic. And I was thinking that we might want to simplify these so that there is one topic and one mood which occassionally is “on trend” but the other ones are just neutral. Hence, perhaps happy songs almost perform about the same, but sad songs periodically get a big boost. I was just getting worried that if everything is potentially changing, it could take a long time to figure it all out.

LS0tCnRpdGxlOiAiTXVzaWMgR2FtZSAtLSBTaW11bGF0ZWQgRXhwZXJpZW5jZSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBJbnRyb2R1Y3Rpb24KClRoaXMgZG9jdW1lbnQgaXMgdG8gZXhwbG9yZSBhIGJpdCBtb3JlIHdoYXQgdGhlIHN0dWRlbnRzIGV4cGVyaWVuY2UgbWlnaHQgYmUgbGlrZSwgaW4gdGVybXMgb2YgInJlbGVhc2luZyBzb25ncy4iIEl0IGFkb3B0cyB0aGUgY29uY2VpdCB0aGF0IGFsbCBzb25ncyBhcmUgcmVsZWFzZWQgb24gdGhlIHNhbWUgZGF5LCBhbmQgc28geW91IGNhbiBnbyBiYWNrIGluIHRpbWUgYW5kIHJlbGVhc2UgbW9yZSBzb25ncyBvbiB0aGF0IGRheS4gTW9yZSBvbiB0aGlzIGxhdGVyIC0tIG5vdCB5ZXQgbWFraW5nIGFuIGFyZ3VtZW50IGZvciBpdCwganVzdCBJIGRpZG4ndCBoYXZlIHRpbWUgdG8gY29kZSBhIHNpbXVsYXRpb24gd2l0aCBkaWZmZXJlbnQgcmVsZWFzZSBkYXRlcy4KCldoYXQgaXMgbW9kZWxlZCBoZXJlOgoKMS4gdGhlcmUgYXJlIHRocmVlIGdlbnJlcywgcG9wLCByb2NrLCBhbmQgamF6ei4gRWFjaCBoYXMgYSBkaWZmZXJlbnQgdmFsdWUgZm9yIGl0cyBmaXJzdCB3ZWVrIGxpc3RlbnMgYW5kIGl0cyBkdXJhdGlvbiBpbiBudW1iZXIgb2Ygd2Vla3MuIFRoZW4gbm9pc2UgaXMgYWRkZWQsIHNvIHRoZSBpbmRpdmlkdWFsIHNvbmdzIHZhcnkuIAoKMi4gU29uZ3MgY2FuIGJlICJvbiB0cmVuZCIgb3Igbm90LiBBcyBpdCBzdGFuZHMsIGEgdHJlbmQga2lja3MgaW4gb24gd2VlayA2IGFuZCBsYXN0cyBmb3IgNCB3ZWVrcywgYW5kIGl0IGZhdm9ycyAic2FkIiBzb25ncy4gU28gc2FkIHNvbmdzIGdldCBhIGJvb3N0IGR1cmluZyB0aGF0IHRpbWUuCgozLiBUaGVyZSBhcmUgdHdvIHR5cGVzIG9mIHBsb3RzLCBvbmUgdHlwZSB3aXRoIGluZGl2aWR1YWwgc29uZ3MgYW5kIGFub3RoZXIgdGhhdCBhdmVyYWdlcyBieSBnZW5yZS4gVGhlIGNvZGUgZm9yIGF2ZXJhZ2luZyBieSBnZW5yZSBkb2Vzbid0IHNlZW0gdG8gYmUgd29ya2luZyByaWdodCwgYW5kIEkgaGF2ZW4ndCBoYWQgdGltZSB0byBmaXggaXQuIEJ1dCBhdCBsZWFzdCB5b3UgY2FuIGxvb2sgYXQgdGhlIGdyYXBoLiAKClRoZSBjb21tYW5kICJtYWtlIHNvbmcgZGF0YSIgaXMgbGlrZSBidWlsZGluZyBhbmQgcmVsZWFzaW5nIGEgc29uZy4KCkp1c3QgdG8gYmUgY2xlYXIsIEkgZG9uJ3QgcmVhbGx5IGNhcmUgaWYgd2UgZW5kIHVwIHVzaW5nIG15IG1vZGVsIG9yIG5vdC4gSSBqdXN0IHdhbnQgdG8gZ2V0IHRvIGEgcGxhY2Ugd2hlcmUgSSBiZWxpZXZlIHdlIGNhbiBjcmVhdGUgc2VtaS1yYW5kb20gc29uZ3Mgd2l0aCBkaXNjZXJuYWJsZSBwYXR0ZXJucyB0byB0aGVtLCBiYXNlZCBvbiB0aGVpciBjaGFyYWN0ZXJpc3RpY3MuCgoKIyBDb25zdGFudHMKClRoaXMgbmV4dCBzZWN0aW9uIGlzIHNldHRpbmcgdXAgY29uc3RhbnRzIHVzZWQgaW4gdGhlIHNpbXVsYXRpb25zLiBUaGVyZSBhcmUgdGhyZWUgZ2VucmVzIG9mIHNvbmdzLCBQT1AsIFJPQ0ssIGFuZCBKQVpaLiBFYWNoIHN0YXJ0cyB3d2l0aCBhIGRpZmZlcmVudCBudW1iZXIgb2YgbGlzdGVucyBvbiB3ZWVrIDE6IDUwIGZvciBQT1AsIDI1IGZvciBST0NLLCBhbmQgMjAgZm9yIEpBWlouIEVhY2ggaGFzIGEgZHVyYXRpb24gaW4gd2Vla3MgdGhhdCBpdCBsYXN0cy4gVGhpcyBpcyBzZXQgdG8gOCwgMTIsIGFuZCA0IHdlZWtzIHJlc3BlY3RpdmVseS4gVGhlIHNpbXVsYXRpb24gY2FuIGVhc2lseSBiZSBtb2RpZmllZCBieSBjaGFuZ2luZyB0aGVzZSBwYXJhbWV0ZXJzLgoKCmBgYHtyfQoKUE9QIDwtICJwb3AiCkpBWlogPC0gImphenoiClJPQ0sgPC0gInJvY2siCkhBUFBZIDwtICJoYXBweSIKU0FEICA8LSAic2FkIgoKbmFtZV92ZWN0b3IgPC0gYyhQT1AsUk9DSyxKQVpaKQpzdGFydHMgPC0gYyg1MCwgMjUsIDIwKQpuYW1lcyhzdGFydHMpIDwtIG5hbWVfdmVjdG9yCmR1cmF0aW9ucyA8LSBjKDgsMTIsNCkKbmFtZXMoZHVyYXRpb25zKSA8LSBuYW1lX3ZlY3RvcgpgYGAKCgojIFNpbXVsYXRpb24gc2V0IHVwCgpUaGUgY29kZSBpbiBoZXJlIGlzIGJhc2VkIG9uIG15IGZpcnN0IGZpbGUsIHNvIGlmIHlvdSB3YW50IHRvIHVuZGVyc3RhbmQgaG93IGl0IHdvcmtzLCBnbyB0aGVyZS4gT3RoZXJ3aXNlIHNraXAgb3ZlciB0aGlzLgoKCmBgYHtyfQoKbGlicmFyeSh0aWR5dmVyc2UpCgojIG1heGltdW0gbnVtYmVyIG9mIHdlZWtzIGEgc29uZyBsYXN0cywgZS5nLiB0aGUgbGVuZ3RoIG9mIHRoZSBzaW11bGF0aW9uIGluIHdlZWtzCk1BWF9EVVJBVElPTiA8LSAxNiAKCiMgc3RhbmRhcmQgZGV2aWF0aW9uLCBhcm91bmQgYSBtZWFuIHZhbHVlIG9mIDEsIGZvciB0aGUgYW1vdW50IG9mIG5vaXNlCiMgLjI1IHNlZW1zIHRvIGJlIGEgcHJldHR5IGdvb2QgdmFsdWUKUkFORE9NTkVTU19GQUNUT1IgPC0gLjI1CgojIGNyZWF0ZXMgYSBkZWNsaW5pbmcgc2xvcGUgdG8gMApnZW5lcmF0ZV9kZWNsaW5lIDwtIGZ1bmN0aW9uKGxhc3Rfd2VlayxtYXhfd2Vla3MpIHsKICAjIGluaXRpYWxpemUgdG8gYWxsIHplcm9zCiAgcmVzdWx0IDwtIHJlcCgwLG1heF93ZWVrcykgCiAgIyBhZGQgdGhlIGRlY2xpbmluZyBzZXF1ZW5jZSwgbmVlZHMgdG8gYmUgb25lIGxvbmdlciwgYmVjYXVzZSB0aGUgZGVjbGluZSBpbmNsdWRlcyB6ZXJvCiAgcmVzdWx0WzE6KGxhc3Rfd2VlaysxKV0gPC0gc2VxKDEsMCxsZW5ndGgub3V0PShsYXN0X3dlZWsrMSkpCiAgcmVzdWx0Cn0KCiMgdHJlbmQgYm9vc3QgdmVjdG9yLCBzdGFydGluZyBpbiB0aGUgNnRoIHdlZWsgYW5kIGxhc3RpbmcgZm91ciB3ZWVrcwp0cmVuZF9ib29zdCA8LSBjKHJlcCgxLGxlbmd0aC5vdXQ9NSksCiAgICAgICAgICAgICAgICAgcmVwKDMsbGVuZ3RoLm91dD00KSwKICAgICAgICAgICAgICAgICByZXAoMSxsZW5ndGgub3V0PU1BWF9EVVJBVElPTiAtIDkpKQoKCmNsZWFyX3NvbmdfZGF0YSA8LSBmdW5jdGlvbigpIHsKICBkYXRhLmZyYW1lKHNvbmdfbmFtZT1jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgIHNvbmdfdHJlbmQ9bG9naWNhbCgpLAogICAgICAgICAgICAgc29uZ19nZW5yZT1jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgIHdlZWs9aW50ZWdlcigpLAogICAgICAgICAgICAgbGlzdGVucyA9IGludGVnZXIoKSwgCiAgICAgICAgICAgICBjdW11bGF0aXZlX2xpc3RlbnM9aW50ZWdlcigpKQp9CgptYWtlX3NvbmdfZGF0YSA8LSBmdW5jdGlvbiAobmFtZSxnZW5yZSx0cmVuZCkgewogIAogICMgcmV0cmlldmUgcGFyYW1ldGVycyBmcm9tIHRoZSB2ZWN0b3IsIGJhc2VkIG9uIHRoZSBnZW5yZS4KICBzdGFydF9hdCA8LSBzdGFydHNbZ2VucmVdCiAgZHVyYXRpb24gPC0gZHVyYXRpb25zW2dlbnJlXQoKICMgcmFuZG9tbmVzcyBpcyBhIHZlY3RvciB3aXRoIGEgcmFuZG9tIG11bHRpcGxpZXIgZm9yIGVhY2ggd2VlawogcmFuZG9tbmVzcyA8LSBybm9ybShNQVhfRFVSQVRJT04sbWVhbj0xLHNkPVJBTkRPTU5FU1NfRkFDVE9SKQogCiAjIHRoaXMgaXMgYSB2ZWN0b3Igb2YgZGVjbGluaW5nIHZhbHVlcwogZGVjbGluaW5nIDwtIGdlbmVyYXRlX2RlY2xpbmUoZHVyYXRpb24sTUFYX0RVUkFUSU9OKQogCiAjIG91ciB2ZWN0b3Igb2YgbGlzdGVucyBtdWx0aXBsaWVzIGEgZmxhdCBpbml0aWFsIHZhbHVlIGJ5IHJhbmRvbW5lc3MgYnkgZGVjbGluaW5nCiBsaXN0ZW5zIDwtIHN0YXJ0X2F0ICogcmFuZG9tbmVzcyAqIGRlY2xpbmluZwogCiAjIGFkZCB0aGUgZWZmZWN0IG9mIHRoZSB0cmVuZCwgaWYgdGhlIHNvbmcgaXMgZWZmZWN0ZWQgYnkgdGhlIHRyZW5kLCBhZ2FpbiBtdWx0aXBseWluZwogaWYgKHRyZW5kKSBsaXN0ZW5zIDwtIHRyZW5kX2Jvb3N0ICogbGlzdGVucwogCiAjbWFrZSB0aGVzZSBpbnRvIGludGVnZXJzCiBsaXN0ZW5zIDwtIGZsb29yIChsaXN0ZW5zKQogICAgICAgICAgICAgICAgICAgICAgCiAjIHdlIHVzZSB0aGlzIGJ1aWx0LWluIFIgZnVuY3Rpb24sIGN1bXN1bSwgdG8gYWNjdW11bGF0ZSB0aGUgbGlzdGVucwogY3VtX2xpc3RlbnMgPC0gY3Vtc3VtKGxpc3RlbnMpCgogI29rLCBub3cgd2UgY2FuIG1ha2UgYSBkYXRhZnJhbWUgZm9yIHRoaXMgc29uZywgYW5kIGFkZCBpdCB0byBvdXIgb3ZlcmFsbCBkYXRhZnJhbWUKIGRhdGEuZnJhbWUoc29uZ19uYW1lID0gbmFtZSwKICAgICAgICAgICAgc29uZ19nZW5yZSA9IGdlbnJlLAogICAgICAgICAgICBzb25nX3RyZW5kID0gdHJlbmQsCiAgICAgICAgICAgIHdlZWsgPSAxOk1BWF9EVVJBVElPTiwKICAgICAgICAgICAgbGlzdGVucyA9IGxpc3RlbnMsCiAgICAgICAgICAgIGN1bXVsYXRpdmVfbGlzdGVucyA9IGN1bV9saXN0ZW5zKQp9CgpwbG90X3NvbmdzIDwtIGZ1bmN0aW9uIChzb25nX2RhdGEpIHsKICBnZ3Bsb3QoKSArCiAgICAgICAgZ2VvbV9jb2woZGF0YT1zb25nX2RhdGEsYWVzKHg9d2Vlayx5PWxpc3RlbnMsZmlsbD1zb25nX2dlbnJlKSkgKyAKICAgICAgICBnZW9tX3Ntb290aChkYXRhPXNvbmdfZGF0YSxhZXMoeD13ZWVrLHk9bGlzdGVucyxmaWxsPXNvbmdfbmFtZSksCiAgICAgICAgICAgICAgICAgICAgZmlsbD1OQSxjb2xvcj0iZGltZ3JheSIsbWV0aG9kPSJsb2VzcyIpICsKICAgICAgICBnZW9tX2NvbChkYXRhPXRyZW5kX2RmLGFlcyh4PXdlZWsseT10cmVuZCkpICsKICAgICAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsODApKSArCiAgICAgICAgZmFjZXRfd3JhcCggfiBzb25nX25hbWUpCn0KCiAKcGxvdF9nZW5yZSA8LSBmdW5jdGlvbiAoc29uZ19kYXRhKSB7CiAgCiAgIGdyb3VwZWRfZGF0YSA8LSAgc29uZ19kYXRhICU+JSAKICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoc29uZ19nZW5yZSwgd2VlaykgJT4lCiAgICAgICAgICAgICAgICAgIHN1bW1hcml6ZShtZWFuX2xpc3RlbnMgPSBtZWFuKGxpc3RlbnMpKQoKIGdncGxvdCgpICsKICAgICAgICBnZW9tX2NvbChkYXRhPWdyb3VwZWRfZGF0YSxhZXMoeD13ZWVrLHk9bWVhbl9saXN0ZW5zLGZpbGw9c29uZ19nZW5yZSkpICsgCiAgICAgICAgZ2VvbV9zbW9vdGgoZGF0YT1ncm91cGVkX2RhdGEsYWVzKHg9d2Vlayx5PW1lYW5fbGlzdGVucyksCiAgICAgICAgICAgICAgICAgICAgZmlsbD1OQSxjb2xvcj0iZGltZ3JheSIsbWV0aG9kPSJsb2VzcyIpICsKICAgICAgICBnZW9tX2NvbChkYXRhPXRyZW5kX2RmLGFlcyh4PXdlZWsseT10cmVuZCkpICsKICAgICAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsODApKSArCiAgICAgICAgZmFjZXRfd3JhcCggfiBzb25nX2dlbnJlKQogCn0KCmBgYAoKIyBsZXQncyBzdGFydCBleHBsb3JpbmcKCkZpcnN0LCBJJ2xsIG1ha2Ugb25lIHBvcCBzb25nLCBjYWxsZWQgInBvcCB5ZXIiLCB3aXRoIGdlbnJlICJwb3AiIGFuZCBubyByZXNwb25zZSB0byB0cmVuZApBbmQgYWxzbyBvbmUgcm9jayBzb25nLiBBbmQgb25lIGphenogc29uZy4KCkNhbiB5b3Ugc2VlIHdoaWNoIGdlbnJlIG9mIHNvbmcgdGVuZHMgdG8gaGF2ZSBtb3JlIGluaXRpYWwgbGlzdGVucz8gV2hpY2ggbGFzdHMgbG9uZ2VyIG9uIHRoZSBjaGFydHM/CgpgYGB7cn0Kc29uZ19saXN0ZW5zX2RmPSBzdXBwcmVzc1dhcm5pbmdzKAogIGJpbmRfcm93cygKICAgICAgbWFrZV9zb25nX2RhdGEoInBvcCB5ZXIiLFBPUCxGQUxTRSksCiAgICAgIG1ha2Vfc29uZ19kYXRhKCJyb2NrIG9uIixST0NLLEZBTFNFKSwKICAgICAgbWFrZV9zb25nX2RhdGEoImphenp5IGpvbmVzIixKQVpaLEZBTFNFKQogICkpCgoKcGxvdF9zb25ncyhzb25nX2xpc3RlbnNfZGYpCgpgYGAKCiMgQW4gSWRlYTogcG9wIHNvbmdzIGFyZSBiZXR0ZXIuCgpTaW5jZSBJJ20gZ29pbmcgdG8gYWRkIHJlbGVhc2UgbW9yZSBwb3Agc29uZ3MgdG8gc2VlIGlmIHRoZXkgc2VlbSBhbGwgdG8gYmUgdGFsbGVyLi4uCgpgYGB7cn0Kc29uZ19saXN0ZW5zX2RmPSBzdXBwcmVzc1dhcm5pbmdzKAogIGJpbmRfcm93cygKICAgICAgc29uZ19saXN0ZW5zX2RmLAogICAgICBtYWtlX3NvbmdfZGF0YSgicG9wIHdvcCIsUE9QLEZBTFNFKSwKICAgICAgbWFrZV9zb25nX2RhdGEoInBvcCBhIGxvdCIsUE9QLEZBTFNFKSwKICAgICAgbWFrZV9zb25nX2RhdGEoInBvcCBiZSBnb25lICIsUE9QLEZBTFNFKSwKICApKQoKYGBgCgpgYGB7cn0KcGxvdF9zb25ncyhzb25nX2xpc3RlbnNfZGYpCmBgYAoKeWVzLCBpdCBzZWVtcyB0byBtZSB0aGF0IHBvcCBzb25ncyBhbGwgZm9sbG93IGEgc2ltaWxhciBwYXR0ZXJuLiBhbmQgaXQgbG9va3MgZGlmZmVyZW50IGZyb20gcm9jayBzb25ncy4KCkJ1dCBqdXN0IHRvIGJlIHN1cmUsIGxldCdzIHBsb3QgQUxMIHRoZSBwb3Agc29uZ3MgKG9uIGF2ZXJhZ2UgdnMuIG91ciByb2NrIHNvbmcpLiBQbGVhc2Ugbm90ZSB0aGF0IHRoaXMgZGlkIG5vdCBzZWVtIHRvIHdvcmsgcXVpdGUgcmlnaHQuIEknbSBub3Qgc3VyZSB3aHksIGJ1dCB0aGUgYXZlcmFnZXMgZm9yIHBvcCBzaG91bGQgYmUgaGlnaGVyLiBBbnl3YXksIHRoZSBwb2ludCBpcyBhIHBsb3QgYnkgZ2VucmUgdHlwZS4KCmBgYHtyfQpwbG90X2dlbnJlKHNvbmdfbGlzdGVuc19kZikKCmBgYAoKU28gdGhhdCBsYXN0IHBsb3QgYWJvdmUgaXMgdGhlIEFWRVJBR0Ugb2YgYWxsIHRoZSBQT1Agc29uZyBsaXN0ZW5zIGFnYWluc3QgdGhlIGF2ZXJhZ2Ugb2YgYWxsIHRoZSByb2NrIGFuZCBqYXp6IHNvbmcgbGlzdGVucyAtLSBidXQgdGhlcmUncyBvbmx5IG9uZSByb2NrIGFuZCBvbmUgamF6eiBzb25nLgoKIyBuZXh0IHJvdW5kIC0tIHRyZW5kcwoKTm93LCBsZXQncyBpbWFnaW5lIHRoYXQgYXQgd2VlayA2IC0tIHNvbmdzIGdldCBhIGJvb3N0IGlmIHRoZXkgbWF0Y2ggdGhlIHRyZW5kLCB3aGljaCBpcyBmb3Igc2FkIHNvbmdzLiBMb29rIGJlbG93IGFuZCBzZWUgaWYgeW91IGNhbmZpZ3VyZSBvdXQgd2hpY2ggMyBvZiB0aGUgNiBzb25ncyBnb3QgYSBib29zdCBmb3IgYmVpbmcgc2FkLiAKCmBgYHtyfQpzb25nX2xpc3RlbnNfZGY9IHN1cHByZXNzV2FybmluZ3MoCiAgYmluZF9yb3dzKAogICAgICBtYWtlX3NvbmdfZGF0YSgiUm9jayBqb3kiLFJPQ0ssRkFMU0UpLAogICAgICBtYWtlX3NvbmdfZGF0YSgiUm9jayBibHVlcyIsUk9DSyxUUlVFKSwKICAgICAgbWFrZV9zb25nX2RhdGEoIlJvY2sgdGhlIHRlYXJzIGF3YXkgIixST0NLLFRSVUUpLAogICAgICBtYWtlX3NvbmdfZGF0YSgicG9wIHdvcCIsUE9QLEZBTFNFKSwKICAgICAgbWFrZV9zb25nX2RhdGEoInBvcCBjcnkiLFBPUCxUUlVFKSwKICAgICAgbWFrZV9zb25nX2RhdGEoInBvcCBiZSBnb25lICIsUE9QLEZBTFNFKSwKICApKQoKcGxvdF9zb25ncyhzb25nX2xpc3RlbnNfZGYpCgpgYGAKCkFub3RoZXIgZXhwZXJpbWVudCB3aXRoIHBsb3R0aW5nIHRoZSBhdmVyYWdlcyBhY3Jvc3MgYWxsIHNvbmdzIG9mIHRoZSBnZW5yZS4gCgpgYGB7cn0KcGxvdF9nZW5yZShzb25nX2xpc3RlbnNfZGYpCgpgYGAKCiMgUmVmbGVjdGlvbnMKCkJhc2VkIG9uIHRoaXMgZXhwZXJpbWVudCwgSSBhbSB0aGlua2luZyB3ZSBuZWVkIHRvIGJlIGNhcmVmdWwgYWJvdXQgdGhlIGxldmVsIG9mIHBhdHRlcm4gZmluZGluZyB3ZSBhcmUgZXhwZWN0aW5nIG9mIHN0dWRlbnRzLiBUaGVyZSdzIGEgbG90IGdvaW5nIG9uIGluIHRoZXNlIGdyYXBocywgYW5kIHRoZXkgYXJlbid0IG5lY2Vzc2FyaWx5IGFsbCB0aGF0IGVhc3kgdG8gcmVhZC4gSnVzdCByZWFkaW5nIG9uZSBmZWF0dXJlcyBvZmYgdGhlIGdyYXBocyBtaWdodCBiZSBhbiBhY2NvbXBsaXNobWVudC4KCkkgZG8gc29tZXdoYXQgZmF2b3IgdXNpbmcgYmFycyBmb3IgdGhlIG51bWJlciBvZiBzb25nIGxpc3RlbnMgaW4gYSB3ZWVrLCByYXRoZXIgdGhhbiBnb2luZyBpbW1lZGlhdGVseSB0byBsaW5lcy4gSSB0aGluayBhIHRhbGwgYmFyIGZvciBhIGxvdCBvZiBsaXN0ZW5zIG1heSBiZSBlYXNpZXIgZm9yIGEga2lkIHRvIG1ha2Ugc2Vuc2Ugb2YuIEkgZmluZCB0aGUgc21vb3RoZWQgbGluZXMgc3VtbWFyaXppbmcgZWFjaCBiYXIgdmVyeSBoZWxwZnVsIHRvIG15IGludGVycHJldGF0aW9uIC0tIG11Y2ggYmV0dGVyIHRoYW4gbGluZXMgY29ubmVjdGluZyB0aGUgdG9wcy4KCkkgZGlkbid0IHlldCBtYWtlIGEgc2ltdWxhdGlvbiB0aGF0IHNob3dzIHNvbmdzIGJlaW5nIHJlbGVhc2VkIGF0IGRpZmZlcmVudCB0aW1lcywgYnV0IHlvdSBjYW4gaW1hZ2luZSBpdCBteSBtZW50YWxseSBzaGlmdGluZyBzb21lIG9mIHRoZSBwbG90cyB0byB0aGUgcmlnaHQuIFRoYXQgYmVpbmcgc2FpZCwgaXQgbWF5IGJlIGFza2luZyBxdWl0ZSBhIGxvdCBvZiBzdHVkZW50cyBmb3IgdGhlbSB0byBtYWtlIHNlbnNlIG9mIGRhdGEgYmFzZWQgb24gcGhlbm9tZW5hIHRoYXQgc3RhcnQgYXQgZGlmZmVyZW50IHBvaW50cyBpbiB0aW1lLiBJIGFtIHdvbmRlcmluZyB3aGV0aGVyIHRoZXJlIHNob3VsZCBiZToKCmEpIGEgZ2FtZSBjb250ZXh0IHdoaWNoIGhhcyBhIHR1cm4tYnktdHVybiBmbG93IG9mIHRpbWUsIGFuZCB0aGlzIGlzIHdoZXJlIHlvdSBlYXJuIGRvbGxhcnMvZm9sbG93ZXJzL3Njb3JlcwoKYikgYnV0IGEgc2ltcGxlciBjb250ZXh0IHd0aWggYSBzaW1wbGVyIGZsb3cgb2YgdGltZSB3aGVyZSB5b3UgY2FuIGNvbmR1Y3QgZXhwZXJpbWVudHMgd2l0aCBsZXNzIGdvaW5nIG9uLiBUaGUgaWRlYSB3b3VsZCBiZSB0aGF0IHdoYXQgeW91IGxlYXJuIGZyb20gYiBtaWdodCBpbmZvcm0gYS4KCkkgYWxzbyB3b25kZXJlZCBhYm91dCB0aGUgY29tcGxleGl0eSBvZiBvdXIgdGhvdWdodHMgYWJvdXQgdHJlbmRzLiBXZSBtYXkgbmVlZCB0byBzaW1wbHkgdGhpcyBzbyB0aGF0IG9ubHkgY2VydGFpbiB0cmVuZHMgKGNoYW5naW5nIGluIHRpbWUgZHVyaW5nIHRoZSBnYW1lKSBtYXR0ZXIgYW5kIHRoZXJlIGFyZSBqdXN0IGEgZmV3LiBJIHdhcyB0aGlua2luZyB0aGF0IHRoZSBwcm9wZXJ0aWVzIG9mIGdlbnJlcyBzdGF5IHByZXR0eSBmaXhlZC4gQWxsIHRoZSB2YXJpYWJpbGl0eSB3b3VsZCBiZSBpbiByZXNwb25zZSB0byBtb29kIG9yIHRvcGljLiBBbmQgSSB3YXMgdGhpbmtpbmcgdGhhdCB3ZSBtaWdodCB3YW50IHRvIHNpbXBsaWZ5IHRoZXNlIHNvIHRoYXQgdGhlcmUgaXMgb25lIHRvcGljIGFuZCBvbmUgbW9vZCB3aGljaCBvY2Nhc3Npb25hbGx5IGlzICJvbiB0cmVuZCIgYnV0IHRoZSBvdGhlciBvbmVzIGFyZSBqdXN0IG5ldXRyYWwuIEhlbmNlLCBwZXJoYXBzIGhhcHB5IHNvbmdzIGFsbW9zdCBwZXJmb3JtIGFib3V0IHRoZSBzYW1lLCBidXQgc2FkIHNvbmdzIHBlcmlvZGljYWxseSBnZXQgYSBiaWcgYm9vc3QuIEkgd2FzIGp1c3QgZ2V0dGluZyB3b3JyaWVkIHRoYXQgaWYgZXZlcnl0aGluZyBpcyBwb3RlbnRpYWxseSBjaGFuZ2luZywgaXQgY291bGQgdGFrZSBhIGxvbmcgdGltZSB0byBmaWd1cmUgaXQgYWxsIG91dC4KCgo=