Jump to content

Python DJ Playlist program

Agena_

Figure 4 shows selection of songs paul has store

 

 

rules:

1. duration of playlist is to be generated is entered in minutes

2. 25% of playlist left empty so paul can add songs that customers request

3. a playlist is then generated for the remaining duration using these rules:

            45% must be 5 star

            30% must be 4 star

            25% must be 3 star

4. songs with the greatest 'last selected' value should always be selected first

5. when a song is added to the playlist then the 'last selected' is set to 0

 

NOTE: 1 and 2 stars are not added to playlist. they are stored in case a customer requests during an event

20200927_102829.jpg

Link to comment
Share on other sites

Link to post
Share on other sites

So... You want us to create your homework?

What have you finished about this assignment yet? What issue(s) are you running into?

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, Agena_ said:

Plus im not that fluent so no hard stuff please :D

So you want us to do you homework for you? I am going to do because it looks fun though it'll be tomorrow when I do but you should really try yourself and we can help with any problems you in counter

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to comment
Share on other sites

Link to post
Share on other sites

So thought i would have play with this and this is what i came up with but before you look please please actually have a go your self you will learn nothing if you never try to solve the puzzle after you are done come back here and see how mine differs from yours.

 

output
 

# Data after the list generation to show the last was updated
                   name           artist  duration  rating  last
0       Jagged Boarders        Rob Smith       204       3     0
1           Last Minute         Sharpiee       165       3    19
2   It's gonna be great            Flybe       258       5     5
3                 Chaos  Trouble dodgers       302       5     0
4              Dreamin'        Rob Smith       214       3    16
5             Rock this        Ian Green       232       2    25
6           Let's Party            FlyBy       178       4     0
7           Lovin' life      Andrew ford       257       5     1
8                 Smile            Crazy       249       3    17
9          Keep It Real    Story Tellers       228       4     0
10                 Time          Various       232       5     4
11      Let's selebrate       Harry Bunn       249       5     0

# this is the play list that is also shuffled
              name           artist  duration  rating  last
0     Keep It Real    Story Tellers       228       4    11
1  Let's selebrate       Harry Bunn       249       5     7
2            Chaos  Trouble dodgers       302       5     9
3  Jagged Boarders        Rob Smith       204       3    20
4      Let's Party            FlyBy       178       4    13

# print the duration
Playlist length 19.35 mintues

 

On 9/27/2020 at 10:34 AM, Agena_ said:

Plus im not that fluent so no hard stuff please :D

 

incoming hard stuff :)

Spoiler
 
 
 
Spoiler

import pandas as pd
from math import floor

columns=['name','artist', 'duration', 'rating', 'last']

data = [
  ['Jagged Boarders', 'Rob Smith', 204, 3, 20],
  ['Last Minute', 'Sharpiee', 165, 3, 19],
  ["It's gonna be great", 'Flybe', 258, 5, 5],
  ['Chaos', 'Trouble dodgers', 302, 5, 9],
  ["Dreamin'", 'Rob Smith', 214,3,16],
  ['Rock this', 'Ian Green', 232, 2, 25],
  ["Let's Party", 'FlyBy', 178, 4,13],
  ["Lovin' life", 'Andrew ford', 257, 5,1],
  ['Smile', 'Crazy', 249, 3, 17],
  ['Keep It Real', 'Story Tellers',228,4,11],
  ['Time', 'Various', 232, 5, 4],
  ["Let's selebrate", 'Harry Bunn', 249, 5,7],
  ]

df = pd.DataFrame(data, columns=columns)


def get_songs(rating: int, duration: int) -> list:
  # get the songs
  song_data = df.loc[df['rating'] == rating].sort_values(by='last', ascending=False).values.tolist()
  songs = list()
  # turn mintues into seconds
  max_duration = duration * 60
  length = 0
  for song in song_data:
   name = song[0]
   song_duration = song[2]
   if length + song_duration > max_duration: break;
   index = df.index[df['name'] == name].tolist()[0]
   df.at[index, 'last'] = 0
   songs.append(song)
   length = length + song_duration
  return songs

def append_to_playlist(playlist, songs):
  temp = pd.DataFrame(songs, columns=columns)
  return playlist.append(temp, ignore_index=True)


length = 30 # 30 min playlist

s5Total = floor(length * 0.45)
s4Total = floor(length * 0.3)
s3Total = floor(length * 0.2)

# start the playlist with 5 star songs
playlist = pd.DataFrame(get_songs(5, s5Total), columns=columns)
# # add 4 star songs
playlist = append_to_playlist(playlist, get_songs(4, s4Total))
# # add 3 star songs
playlist = append_to_playlist(playlist, get_songs(3, s3Total))
# # shuffle that list 
playlist = playlist.sample(frac=1).reset_index(drop=True)

print(df) # song database

print(playlist) # our playlist
print(f'Playlist length {playlist["duration"].sum()/60} mintues')

 

 

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to comment
Share on other sites

Link to post
Share on other sites

The problem is quite interesting, because of this:

 

* you have a total playlist time (60 minutes for example) and have to reserve 25% of that, so your actual time is 75% of input number.

