alaingilbert / Turntable-API

Allows you to create bots for turntable.fm
http://alaingilbert.github.com/Turntable-API/
MIT License
317 stars 97 forks source link

shuffle playlist? #104

Closed samuri51 closed 12 years ago

samuri51 commented 12 years ago

how would i go about getting my bot to shuffle its playlist and play a random song?

MikeWills commented 12 years ago

You would probably have to loop through your playlist and assign a new random position in your playlist.

samuri51 commented 12 years ago

is there a way to get all my song ids at once or do i have to go through every single one of them?

MikeWills commented 12 years ago

My best guess would be something like:

playlistAll(function(playlist){
    for (var i = 0; i <= playlist.length; i++){
        var nextId = Math.ceil(Math.random() * playlist.length);
        playlistReorder(i,nextId);
    }
});

DISCLAIMER: This is completely untested and may fail.

samuri51 commented 12 years ago

i found a randomize algorithm how would i actually go about using this in my code? in non prototype form

Array.prototype.shuffle = function (){
    var i = this.length, j, temp;
    if ( i == 0 ) return;
    while ( --i ) {
        j = Math.floor( Math.random() * ( i + 1 ) );
        temp = this[i];
        this[i] = this[j];
        this[j] = temp;
    }
};

http://sroucheray.org/blog/2009/11/array-sort-should-not-be-used-to-shuffle-an-array/

alaingilbert commented 12 years ago

You shouldn't mess with the "Array" (or "Object", "String"...) prototypes.

var a = [9, 3, 6, 0, 6];
console.log(a.sort(function() { return Math.random() > 0.5; }));

Will do the job.

samuri51 commented 12 years ago

playlistALL() gets all the information from queue? or from some playlist that i have to manually create? i was using that command earlier and couldnt get it to work... need a method of finding all the song id's in my queue(the native turntable one)

samuri51 commented 12 years ago

without actually playing through the list....

MikeWills commented 12 years ago

playlistAll(function(playlist){}); will return everything in the bot's playlist.

samuri51 commented 12 years ago

i did the commands and it returned undefined? does that mean i have to manually add songs to the some playlist variable? or is the "playlist" my queue in turntable? and yeah i have songs on the bot


var hello = bot.playlistAll(function(playlist){});
console.log('DEBUGGING: ',hello);
samuri51 commented 12 years ago

if i dont use the bot. part of the command it straight up crashed :/ what am i doin wrong

MikeWills commented 12 years ago

Your test should be

playlistAll(function(playlist){
    console.log("Playlist", JSON.stringify(playlist)); // Sometimes stringify works better than what .log() uses
});
samuri51 commented 12 years ago

thanks that deffinitely returns some songs but two questions,

  1. why does it only show like 30 songs rather than all my songs?
  2. whats the path to the ids in there? like for(i = 0; i<playlist.length; i++) { playList = data.song.id } or something like that?
MikeWills commented 12 years ago
  1. I am not sure why only 30. I haven't used it enough to know about it. My guess is that is what TT is returning to make the browser interface faster.
  2. To access the id, use playlist.list[0]._id. I don't remember off the top of my head.
samuri51 commented 12 years ago

alright thanks ill give it a go

samuri51 commented 12 years ago

is this what that command is accessing?

https://github.com/alaingilbert/Turntable-API/blob/master/turntable_data/search_complete.js

i notice theres also a searchSong command? does that give more songs

samuri51 commented 12 years ago

cant figure out what im doing wrong here... it gives me playlist is undefined every time

what i'm trying to do: get the song ids of all the songs in my bots queue then put them on an array.


bot.playlistAll(function(playlist){
   console.log("Playlist", JSON.stringify(playlist));
   return ("Playlist", JSON.stringify(playlist));
   });

   var playlist10 = playlist();   
   console.log('DEBUGGING: ',playlist10);

   for (var p=0; p<playlist10.length; p++) {
    var user10 = playlist10[p];
    playListIds.push(user10._id);   
  }   
MikeWills commented 12 years ago

Try this:

bot.playlistAll(function(playlist){
   console.log("Playlist", JSON.stringify(playlist));

   for (var p=0; p<playlist.list.length; p++) {
    var song = playlist.list[p];
    playListIds.push(song._id);   
  } 
});
samuri51 commented 12 years ago

it correctly assigns the information to playListIds but doesnt give me just the id's

samuri51 commented 12 years ago

looks like its giving me all the songs on my list now though which is sweet

samuri51 commented 12 years ago

and question how do i get my bot to actually use my playlist?

samuri51 commented 12 years ago

