assert len(song_list.songs) > 0 # assuming CSV file is not empty # TODO: add tests below to show the various required methods work as expected # test sorting songs song_list.sort_songs() print(song_list.songs) for i in range(len(song_list.songs)): print(song_list.songs[i]) # check manually if the list is ordered by artist or not (default) # test adding a new Song song_list.add_songs("Sugar", "Maroon 5", 2017) song_list.sort_songs() print(song_list.songs[0]) # The new song should be on top of the list (A, A, 1, True) # As it has been added and sort by artist (default) # test get_song() print(song_list.get_songs("Heartbreak Hotel")) # The result should be a whole song when it get called by its title print(song_list.songs) song_list.remove_songs(song_list.get_songs("Sugar")) print(song_list.songs) # Tesing remove_song func with get_song item # test getting the number of required and learned songs (separately) song_list.get_status_songs() # Manually check, the result should be 2 learned and 4 required to learn (default) # test saving songs (check CSV file manually to see results)
class Song_To_LearnApp(App): # The string for main status will be change # depend on the function runs main_status = StringProperty() # The string the update when new song added or new song learnt learn_status = StringProperty() # Initializer and start to load songs from the file def __init__(self, **kwargs): super(Song_To_LearnApp, self).__init__(**kwargs) self.album = SongList() self.album.load_songs("songs.csv") self.album.kivy_load_songs() def count_status(self): self.learn_status = self.album.get_status_songs() # GUI BUILDER def build(self): Window.clearcolor = (1, 1, 1, 1) self.title = "Song to learn v2.0 by Nhan Gia Huy" self.root = Builder.load_file("app.kv") # Create the album self.create_album() # Trigger learn status self.count_status() # Welcome user self.main_status = "Welcome to Song To Learn App" return self.root def on_stop(self): self.album.save_songs() # Generating an album based on the song list def create_album(self): # For every song in the list for song in self.album.review_list: # If it is learned, make the button background black if song.split(",")[1] == "learned": temp_text = "{} ({})".format( song.split(",")[0], song.split(",")[1]) temp_button = Button(text=temp_text, background_color=(0, 0, 0, 1)) # Else, make a button with a background of grey else: # Create a text for the button to help the user know the song temp_text = "{}".format(song.split(",")[0]) # give the song title as an ID of the button temp_id = song.split(",")[-1] # Create a button temp_button = Button(id=temp_id, text=temp_text) # bind the function to the button # when pressed, this will marked the song as learnt temp_button.bind(on_release=self.press_learnt) # Add the button the the box self.root.ids.list_of_songs.add_widget(temp_button) # Function when the button pressed, unlearn song return as learnt def press_learnt(self, instance): # When pressed, the selected button will throw its ID to the get song self.album.get_songs(instance.id).mark_learned() # recreate the list self.root.ids.list_of_songs.clear_widgets() self.album.kivy_load_songs() self.create_album() # Update status bar self.main_status = "{} has been marked as learnt".format(instance.text) # update learn status self.count_status() # Create a attribute for sorting radio button # default setup for the radio button (default will be sort by artist) Artist = ObjectProperty(True) Title = ObjectProperty(False) Year = ObjectProperty(False) # sorting songs based on radio buttons def radio_button_sort(self, option): # Sort the song based on the option self.album.sort_songs(option=option) # Recreate list for GUI self.album.kivy_load_songs() # Destroy the whole list and recreate it with new order (sorted) self.root.ids.list_of_songs.clear_widgets() self.create_album() # Update status bar self.main_status = "Sorting by {}".format(option) # function to open the popup for adding purpose def open_adding_pop_up(self): self.root.ids.Adding_Popup.open() # Update status bar self.main_status = "Adding new song" # Function to dismiss the popup def press_cancel_pop_up(self): # Dismiss the pop up self.root.ids.Adding_Popup.dismiss() # Update count learn song self.count_status() # Handle add function def press_add(self): # gather information for new song title = self.get_title() year = self.get_year() artist = self.get_artist() # check the information # Title is blank => Prompt title shouldnt be blank if title == "" or title == " ": self.root.ids.add_prompt_3.text = "Title cannot be blank" # artist is blank => Prompt artist shouldnt be blank elif artist == "" or artist == " ": self.root.ids.add_prompt_3.text = "Artist cannot be blank" # Year is blank => Prompt artist shouldnt be blank elif year == "" or year == " ": self.root.ids.add_prompt_3.text = "Year cannot be blank" # If year get return as -1, There is a Value Error, Prompt the Error elif year == "Case value": self.root.ids.add_prompt_3.text = "Invalid input for year. Try again" # If the year is unreal, prompt the user to input again elif year == "Case 2019": self.root.ids.add_prompt_3.text = "The year is unreal, must be =< 2019" # If year is negative, Prompt year must be > 0 elif year < 0: self.root.ids.add_prompt_3.text = "The year must be > 0" else: # add new song to the list self.album.add_songs(title, artist, year) # clear and recreate the list self.root.ids.list_of_songs.clear_widgets() self.album.kivy_load_songs() self.create_album() # close popup self.root.ids.Adding_Popup.dismiss() # Update status bar self.main_status = "{} by {} ({}) has been added".format( title, artist, year) # update learn status self.count_status() # Method to gather the information in the text input box def get_title(self): # retrieve value and return value value = str(self.root.ids.add_detail_title.text).title() return value def get_artist(self): # retrieve value and return value value = str(self.root.ids.add_detail_artist.text).title() return value def get_year(self): # retrieve value and return value try: value = int(self.root.ids.add_detail_year.text) if value > 2019: return "Case 2019" else: return value # return Case value for case where input is a Value Error except ValueError: return "Case value"