* you then have 3 "pools" of audio tracks (45%, 30% , 25%) in which you have random audio tracks.

Then in theory you have to combine the 3 pools and sort by last used

 

Here's my php solution ... it does everything but the final sorting by last used... that's trivial :

 

 

<?php

$duration = isset($_GET['time'])? intval($_GET['time']) * 60 : 0;
$action = isset($_GET['action'])? $_GET['action'] : '';

// reset the database, generate random scores and last used for each track
if ($action=='reset') {

	$entries = [];
	$lines = explode("\r\n",file_get_contents('database.txt'));

	foreach ($lines as $line) {
		$l = explode("\t",$line);
		$t = explode(":",$l[3]);
		$timer = intval($t[0]) * 60 + intval($t[1]);
		$l[0] = mb_convert_encoding($l[0],'UTF-8','ASCII');
		$l[2] = mb_convert_encoding($l[2],'UTF-8','ASCII');
		
		array_push($entries, array('artist'=>$l[0],'track'=>$l[2],'time'=>$timer,'score'=>mt_rand(1,5),'last'=>mt_rand(0,60)));
	}

	$js = json_encode($entries,JSON_PRETTY_PRINT);
	file_put_contents( __DIR__ . '/database.json',$js);
	die('Playlist reset.');
}

// load database

$entries = json_decode(file_get_contents(__DIR__.'/database.json'),TRUE);
if (count($entries)<1) die('Database empty. Maybe reset it?');
foreach ($entries as $idx=>$entry) {
	$entries[$idx]['used'] = false;
}

// pick a track with desired score, suitable length and not selected before 
function find_track($len,$score) {
	global $entries;
	$ids = [];
	foreach ($entries as $i => $e) {
		if (($e['time']<=$len) && ($e['score']==$score) && ($e['used']==FALSE)) {
			array_push($ids,$i);
		}
	}
	if (count($ids)==0) return FALSE;
	$result = mt_rand(0,count($ids)-1);
	return $ids[$result];
}

if ($duration > 0) {
	$time_total = round($duration * 0.75,0);
	$pools = array();
	$pools[0] = array('score'=>5, 'duration'=> intval(0.45 * $time_total) , 'length'=>0, 'tracks'=> []);
	$pools[1] = array('score'=>4, 'duration'=> intval(0.30 * $time_total) , 'length'=>0, 'tracks'=> []);
	$pools[2] = array('score'=>3, 'duration'=> intval(0.25 * $time_total) , 'length'=>0, 'tracks'=> []);
	
	for ($i=0;$i<3;$i++) {
		$seconds = $pools[$i]['duration'];
		$track = TRUE;
		while ($track = find_track($seconds,$pools[$i]['score'])) {
				array_push($pools[$i]['tracks'],$entries[$track]); // copy track to pool track array
				$pools[$i]['length'] += $entries[$track]['time'];  // just for stats
				$seconds = $seconds - $entries[$track]['time'];
				$entries[$track]['used'] = TRUE; // so it won't be picked twice
		}
	}
	// print the tracks
	for ($i=0;$i<3;$i++) {
		echo '<p>Pool '.$i.': max='.$pools[$i]['duration'].', used='.$pools[$i]['length'].', tracks='.count($pools[$i]['tracks']).'</p>';
		echo '<table>';
		echo '<tr><td>Artist</td><td>Track</td><td>Time</td><td>Score</td><td>Used last</td></tr>';
		foreach ($pools[$i]['tracks'] as $track) {
			echo '<tr><td>'.$track['artist'].'</td><td>'.$track['track'].'</td><td>'.
							$track['time'].'</td><td>'.$track['score'].'</td><td>'.$track['last'].'</td></tr>';
		}
		echo '</table>';
		
	}
	
die('Done.');
}


die('Usage:<br/>
?action=reset  - reset database<br/>
?time=[minutes] - make playlist with [minutes] minutes<br/>
');
  	
?>

 

example output:

 

image.png.c6fb9df5ed3009f1db90c1de77650220.png

 

The source code and example database is attached.

 

 

playlist.zip

Link to comment
Share on other sites

Link to post
Share on other sites

12 hours ago, mariushm said:

Then in theory you have to combine the 3 pools and sort by last used

Quote

4. songs with the greatest 'last selected' value should always be selected first

You should be selecting your pools by last selected.

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to comment
Share on other sites

Link to post
Share on other sites

In that case, all that needs to be done is modify the find_track function to sort the suitable tracks by last used, then always return the first track (with most used value) instead of a random one. Probably 2 extra lines, and one line modified... easy.

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, mariushm said:

In that case, all that needs to be done is modify the find_track function to sort the suitable tracks by last used, then always return the first track (with most used value) instead of a random one. Probably 2 extra lines, and one line modified... easy.

yeah its actually a fun little project, which my college classes had problems like this :P

                     ¸„»°'´¸„»°'´ Vorticalbox `'°«„¸`'°«„¸
`'°«„¸¸„»°'´¸„»°'´`'°«„¸Scientia Potentia est  ¸„»°'´`'°«„¸`'°«„¸¸„»°'´

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×