and do i even need just the id's or can it be left in that format?

MikeWills commented 12 years ago

I am confused as to what you are doing now? Are your trying to randomize your bot's playlist? You don't need any IDs to do do that. playlistReorder(previous_index, new_index) is all that you would need.

samuri51 commented 12 years ago

yeah im trying to reorder my playlist : p

MikeWills commented 12 years ago

So the first comment I left should get you close. https://github.com/alaingilbert/Turntable-API/issues/104#issuecomment-9319932

Maybe not the best solution, but it should work.

samuri51 commented 12 years ago

i'm trying to do something like this

playListIds = [];
   bot.playlistAll(function(playlist){
   console.log("Playlist", JSON.stringify(playlist));

   for (var p=0; p<playlist.list.length; p++) {
    var song = playlist.list[p];
    playListIds.push(song._id);   
    } 
   });
   console.log('DEBUGGING: ', playListIds);

   for(var count = 0; count < 200; count++){
   var i = playListIds.length, j, temp;
   if (i == 0) return;
   while ( --i) {
    j = Math.floor(Math.random() * (i + 1));
    temp = playListIds[i];
    bot.playlistReorder(playListIds[i], playListIds[j]);
    bot.playlistReorder(playListIds[j], temp);  
    }}
   console.log('DEBUGGING: ',playListIds);
  }
samuri51 commented 12 years ago

seems not to reorder anything though

MikeWills commented 12 years ago

You need the index number, not the song id. I'll write it up as usable code tonight and post the code. I think you are making it harder than it should be.

samuri51 commented 12 years ago

thank you man :)

samuri51 commented 12 years ago

maybe so... but an algorithm like this will gaurntee randomness, i've heard a lot of users of other bots complaining about using the "random" song feature and end up hearing the same song over and over.

alaingilbert commented 12 years ago

@MikeWills, I know that turntable.fm limit the number of requests that a single user can make per minute. (I don't know what is the limit though)

So if you reorder like 40 songs in a too short lapse of time, it may work for the first 5-10 songs, and all the rest could be rejected.

Like I said, my numbers are fictives ! I don't know the real limit.

MikeWills commented 12 years ago

I guess I'll find out in a few minutes :-)

MikeWills commented 12 years ago

This code works.

            bot.playlistAll(function(playlist) {
                Log("Old Playlist: " + JSON.stringify(playlist));
                Log("Playlist length: " + playlist.list.length);
                for(var i = 0; i <= playlist.list.length; i++) {
                    var nextId = Math.ceil(Math.random() * playlist.list.length);
                    bot.playlistReorder(i, nextId);
                    Log("Song " + i + " changed.");
                }
                Log("Reorder complete!");
            });

However like @alaingilbert said, I must be hitting a query limit. I am going to try to slow this down and see if that helps.

MikeWills commented 12 years ago

Okay... I'll leave the other example, but this one allows me to query TT immediately after running, the previous one I had to wait a minute or so.

            bot.playlistAll(function(playlist) {
                var i = 0
                var reorder = setInterval(function() {
                    if(i <= playlist.list.length) {
                        var nextId = Math.ceil(Math.random() * playlist.list.length);
                        bot.playlistReorder(i, nextId);
                        console.log("Song " + i + " changed.");
                        i++;
                    } else {
                        clearInterval(reorder);
                        console.log("Reorder Ended");
                        bot.speak("Reorder completed.");
                    }
                }, 1000);
            });

The more songs you have the longer it will take. This will run one a second.

samuri51 commented 12 years ago

looks good im gonna try it :) ill be sure to credit you in my script

samuri51 commented 12 years ago

really like the logic behind this one :p tells me exactly how many songs are changed and when its done. i'm makin it a admin only command so it only runs when you call it

MikeWills commented 12 years ago

That was debugging code... but still glad it works.

MikeWills commented 12 years ago

@alaingilbert I added this to the wiki

samuri51 commented 12 years ago

hm.... seems to get stuck in an infinite loop cause i know i dont have 700 songs on my playlist

MikeWills commented 12 years ago

Are you sure? I added how to get the playlist length to the wiki entry

samuri51 commented 12 years ago

nevermind??? it went to 737 then reorder ended lol

samuri51 commented 12 years ago

guess it reordered me several times eh. anyway looks like it works good job.

samuri51 commented 12 years ago

idk man maybe i do have that many lol

samuri51 commented 12 years ago

i logged into my bot and their all different so yes its confirmed working

alaingilbert commented 12 years ago

Nice ! Thanks @MikeWills.

Hint: If you want your code to be highlighted:

// Your code here.