From c5988c70a2d2f9f28fd9cfbf2db06164ebc33740 Mon Sep 17 00:00:00 2001 From: ziyic Date: Wed, 30 Jun 2021 18:34:04 +0100 Subject: [PATCH 1/2] test(video.py;video_player.py;video_playlist.py): Part1&Part2 Passed the test Part1&Part2 Passed the test --- python/src/video.py | 3 + python/src/video_player.py | 164 +++++++++++++++++++++++++++++++---- python/src/video_playlist.py | 37 ++++++++ 3 files changed, 185 insertions(+), 19 deletions(-) diff --git a/python/src/video.py b/python/src/video.py index 52da908..b1b983d 100644 --- a/python/src/video.py +++ b/python/src/video.py @@ -29,3 +29,6 @@ def video_id(self) -> str: def tags(self) -> Sequence[str]: """Returns the list of tags of a video.""" return self._tags + + def __str__(self): + return f"{self.title} ({self.video_id}) [{' '.join(list(self.tags))}]" diff --git a/python/src/video_player.py b/python/src/video_player.py index bb79af8..bea469d 100644 --- a/python/src/video_player.py +++ b/python/src/video_player.py @@ -1,6 +1,20 @@ """A video player class.""" +from enum import Enum +from .video_playlist import Playlist from .video_library import VideoLibrary +import random + + +class PlayingStatus(Enum): + PLAYING = 1 + PAUSED = 2 + STOPPED = 3 + + +class PlayStatusException(Exception): + """A class used to represent a wrong play status exception.""" + pass class VideoPlayer: @@ -8,6 +22,9 @@ class VideoPlayer: def __init__(self): self._video_library = VideoLibrary() + self._playing_status = False + self._playing_video = '' + self._list_playlist = [] def number_of_videos(self): num_videos = len(self._video_library.get_all_videos()) @@ -15,8 +32,12 @@ def number_of_videos(self): def show_all_videos(self): """Returns all videos.""" + videos = self._video_library.get_all_videos() + videos = sorted(videos, key=lambda x: x.title) - print("show_all_videos needs implementation") + print("Here's a list of all available videos:") + for video in videos: + print(str(video)) def play_video(self, video_id): """Plays the respective video. @@ -24,32 +45,72 @@ def play_video(self, video_id): Args: video_id: The video_id to be played. """ - print("play_video needs implementation") + videos = self._video_library.get_all_videos() + for video in videos: + if video.video_id == video_id: + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print(f"Playing video: {video.title}") + self._playing_video = video + self._playing_status = PlayingStatus.PLAYING + elif self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: + print(f"Stopping video: {self._playing_video.title}") + self._playing_video = video + print(f"Playing video: {self._playing_video.title}") + self._playing_status = PlayingStatus.PLAYING + break + else: + print("Cannot play video: Video does not exist") def stop_video(self): """Stops the current video.""" - - print("stop_video needs implementation") + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print("Cannot stop video: No video is currently playing") + elif self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: + print(f"Stopping video: {self._playing_video.title}") + self._playing_status = PlayingStatus.STOPPED def play_random_video(self): """Plays a random video from the video library.""" - - print("play_random_video needs implementation") + videos = self._video_library.get_all_videos() + rand = random.randint(0, len(videos) - 1) + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print(f"Playing video: {videos[rand].title}") + self._playing_status = PlayingStatus.PLAYING + self._playing_video = videos[rand] + elif self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: + print(f"Stopping video: {self._playing_video.title}") + self._playing_status = PlayingStatus.PLAYING + self._playing_video = videos[rand] + print(f"Playing video: {self._playing_video.title}") def pause_video(self): """Pauses the current video.""" - - print("pause_video needs implementation") + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print("Cannot pause video: No video is currently playing") + elif self._playing_status == PlayingStatus.PLAYING: + print(f"Pausing video: {self._playing_video.title}") + self._playing_status = PlayingStatus.PAUSED + elif self._playing_status == PlayingStatus.PAUSED: + print(f"Video already paused: {self._playing_video.title}") def continue_video(self): """Resumes playing the current video.""" - - print("continue_video needs implementation") + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print("Cannot continue video: No video is currently playing") + elif self._playing_status == PlayingStatus.PLAYING: + print("Cannot continue video: Video is not paused") + elif self._playing_status == PlayingStatus.PAUSED: + print(f"Continuing video: {self._playing_video.title}") + self._playing_status = PlayingStatus.PLAYING def show_playing(self): """Displays video currently playing.""" - - print("show_playing needs implementation") + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print("No video is currently playing") + elif self._playing_status == PlayingStatus.PLAYING: + print(f"Currently playing: {str(self._playing_video)}") + elif self._playing_status == PlayingStatus.PAUSED: + print(f"Currently playing: {str(self._playing_video)} - PAUSED") def create_playlist(self, playlist_name): """Creates a playlist with a given name. @@ -57,7 +118,17 @@ def create_playlist(self, playlist_name): Args: playlist_name: The playlist name. """ - print("create_playlist needs implementation") + if len(self._list_playlist) == 0: + self._list_playlist.append(Playlist(playlist_name=playlist_name)) + print(f"Successfully created new playlist: {playlist_name}") + else: + for playlist in self._list_playlist: + if playlist_name.upper() == playlist.name.upper(): + print("Cannot create playlist: A playlist with the same name already exists") + break + else: + self._list_playlist.append(Playlist(playlist_name=playlist_name)) + print(f"Successfully created new playlist: {playlist_name}") def add_to_playlist(self, playlist_name, video_id): """Adds a video to a playlist with a given name. @@ -66,12 +137,31 @@ def add_to_playlist(self, playlist_name, video_id): playlist_name: The playlist name. video_id: The video_id to be added. """ - print("add_to_playlist needs implementation") + + video = self._video_library.get_video(video_id) + for playlist in self._list_playlist: + if playlist.name.upper() == playlist_name.upper(): + if video is None: + print(f"Cannot add video to {playlist_name}: Video does not exist") + elif playlist.find_video(video): + print(f"Cannot add video to {playlist_name}: Video already added") + else: + playlist.add_video(video) + print(f"Added video to {playlist_name}: {video.title}") + break + else: + print(f"Cannot add video to {playlist_name}: Playlist does not exist") def show_all_playlists(self): """Display all playlists.""" - print("show_all_playlists needs implementation") + if len(self._list_playlist) == 0: + print("No playlists exist yet") + else: + print("Showing all playlists:") + self._list_playlist = sorted(self._list_playlist, key=lambda x: x.name) + for playlist in self._list_playlist: + print(playlist.name) def show_playlist(self, playlist_name): """Display all videos in a playlist with a given name. @@ -79,7 +169,19 @@ def show_playlist(self, playlist_name): Args: playlist_name: The playlist name. """ - print("show_playlist needs implementation") + + for playlist in self._list_playlist: + if playlist_name.upper() == playlist.name.upper(): + print(f"Showing playlist: {playlist_name}") + if len(playlist.content) == 0: + print("No videos here yet") + else: + for video in playlist.content: + print(str(video)) + break + else: + self._list_playlist.append(Playlist(playlist_name=playlist_name)) + print(f"Cannot show playlist {playlist_name}: Playlist does not exist") def remove_from_playlist(self, playlist_name, video_id): """Removes a video to a playlist with a given name. @@ -88,7 +190,19 @@ def remove_from_playlist(self, playlist_name, video_id): playlist_name: The playlist name. video_id: The video_id to be removed. """ - print("remove_from_playlist needs implementation") + video = self._video_library.get_video(video_id) + for playlist in self._list_playlist: + if playlist.name.upper() == playlist_name.upper(): + if video is None: + print(f"Cannot remove video from {playlist_name}: Video does not exist") + elif not playlist.find_video(video): + print(f"Cannot remove video from {playlist_name}: Video is not in playlist") + else: + print(f"Removed video from {playlist_name}: {video.title}") + playlist.remove_video(video) + break + else: + print(f"Cannot remove video from {playlist_name}: Playlist does not exist") def clear_playlist(self, playlist_name): """Removes all videos from a playlist with a given name. @@ -96,7 +210,13 @@ def clear_playlist(self, playlist_name): Args: playlist_name: The playlist name. """ - print("clears_playlist needs implementation") + for playlist in self._list_playlist: + if playlist.name.upper() == playlist_name.upper(): + playlist.clear() + print(f"Successfully removed all videos from {playlist_name}") + break + else: + print(f"Cannot clear playlist {playlist_name}: Playlist does not exist") def delete_playlist(self, playlist_name): """Deletes a playlist with a given name. @@ -104,7 +224,13 @@ def delete_playlist(self, playlist_name): Args: playlist_name: The playlist name. """ - print("deletes_playlist needs implementation") + for playlist in self._list_playlist: + if playlist.name.upper() == playlist_name.upper(): + self._list_playlist.remove(playlist) + print(f"Deleted playlist: {playlist_name}") + break + else: + print(f"Cannot delete playlist {playlist_name}: Playlist does not exist") def search_videos(self, search_term): """Display all the videos whose titles contain the search_term. diff --git a/python/src/video_playlist.py b/python/src/video_playlist.py index 5836da4..0a0eb61 100644 --- a/python/src/video_playlist.py +++ b/python/src/video_playlist.py @@ -1,5 +1,42 @@ """A video playlist class.""" +from typing import Sequence + +from .video import Video class Playlist: """A class used to represent a Playlist.""" + + def __init__(self, playlist_name: str): + """Video constructor.""" + self._name = playlist_name + self._contents = [] + + @property + def name(self) -> str: + """Returns the title of a video.""" + return self._name + + @property + def content(self) -> Sequence[Video]: + """Returns the list of video which in this playlist.""" + return self._contents + + def add_video(self, video: Video): + self._contents.append(video) + + def remove_video(self, video: Video): + self._contents.remove(video) + + def find_video(self, video: Video): + if len(self._contents) == 0: + return False + else: + for content in self._contents: + if video.video_id == content.video_id: + return True + else: + return False + + def clear(self): + self._contents.clear() \ No newline at end of file From 7fac5a0a76d9e7d87f08a99106d390a95858188d Mon Sep 17 00:00:00 2001 From: ziyic Date: Thu, 1 Jul 2021 02:43:19 +0100 Subject: [PATCH 2/2] feat(video.py;video_player.py;video_playlist.py): All 4 Parts completed All 4 Parts completed --- python/src/video.py | 26 ++++++- python/src/video_player.py | 129 ++++++++++++++++++++++++++++------- python/src/video_playlist.py | 2 +- 3 files changed, 129 insertions(+), 28 deletions(-) diff --git a/python/src/video.py b/python/src/video.py index b1b983d..3d9ccb7 100644 --- a/python/src/video.py +++ b/python/src/video.py @@ -6,11 +6,13 @@ class Video: """A class used to represent a Video.""" - def __init__(self, video_title: str, video_id: str, video_tags: Sequence[str]): + def __init__(self, video_title: str, video_id: str, video_tags: Sequence[str], + video_flagged=False, video_flagged_reason="Not supplied"): """Video constructor.""" self._title = video_title self._video_id = video_id - + self._flagged = video_flagged + self._flagged_reason = video_flagged_reason # Turn the tags into a tuple here so it's unmodifiable, # in case the caller changes the 'video_tags' they passed to us self._tags = tuple(video_tags) @@ -25,6 +27,26 @@ def video_id(self) -> str: """Returns the video id of a video.""" return self._video_id + @property + def flagged(self) -> bool: + """Returns the video flag of a video.""" + return self._flagged + + @flagged.setter + def flagged(self, flag): + """Set the video flag of a video.""" + self._flagged = flag + + @property + def flagged_reason(self) -> str: + """Returns the video flagged_reason of a video.""" + return self._flagged_reason if self._flagged else None + + @flagged_reason.setter + def flagged_reason(self, reason="Not supplied"): + """Set the video flagged_reason of a video.""" + self._flagged_reason = reason + @property def tags(self) -> Sequence[str]: """Returns the list of tags of a video.""" diff --git a/python/src/video_player.py b/python/src/video_player.py index bea469d..e791ea9 100644 --- a/python/src/video_player.py +++ b/python/src/video_player.py @@ -37,7 +37,10 @@ def show_all_videos(self): print("Here's a list of all available videos:") for video in videos: - print(str(video)) + if video.flagged: + print(str(video) + f" - FLAGGED (reason: {video.flagged_reason})") + else: + print(str(video)) def play_video(self, video_id): """Plays the respective video. @@ -48,16 +51,20 @@ def play_video(self, video_id): videos = self._video_library.get_all_videos() for video in videos: if video.video_id == video_id: - if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: - print(f"Playing video: {video.title}") - self._playing_video = video - self._playing_status = PlayingStatus.PLAYING - elif self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: - print(f"Stopping video: {self._playing_video.title}") - self._playing_video = video - print(f"Playing video: {self._playing_video.title}") - self._playing_status = PlayingStatus.PLAYING + if not video.flagged: + if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: + print(f"Playing video: {video.title}") + self._playing_video = video + self._playing_status = PlayingStatus.PLAYING + elif self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: + print(f"Stopping video: {self._playing_video.title}") + self._playing_video = video + print(f"Playing video: {self._playing_video.title}") + self._playing_status = PlayingStatus.PLAYING + else: + print(f"Cannot play video: Video is currently flagged (reason: {video.flagged_reason})") break + else: print("Cannot play video: Video does not exist") @@ -72,16 +79,19 @@ def stop_video(self): def play_random_video(self): """Plays a random video from the video library.""" videos = self._video_library.get_all_videos() - rand = random.randint(0, len(videos) - 1) - if not self._playing_status or self._playing_status == PlayingStatus.STOPPED: - print(f"Playing video: {videos[rand].title}") - self._playing_status = PlayingStatus.PLAYING - self._playing_video = videos[rand] - elif self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: - print(f"Stopping video: {self._playing_video.title}") - self._playing_status = PlayingStatus.PLAYING - self._playing_video = videos[rand] - print(f"Playing video: {self._playing_video.title}") + available_videos = [] + for video in videos: + if not video.flagged: + available_videos.append(video) + if len(available_videos) == 0: + print("No videos available") + else: + rand = random.randint(0, len(available_videos) - 1) + if self._playing_status == PlayingStatus.PLAYING or self._playing_status == PlayingStatus.PAUSED: + self.stop_video() + self.play_video(available_videos[rand].video_id) + else: + self.play_video(available_videos[rand].video_id) def pause_video(self): """Pauses the current video.""" @@ -145,6 +155,9 @@ def add_to_playlist(self, playlist_name, video_id): print(f"Cannot add video to {playlist_name}: Video does not exist") elif playlist.find_video(video): print(f"Cannot add video to {playlist_name}: Video already added") + elif video.flagged: + print(f"Cannot add video to {playlist_name}: " + f"Video is currently flagged (reason: {video.flagged_reason})") else: playlist.add_video(video) print(f"Added video to {playlist_name}: {video.title}") @@ -177,7 +190,10 @@ def show_playlist(self, playlist_name): print("No videos here yet") else: for video in playlist.content: - print(str(video)) + if video.flagged: + print(str(video)+f" - FLAGGED (reason: {video.flagged_reason})") + else: + print(str(video)) break else: self._list_playlist.append(Playlist(playlist_name=playlist_name)) @@ -238,7 +254,30 @@ def search_videos(self, search_term): Args: search_term: The query to be used in search. """ - print("search_videos needs implementation") + videos = self._video_library.get_all_videos() + results = [] + for video in videos: + words = video.title.split(' ') + for word in words: + if search_term.upper() in word.upper() and not video.flagged: + results.append(video) + if len(results) > 0: + print(f"Here are the results for {search_term}:") + for i in range(1, len(results) + 1, 1): + print(f"{i}) {str(results[i - 1])}") + print("Would you like to play any of the above? " + "If yes, specify the number of the video. ") + print("If your answer is not a valid number, we will assume it's a no.") + selection = input() + try: + selection = int(selection) + except ValueError: + return + if int(selection) <= len(results): + self.play_video(results[int(selection) - 1].video_id) + + else: + print(f"No search results for {search_term}") def search_videos_tag(self, video_tag): """Display all videos whose tags contains the provided tag. @@ -246,7 +285,30 @@ def search_videos_tag(self, video_tag): Args: video_tag: The video tag to be used in search. """ - print("search_videos_tag needs implementation") + videos = self._video_library.get_all_videos() + results = [] + for video in videos: + words = video.tags + for word in words: + if video_tag.upper() == word.upper() and not video.flagged: + results.append(video) + if len(results) > 0: + print(f"Here are the results for {video_tag}:") + for i in range(1, len(results) + 1, 1): + print(f"{i}) {str(results[i - 1])}") + print("Would you like to play any of the above? " + "If yes, specify the number of the video. ") + print("If your answer is not a valid number, we will assume it's a no.") + selection = input() + try: + selection = int(selection) + except ValueError: + return + if int(selection) <= len(results): + self.play_video(results[int(selection) - 1].video_id) + + else: + print(f"No search results for {video_tag}") def flag_video(self, video_id, flag_reason=""): """Mark a video as flagged. @@ -255,7 +317,17 @@ def flag_video(self, video_id, flag_reason=""): video_id: The video_id to be flagged. flag_reason: Reason for flagging the video. """ - print("flag_video needs implementation") + video = self._video_library.get_video(video_id) + if video is None: + print("Cannot flag video: Video does not exist") + elif not video.flagged: + if self._playing_video == video: + self.stop_video() + video.flagged = True + video.flagged_reason = flag_reason if len(flag_reason) > 0 else "Not supplied" + print(f"Successfully flagged video: {video.title} (reason: {video.flagged_reason})") + else: + print("Cannot flag video: Video is already flagged") def allow_video(self, video_id): """Removes a flag from a video. @@ -263,4 +335,11 @@ def allow_video(self, video_id): Args: video_id: The video_id to be allowed again. """ - print("allow_video needs implementation") + video = self._video_library.get_video(video_id) + if video is None: + print("Cannot remove flag from video: Video does not exist") + elif video.flagged: + video.flagged = False + print(f"Successfully removed flag from video: {video.title}") + else: + print("Cannot remove flag from video: Video is not flagged") diff --git a/python/src/video_playlist.py b/python/src/video_playlist.py index 0a0eb61..137b0d6 100644 --- a/python/src/video_playlist.py +++ b/python/src/video_playlist.py @@ -39,4 +39,4 @@ def find_video(self, video: Video): return False def clear(self): - self._contents.clear() \ No newline at end of file + self._contents.clear()