Due Monday, November 27 @ 8:00pm on Gradescope
In this assignment, you will be extending your music manager from the previous to include playlists, song sorting, and song export.
You will be modifying the code you wrote for HW5. The autograder for this assignment is still testing the functionality and efficiency from HW5, in addition to new testcases for this homework.
For this assignment you have 5 submissions. You should write your own testcases while you work so that you don’t waste submissions. After you have used your submissions, you may continue to submit, but your submission will be penalized 4 points for every extra submission. (So, your 6th submission receives a -4, your 7th submission a -8, etc.)
The file format for importing songs has changed slightly. You are given a plain text file of songs (there are multiple examples in the pre-prepared Eclipse project, such as tunes.txt
). Each song entry in the file is formatted in the following manner:
artist
title
album
genre, followed by any playlists the song is contained in (could be 0), each separated by a semi-colon (;) (every song belongs to exactly one genre, but can belong to zero, one, or more playlists)
a blank line to separate entries (warning: there is no blank line after the last entry!)
You can find new sample files that use this format by downloading hw6-songs.zip.
You have four main tasks:
Modify the Song
class.
Modify the MusicLibrary
implementation.
Write the Playlist
class.
Write the PlaylistNotFoundException
class.
Song
classYou will need to modify the Song
class to accommodate songs being on playlists. Note, however, that the constructor for a Song
has not changed.
You will need some way to keep track of which playlists a song is on.
The toString()
for Song
should produce results such as…
Song [artist=Johnny Cash, title=If I Told You Who It Was, album=Out Among The Stars, genre=outlaw country, playlists=[]]
Song [artist=Johnny Cash, title=If I Were a Carpenter, album=Hello, I'm Johnny Cash, genre=outlaw country, playlists=[]]
Song [artist=Johnny Cash, title=I Won't Back Down, album=American III: Solitary Man, genre=arkansas country, playlists=[Driving Music]]
Song [artist=Diana Haddad, title=Ela Hona, album=Ela Hona, genre=lebanese pop, playlists=[Arabic Tunes, Driving Music, Khaliji Sad Melodies]]
Note that the playlists are in sorted order. That is intentional and required.
Also note that which playlists a Song
is on does not impact whether or not two songs are the same. For the purposes of object equality, the following two songs are equal:
Song [artist=Johnny Cash, title=If I Told You Who It Was, album=Out Among The Stars, genre=outlaw country, playlists=[My Favorites]]
Song [artist=Johnny Cash, title=If I Told You Who It Was, album=Out Among The Stars, genre=outlaw country, playlists=[Driving Music]]
If you were attempting to add the second song
MusicLibrary
The MusicLibrary
class includes a few minor changes to existing methods and a set of new methods related to playlist management and song sorting.
Pay careful attention to how the efficiency requirements are specified. If, for example, an efficiency requirement says: “This must be O(M), where M is the number of artists,” then your efficiency must depend only on the total number of different artists; it cannot depend on the number of songs.
Here are the new methods that you need to implement in MusicLibrary
:
public void addSong(String artist, String title, String album, String genre, String[] playlists) throws SongAlreadyExistsException
Add a song to the music library. Throws the SongAlreadyExistsException if the song to be added already exists in the library.
This method has no specific efficiency requirements, but you should avoid doing any linear searches through potentially large data structures. If you don’t, your program may be too slow to pass the autograder.
artist
— The artist of the songtitle
— The title of the songalbum
— The album the song is a part ofgenre
— The genre of the songplaylists
— The array of playlists this song is on. null if the song is not on any playlists.SongAlreadyExistsException
— when the song already exists in the library.
public void createPlaylist(String playlistName)
Create a new playlist with the specified name, adding it to the list of playlists. If a playlist with that name already exists, do not create another one.
This method has no specific efficiency requirements, but be reasonable.
playlistName
— The name of the playlist to create
public void addSongToPlaylist(String title, String playlistName) throws PlaylistNotFoundException
Add all songs with the specified title to the specified playlist. If the playlist does not already exist, throw the appropriate exception.
title
— Title of song to add to the playlistplaylistName
— The name of the playlist to add the song toPlaylistNotFoundException
— when the playlist specified does not exist
public String[] getPlaylistNames()
Return the names of all of the playlists in the library without duplicates
This must be O(M), where M is the number of playlists.
public Playlist getPlaylist(String playlistName) throws PlaylistNotFoundException
Return a Playlist object containing all of the songs currently in a playlist.
This must be O(M), where M is the number of songs in the playlist.
playlistName
— The name of the playlistPlaylistNotFoundException
— if the requested playlist doesn’t exist
public Song[] getAllSongsSorted(String howSorted)
Return all songs in the library sorted in a specific way
If howSorted is….
“title”: Sort by title. Break ties using artist, then genre.
“artist”: Sort by artist. Break ties using title, then genre.
“genre”: Sort by genre. Break ties using artist, then title.
anything else: Return an empty array.
This function should be non-destructive.
howSorted
— How to sort the songs
public void writeMusicDb(String filename)
Write the music database to the file specified by filename. The music DB must be output using the same format as the input. (So, you must be able to input a file that you output.)
filename
— The file to write the music to
Playlist
The new and improved music manager now supports playlists. The Playlist
class provides a way to organize all of the songs from a given playlist.
You can decide on your own design for this class, but it must at least have the specified methods and be iterable.
Here are the methods your Playlist
class must implement:
public Song[] getSongs()
Get all of the songs that are on this playlist.
This must be O(1).
public void sortByArtist()
Sort the songs in this playlist by artist. Break ties by song title, then genre.
public void sortByTitle()
Sort the songs in this playlist by title. Break ties by artist, then genre.
Important Clarification on Playlists: Two different Playlist
objects, even for the same playlist, should be independent of each other. That means that re-order one should not impact the other. Consider the following test code:
new MusicLibrary();
MusicLibrary lib =
addSong("Johnny Cash", "I Walk the Line", "The Broadcast Archive (Live)", "Blues", new String[] { "Tunes", "Country Classics" });
lib.addSong("Rick Astley", "Never Gonna Give You Up", "Whenever You Need Somebody", "Pop", new String[] { "Tunes", "For Enemies" });
lib.addSong("U2","I Still Haven't Found What I'm Looking For","The Joshua Tree","Rock",new String[] {"Tunes"});
lib.
getPlaylist("Tunes");
Playlist p1 = lib.getPlaylist("Tunes");
Playlist p2 = lib.sortByArtist();
p1.sortByTitle();
p2.
for(Song s: p1) {
System.out.println(s);
}System.out.println("---");
for(Song s: p2) {
System.out.println(s);
}
The output should be:
Line, album=The Broadcast Archive (Live), genre=Blues, playlists=[Country Classics, Tunes]]
Song [artist=Johnny Cash, title=I Walk the
Song [artist=Rick Astley, title=Never Gonna Give You Up, album=Whenever You Need Somebody, genre=Pop, playlists=[For Enemies, Tunes]]
Song [artist=U2, title=I Still Haven't Found What I'm Looking For, album=The Joshua Tree, genre=Rock, playlists=[Tunes]]
---
Song [artist=U2, title=I Still Haven't Found What I'm Looking For, album=The Joshua Tree, genre=Rock, playlists=[Tunes]]Line, album=The Broadcast Archive (Live), genre=Blues, playlists=[Country Classics, Tunes]]
Song [artist=Johnny Cash, title=I Walk the Song [artist=Rick Astley, title=Never Gonna Give You Up, album=Whenever You Need Somebody, genre=Pop, playlists=[For Enemies, Tunes]]
PlaylistNotFoundException
You should create a PlayListNotFoundException
that contains the following code:
public class PlaylistNotFoundException extends Exception {
public PlaylistNotFoundException() {
super("Playlist not found.");
}
}
Important: Don’t forget that a Playlist
should also be iterable. That means that it can be properly used in a for-each loop to iterate over all of the songs in the playlist, in order.
There are multiple parts of the grading of this assignment:
For the first 90 points, your submission will be auto-graded based on your implementation of the MusicLibrary
For the next 5 points, your submission will be manually graded to check for good implementation methodologies. (Did you use a good approach to solving the problems?)
For the next 5 points, your submission will be manually graded to check for good testcases that you include in the main method. (Do you have 2-3 of your own testcases for each method, and do they all execute automatically?)
Your code will also be checked for style. The parts of style that can be checked automatically (things like spacing, indentation, the use of CamelCase, etc.) are automatically checked by the autograder. Other parts of style, such as choosing good variable names, will be checked manually. Autograded style guide violations can result in, at most, -10 points. Manually checked style guide violations can result in, at most, -5 points.
You will submit your program to Gradescope. Log in to the system and you will see the homework. Once there, you need to submit a zip
file containing your code. Lucky for you, however, Eclipse can create this zip file for you. Check out these instructions for exporting. On Gradescope, you’ll submit that exported zip
file. On the page that follows your submission, you will see your live score. If you receive a lower score than you expect, you should study the autograder output to see which testcases you failed.
In this homework, we are providing only a single, basic testcase.
For MusicLibrary
you need to provide at least three testcases for each of the new methods. At least one of those must be advanced or test error situations. All of your testcases should be in the MusicLibraryTester
class included with the skeleton code. You must follow the model of our testcases from previous assignments (meaning you print when you start, print the results (pass/fail) when you finish, etc.) Additionally, you must comment each testcase with a note describing what it tests.
You will also need to write testcases that ensure your PlayList
class works correctly.
When grading, in addition to counting testcases we will also look at the quality of what you are testing.
Start early. You need to add fair bit of functionality to your HW5 submission.
If you want to convert a Collection
(such as an ArrayList
or HashSet
) to an array, consider the following example:
ArrayList<String> theList = new ArrayList<String>();
theList.add("Bob");
theList.add("Fred");
theList.add("John");
String[] theArray = theList.toArray(new String[0]);
Seriously, plan ahead on how you want to store your data. You will likely be storing multiple copies of some parts of the data in different data structures.
Due to all of the efficiency testing, the autograder for this assignment takes longer than usual: Potentially 5-10 minutes.
Remember that your input file does not have the extra newline at the end. (And your output file shouldn’t have it, either.)
If you have questions, please post to Piazza. The course staff, including the instructor, monitor and answer questions there.
When posting to Piazza, if you include any code make sure your question is posted privately to the course staff, and not to the entire class.
Do not change the names of any of the provided methods or files. You may, however, add additional methods as needed.
After you submit to Gradescope, make sure you check your score. If you aren’t sure how to do this, then ask.
There is no partial credit on Gradescope testcases. Your Gradescope score is your Gradescope score.
Read the last bullet point again. Seriously, we won’t go back later and increase your Gradescope score for any reason. Even if you worked really hard and it was only a minor error…
You can submit to Gradescope multiple times. So, after you submit you should check your score. If it isn’t a 90 you can keep working until it is.
Don’t forget to make sure your code conforms to the style guide. We’ll be taking a look at that!
The style guide has a bunch of small rules with regard to indentation and spacing that are hard to follow perfectly. Luckily, Eclipse can handle it for you! Go to Source -> Format
in Eclipse and watch all of your spacing and indentation problems get fixed automatically. (You should do this before every submission.)