Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 24 additions & 78 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,37 @@
# MP3 Player - Second Weekend Assignment
You are going to implement an MP3 player.
# MP3 Player :
this project suppose to demonstrate simple MP3 Player.

![image](https://user-images.githubusercontent.com/89573774/132813316-8c310d9f-ef3a-4223-bf49-b59422ba651a.png)

## Instructions
1. Fork this repo into your account.
2. Clone the forked repo to your computer.
3. Execute `npm install` in the project folder to install the [tests](#testing).
4. Create a new git branch for your work.
5. Complete the project [requirements](#requirements).
6. Remember to push your commits regularly to GitHub.
7. Submit your work (explanation [below](#submission))
8. Good luck & have fun!
## Basic functions you should know about:

- `playSong` - Gets a song ID and number of song to play automatically(optional), and plays it by printing it's data.
- `removeSong` - Gets a song ID, and removes it from the player (from songs and playlists).
- `addSong` - Gets a title, album, artist, duration(`mm:ss`) & ID(optional).
- `removePlaylist` - Gets a playlist ID. Remove the playlist from the player.
- `createPlaylist` - Gets a name & ID(optional). Creates a new, empty playlist with the given details.
- `playPlaylist` - Gets a playlist ID. Plays all songs in the playlist.
- `editPlaylist` - Gets a playlist ID & a song ID: -If the song ID exists in the playlist, removes it.
-If it was the only song in the playlist, also deletes the playlist.
-If the song ID does not exist in the playlist, adds it to the end of the playlist.
- `playlistDuration` - Gets a playlist ID. Returns the total duration of the entire playlist.
- `searchByQuery` - Gets a query string. search in songs(title,album and artist) and playlists.
- `searchByDuration` - Gets a duration in `mm:ss` format (for example 01:03). Returns the song, or playlist, with the closest duration to what was given.

## Requirements
The player itself is an object that has:
- `songs`: an array of songs
- `playlists`: an array of playlists
- `playSong`: a method that plays a song.
It receives a song object and should print the following format `"Playing {song.title} from {song.album} by {song.artist} | {song.duration}."` (replace the stuff inside the `{}` with the real values).
The song duration should be in `mm:ss` format (for example 02:40).
__Note__: The functions are not yet merge to the main branch.

A song object has:
- `id`: a unique ID (a number)
- `title`: a title
- `album`: album title
- `artist`: artist name
- `duration`: duration (number, in seconds)

A playlist object has:
- `id`: a unique ID (a number)
- `name`: a name
- `songs`: an array of song IDs
## Additions
- `shufflePlaylist` -play any playlist in random order.
- `autoPlay` - automatically play next song.(insted of adding it as new function I updated playSong so you can choose how many song you want it to play automatically(randomly),if you don't choose it plays only the song that match the ID.)

You are asked to implement the following functions:
- `playSong` - Gets a song ID. Uses `player.playSong` to play the song with the given ID.
- `removeSong` - Gets a song ID. Removes the song with the given ID from the player (from songs and playlists).
- `addSong` - Gets a title, album, artist, duration & ID. Adds a new song with given properties to the player. The ID is optional, and if omitted should be automatically generated. The song duration should be in `mm:ss` format (for example 06:27). Returns the ID of the new song.
- `removePlaylist` - Gets a playlist ID. Remove the playlist with the given ID from the player (does not delete the songs inside it).
- `createPlaylist` - Gets a name & ID. Creates a new, empty playlist with the given details. The ID is optional, and if omitted should be automatically generated. Returns the ID of the new playlist.
- `playPlaylist` - Gets a playlist ID. Plays all songs in the specified playlist, in the order the appear in the playlist.
- `editPlaylist` - Gets a playlist ID & a song ID. If the song ID exists in the playlist, removes it. If it was the only song in the playlist, also deletes the playlist. If the song ID does not exist in the playlist, adds it to the end of the playlist.
- `playlistDuration` - Gets a playlist ID. Returns the total duration of the entire playlist with the given ID.
- `searchByQuery` - Gets a query string. Returns a results object, which has:
- `songs`: an array of songs in which either title or album or artist contain the query string. The songs should be sorted by their titles.
- `playlists`: an array of playlists in which the name contains the query string. The playlists should be sorted by their names.

The comparison in both cases should be case-insensitive.
- `searchByDuration` - Gets a duration in `mm:ss` format (for example 11:03). Returns the song, or playlist, with the closest duration to what was given.

__Note__: The functions are not yet merge to the main branch.

## Testing
We have added some automated tests for you to use. They will help you make sure your code covers the requirements.
## bugs /errors
- The autoPlay adittion choose the songs the next song randomly from all the songs in the player…so if you don't have many songs it will probably repeat the same songs all the time! maybe even 2 or 3 times in a row.

To run the tests, execute `npm run test` in the project folder.

__Note__: These tests might not cover everything. Don't just count on them. You should remain responsible and vigilant for other possible edge-cases.

### If you have anything to add or comment I would love it.

## Grading
Your work will be graded based on the following considerations:
- The number of automatic tests you pass
- Readable and ordered code
- Spacing & indentation
- Indicative vairable/function names
- Comments (where necessary)
- Proper use of Git
- Granular commits
- Descriptive commit messages
- Extra features you might have added


## Submission
1. On GitHub, open a pull request from your branch to the main branch.
2. __Do not merge the pull request!__
3. Add the user `Cyber4sPopo` as collaborator to your repo.
4. Submit a link to the pull request in Google Classroom.


## Important Tip
Try to work in small iterations. You've got a big and complex task ahead of you. Break it down into smaller tasks. Concentrate on making small progress every time. Do it step by step.


## Remarks
- The player object must be stored in a global variable called `player`.
- The function, method & property names should be __exactly__ as described above (for the tests to function).
- __Avoid code duplication!__ You are free to add as many extra functions as you like.
- Pay attention to edge-cases! Your code should throw errors when the user tries to do something invalid (delete a song that doesn't exist, etc.).
- You can use all the material you've learned so far, including extras you've learned on your own.
- Write your code in the `index.js` file. It contains a template which you can use as the basis for your code.
170 changes: 154 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict"
const player = {
songs: [
{
Expand Down Expand Up @@ -48,50 +49,186 @@ const player = {
{ id: 5, name: 'Israeli', songs: [4, 5] },
],
playSong(song) {
console.log(/* your code here */)
},
console.log(`Playing ${song.title} from ${song.album} by ${song.artist} | `
+((Math.floor(song.duration/60))<10? "0": "")+`${Math.floor(song.duration/60)}:` +((song.duration%60)<10? "0": "")+`${song.duration%60}.`)
}
}

function findSong(id){
for(let song of player.songs){
if (song.id===id){
return song;
}
}
throw "ID not found";
}

function findPlaylist(id){
for(let Playlist of player.playlists){
if (Playlist.id===id){
return Playlist;
}
}
throw "ID not found";
}

function playSong(id) {
// your code here
player.playSong(findSong(id));
}

function removeSong(id) {
// your code here
player.songs.splice(player.songs.indexOf(findSong(id)),1);
for(let playlist of player.playlists){
playlist.songs.splice(playlist.songs.indexOf(id),1)
}
}

let newSongId=10;
function generateSongId(){
newSongId+=1;
return newSongId;
}

function durationToSeconds(duration){
checkDurationInput(duration)
return((parseInt(duration[0])*10)+parseInt(duration[1]))*60
+parseInt(duration[3]*10)+parseInt(duration[4])
}

function checkDurationInput(duration){ // checks digits(maximum is 59:59/minimum is 00:00),:,length.
if(0<=parseInt(duration[0])&&parseInt(duration[0])<6&&0<=parseInt(duration[1])&&parseInt(duration[1])<=9
&&duration[2]===":"&&0<=parseInt(duration[3])&&parseInt(duration[3])<6&&0<=parseInt(duration[4])
&&parseInt(duration[4])<=9&&duration.length===5){
return true
}else throw 'Duration is not in the correct format...This is the format-"mm:ss" (for example 03:13)'
}

function addSong(title, album, artist, duration, id) {
// your code here
function addSong(title, album, artist, duration, id=generateSongId()) {
try{
findSong(id)
}catch(err) {
player.songs.push({"id":id,
"title": title,
"album": album,
"artist": artist,
"duration": durationToSeconds(duration),
})
return id;
}
throw "ID taken"
}

function removePlaylist(id) {
// your code here
player.playlists.splice(player.playlists.indexOf(findPlaylist(id)),1);
}

function createPlaylist(name, id) {
// your code here
let newPlaylistId=3
function generatePlaylistId(){
newPlaylistId+=1
return newPlaylistId
}

function createPlaylist(name, id=generatePlaylistId()) {
try{
findPlaylist(id)
}catch(err) {
player.playlists.push({ "id":id , "name": name, "songs": [] })
return id;
}
throw "ID taken"
}

function playPlaylist(id) {
// your code here
for(let songId of findPlaylist(id).songs){
playSong(songId)
}
}

function editPlaylist(playlistId, songId) {
// your code here
function editPlaylist(PlaylistId, songId) { // to check readability!!
let playlistIndex=player.playlists.indexOf(findPlaylist(PlaylistId));
findSong(songId);
if(player.playlists[playlistIndex].songs.indexOf(songId)===(-1)){
player.playlists[playlistIndex].songs.push(songId);
}else{
player.playlists[playlistIndex].songs.splice(player.playlists[playlistIndex].songs.indexOf(songId),1);
}
if(player.playlists[playlistIndex].songs.length===0){
removePlaylist(PlaylistId);
}
}

function playlistDuration(id) {
// your code here
let plDuration=0;
for(let songID of findPlaylist(id).songs){
plDuration+=(findSong(songID).duration);
}
return (plDuration);
}

function searchByQuery(query) {
// your code here
const QUERY=query.toUpperCase();
const queryObj={"songs":[],"playlists":[]}
for(let song of player.songs) {
if(song.title.toUpperCase().includes(QUERY)
||song.artist.toUpperCase().includes(QUERY)
||song.album.toUpperCase().includes(QUERY))
{
queryObj.songs.push(song);
}
}
for(let playlist of player.playlists){
if(playlist.name.toUpperCase().includes(QUERY)){
queryObj.playlists.push(playlist);
}
}
queryObj.songs.sort(sortByTitle);
queryObj.playlists.sort(sortByName);
return queryObj;
}

function searchByDuration(duration) {
// your code here
function sortByTitle(a, b) {
let titleA = a.title.toUpperCase();
let titleB = b.title.toUpperCase();
if (titleA < titleB) {
return -1;
}
if (titleA > titleB) {
return 1;
}
}

function sortByName(a, b) {
let nameA = a.name.toUpperCase();
let nameB = b.name.toUpperCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
}

function searchByDuration(duration) {
checkDurationInput(duration);
let sec=durationToSeconds(duration);
let allDurationArr=[];
let matchingArr=[]; //matching array that saves the song and playlist parallel(they will have the same index) to the duration array(allDurationArr)
let closestDuration=player.songs[0].duration;
for(let song of player.songs){
allDurationArr.push(song.duration);
matchingArr.push(song);
}
for(let playlist of player.playlists){
allDurationArr.push(playlistDuration(playlist.id));
matchingArr.push(playlist);
}
for(let dur of allDurationArr){
if(Math.abs(dur-sec)<Math.abs(closestDuration-sec)){
closestDuration=dur;
}
}
return matchingArr[allDurationArr.indexOf(closestDuration)];
}
module.exports = {
player,
playSong,
Expand All @@ -105,3 +242,4 @@ module.exports = {
searchByQuery,
searchByDuration,
}