Created
July 1, 2021 11:14
-
-
Save chrisbck/50642f56a5c1de6bbca2e6b9cbdb9a1b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google; | |
import java.util.List; | |
/** | |
* A class used to parse and execute a user Command. | |
*/ | |
class CommandParser { | |
private final VideoPlayer videoPlayer; | |
CommandParser(VideoPlayer videoPlayer) { | |
this.videoPlayer = videoPlayer; | |
} | |
/** | |
* Executes the given user command. | |
*/ | |
public void executeCommand(List<String> command) { | |
if (command.isEmpty()) { | |
System.out.println( | |
"Please enter a valid command, " + | |
"type HELP for a list of available commands."); | |
return; | |
} | |
switch (command.get(0).toUpperCase()) { | |
case "NUMBER_OF_VIDEOS": | |
this.videoPlayer.numberOfVideos(); | |
break; | |
case "SHOW_ALL_VIDEOS": | |
this.videoPlayer.showAllVideos(); | |
break; | |
case "PLAY": | |
try { | |
this.videoPlayer.playVideo(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println("Please enter PLAY command followed by video_id."); | |
} | |
break; | |
case "PLAY_RANDOM": | |
this.videoPlayer.playRandomVideo(); | |
break; | |
case "STOP": | |
this.videoPlayer.stopVideo(); | |
break; | |
case "PAUSE": | |
this.videoPlayer.pauseVideo(); | |
break; | |
case "CONTINUE": | |
this.videoPlayer.continueVideo(); | |
break; | |
case "SHOW_PLAYING": | |
this.videoPlayer.showPlaying(); | |
break; | |
case "CREATE_PLAYLIST": | |
try { | |
this.videoPlayer.createPlaylist(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println( | |
"Please enter CREATE_PLAYLIST command followed by a " + | |
"playlist name."); | |
} | |
break; | |
case "ADD_TO_PLAYLIST": | |
try { | |
this.videoPlayer.addVideoToPlaylist(command.get(1), command.get(2)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println( | |
"Please enter ADD_TO_PLAYLIST command followed by a " | |
+ "playlist name and video_id to add."); | |
} | |
break; | |
case "REMOVE_FROM_PLAYLIST": | |
try { | |
this.videoPlayer.removeFromPlaylist(command.get(1), command.get(2)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println( | |
"Please enter REMOVE_FROM_PLAYLIST command followed by a " | |
+ "playlist name and video_id to remove."); | |
} | |
break; | |
case "CLEAR_PLAYLIST": | |
try { | |
this.videoPlayer.clearPlaylist(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println( | |
"Please enter CLEAR_PLAYLIST command followed by a " | |
+ "playlist name."); | |
} | |
break; | |
case "DELETE_PLAYLIST": | |
try { | |
this.videoPlayer.deletePlaylist(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println( | |
"Please enter DELETE_PLAYLIST command followed by a " + | |
"playlist name."); | |
} | |
break; | |
case "SHOW_PLAYLIST": | |
try { | |
this.videoPlayer.showPlaylist(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println("Please enter SHOW_PLAYLIST command followed by a " + | |
"playlist name."); | |
} | |
break; | |
case "SHOW_ALL_PLAYLISTS": | |
this.videoPlayer.showAllPlaylists(); | |
break; | |
case "SEARCH_VIDEOS": | |
try { | |
this.videoPlayer.searchVideos(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println("Please enter SEARCH_VIDEOS command followed by a " + | |
"search term."); | |
} | |
break; | |
case "SEARCH_VIDEOS_WITH_TAG": | |
try { | |
this.videoPlayer.searchVideosWithTag(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println( | |
"Please enter SEARCH_VIDEOS_WITH_TAG command followed by a " + | |
"video tag."); | |
} | |
break; | |
case "FLAG_VIDEO": | |
try { | |
this.videoPlayer.flagVideo(command.get(1), command.get(2)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
try { | |
this.videoPlayer.flagVideo(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException f) { | |
System.out.println("Please enter FLAG_VIDEO command followed by a" + | |
"video_id and an optional flag reason."); | |
} | |
} | |
break; | |
case "ALLOW_VIDEO": | |
try { | |
this.videoPlayer.allowVideo(command.get(1)); | |
} catch (ArrayIndexOutOfBoundsException e) { | |
System.out.println("Please enter ALLOW_VIDEO command followed by a " + | |
"video_id."); | |
} | |
break; | |
case "HELP": | |
this.getHelp(); | |
break; | |
default: | |
System.out.println( | |
"Please enter a valid command, type HELP for a list of " | |
+ "available commands."); | |
break; | |
} | |
} | |
/** | |
* Displays all available commands to the user. | |
*/ | |
private void getHelp() { | |
String helpText = | |
"Available commands:\n" | |
+ " NUMBER_OF_VIDEOS - Shows how many videos are in the library.\n" | |
+ " SHOW_ALL_VIDEOS - Lists all videos from the library.\n" | |
+ " PLAY <video_id> - Plays specified video.\n" | |
+ " PLAY_RANDOM - Plays a random video from the library.\n" | |
+ " STOP - Stop the current video.\n" | |
+ " PAUSE - Pause the current video.\n" | |
+ " CONTINUE - Resume the current paused video.\n" | |
+ " SHOW_PLAYING - Displays the title, url and paused status of the video that is currently playing (or paused).\n" | |
+ " CREATE_PLAYLIST <playlist_name> - Creates a new (empty) playlist with the provided name.\n" | |
+ " ADD_TO_PLAYLIST <playlist_name> <video_id> - Adds the requested video to the playlist.\n" | |
+ " REMOVE_FROM_PLAYLIST <playlist_name> <video_id> - Removes the specified video from the specified playlist\n" | |
+ " CLEAR_PLAYLIST <playlist_name> - Removes all the videos from the playlist.\n" | |
+ " DELETE_PLAYLIST <playlist_name> - Deletes the playlist.\n" | |
+ " SHOW_PLAYLIST <playlist_name> - List all the videos in this playlist.\n" | |
+ " SHOW_ALL_PLAYLISTS - Display all the available playlists.\n" | |
+ " SEARCH_VIDEOS <search_term> - Display all the videos whose titles contain the search_term.\n" | |
+ " SEARCH_VIDEOS_WITH_TAG <tag_name> -Display all videos whose tags contains the provided tag.\n" | |
+ " FLAG_VIDEO <video_id> <flag_reason> - Mark a video as flagged.\n" | |
+ " ALLOW_VIDEO <video_id> - Removes a flag from a video.\n" | |
+ " HELP - Displays help.\n" | |
+ " EXIT - Terminates the program execution.\n"; | |
System.out.println(helpText); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google; | |
import java.util.Arrays; | |
import java.util.Scanner; | |
public class Run { | |
public static void main(String[] args){ | |
System.out.println("Hello and welcome to YouTube, what would you like to do? " | |
+ "Enter HELP for list of available commands or EXIT to terminate."); | |
var videoPlayer = new VideoPlayer(); | |
var parser = new CommandParser(videoPlayer); | |
var scanner = new Scanner(System.in); | |
while (true) { | |
System.out.print("YT> "); | |
var input = scanner.nextLine(); | |
if (input.equalsIgnoreCase("exit")) { | |
System.out.println("YouTube has now terminated its execution. " + | |
"Thank you and goodbye!"); | |
return; | |
} | |
parser.executeCommand(Arrays.asList(input.split("\\s+"))); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google; | |
import java.util.Collections; | |
import java.util.List; | |
/** A class used to represent a video. */ | |
class Video { | |
private final String title; | |
private final String videoId; | |
private final List<String> tags; | |
Video(String title, String videoId, List<String> tags) { | |
this.title = title; | |
this.videoId = videoId; | |
this.tags = Collections.unmodifiableList(tags); | |
} | |
/** Returns the title of the video. */ | |
String getTitle() { | |
return title; | |
} | |
/** Returns the video id of the video. */ | |
String getVideoId() { | |
return videoId; | |
} | |
/** Returns a readonly collection of the tags of the video. */ | |
List<String> getTags() { | |
return tags; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Scanner; | |
import java.util.stream.Collectors; | |
/** | |
* A class used to represent a Video Library. | |
*/ | |
class VideoLibrary { | |
private final HashMap<String, Video> videos; | |
VideoLibrary() { | |
this.videos = new HashMap<>(); | |
try { | |
File file = new File(this.getClass().getResource("/videos.txt").getFile()); | |
Scanner scanner = new Scanner(file); | |
while (scanner.hasNextLine()) { | |
String line = scanner.nextLine(); | |
String[] split = line.split("\\|"); | |
String title = split[0].strip(); | |
String id = split[1].strip(); | |
List<String> tags; | |
if (split.length > 2) { | |
tags = Arrays.stream(split[2].split(",")).map(String::strip).collect( | |
Collectors.toList()); | |
} else { | |
tags = new ArrayList<>(); | |
} | |
this.videos.put(id, new Video(title, id, tags)); | |
} | |
} catch (FileNotFoundException e) { | |
System.out.println("Couldn't find videos.txt"); | |
e.printStackTrace(); | |
} | |
} | |
List<Video> getVideos() { | |
return new ArrayList<>(this.videos.values()); | |
} | |
/** | |
* Get a video by id. Returns null if the video is not found. | |
*/ | |
Video getVideo(String videoId) { | |
return this.videos.get(videoId); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Queue; | |
import java.util.Scanner; | |
import java.util.SortedSet; | |
import java.util.TreeMap; | |
import java.util.TreeSet; | |
public class VideoPlayer { | |
private final VideoLibrary videoLibrary; | |
private Video currentlyPlaying = null; | |
private boolean isCurrentlyPaused = false; | |
private Map<String, Queue<Video>> playlists = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); | |
public VideoPlayer() { | |
this.videoLibrary = new VideoLibrary(); | |
} | |
public void numberOfVideos() { | |
System.out.printf("%s videos in the library%n", videoLibrary.getVideos().size()); | |
} | |
public void showAllVideos() { | |
ArrayList<Video> videoList = new ArrayList<Video>(videoLibrary.getVideos()); | |
// sort the list using comparator | |
Collections.sort(videoList, new Comparator<Video>(){ | |
public int compare(Video video1, Video video2){ | |
return video1.getTitle().compareTo(video2.getTitle()); | |
} | |
}); | |
System.out.println("Here's a list of all available videos:"); | |
for(Video video : videoList){ | |
System.out.print("\t" + video.getTitle() + " (" + video.getVideoId() + ") "); | |
ArrayList<String> tags = new ArrayList<String>(video.getTags()); | |
System.out.println(listAndFormatTags(tags)); | |
} | |
} | |
private String listAndFormatTags(List<String> tags){ | |
String formattedTagsOutput = new String(); | |
formattedTagsOutput = "["; | |
for(String tag : tags){ | |
formattedTagsOutput = formattedTagsOutput.concat(tag + " "); | |
} | |
formattedTagsOutput = formattedTagsOutput.trim(); | |
formattedTagsOutput = formattedTagsOutput.concat("]"); | |
return formattedTagsOutput; | |
} | |
public void playVideo(String videoId) { | |
if(!doesVideoExist(videoId)){ | |
System.out.println("Cannot play video: Video does not exist"); | |
return; | |
} | |
if(currentlyPlaying != null){ | |
stopVideo(); | |
} | |
currentlyPlaying = videoLibrary.getVideo(videoId); | |
isCurrentlyPaused = false; | |
System.out.println("Playing video: " + currentlyPlaying.getTitle()); | |
} | |
public void stopVideo() { | |
if(currentlyPlaying == null){ | |
System.out.println("Cannot stop video: No video is currently playing"); | |
return; | |
} | |
System.out.println("Stopping video: " + currentlyPlaying.getTitle()); | |
currentlyPlaying = null; | |
isCurrentlyPaused = false; | |
} | |
private boolean doesVideoExist(String videoID){ | |
if(videoLibrary.getVideo(videoID) == null){ | |
return false; | |
} | |
else{ | |
return true; | |
} | |
} | |
public void playRandomVideo() { | |
ArrayList<Video> videos = new ArrayList<>(videoLibrary.getVideos()); | |
if(videos.isEmpty()){ | |
System.out.println("No videos available"); | |
return; | |
} | |
// randomize it | |
Collections.shuffle(videos); | |
Video randomVideo = videos.get(0); | |
playVideo(randomVideo.getVideoId()); | |
} | |
public void pauseVideo() { | |
// is a video playing | |
if(currentlyPlaying == null){ | |
System.out.println("Cannot pause video: No video is currently playing"); | |
return; | |
} | |
// is it already paused | |
if(isCurrentlyPaused){ | |
System.out.println("Video already paused: " + currentlyPlaying.getTitle()); | |
return; | |
} | |
// pause video | |
System.out.println("Pausing video: " + currentlyPlaying.getTitle()); | |
isCurrentlyPaused = true; | |
} | |
public void continueVideo() { | |
// is video playing | |
if(currentlyPlaying == null){ | |
System.out.println("Cannot continue video: No video is currently playing"); | |
return; | |
} | |
// is video paused | |
if(!isCurrentlyPaused){ | |
System.out.println("Cannot continue video: Video is not paused"); | |
return; | |
} | |
// continue the video | |
System.out.println("Continuing video: " + currentlyPlaying.getTitle()); | |
isCurrentlyPaused = false; | |
} | |
public void showPlaying() { | |
// is video playing | |
if(currentlyPlaying == null){ | |
System.out.println("No video is currently playing"); | |
return; | |
} | |
// display title, id, tags and pause status | |
System.out.print("Currently playing: " + currentlyPlaying.getTitle() + " (" + currentlyPlaying.getVideoId() + ") "); | |
System.out.print(listAndFormatTags(currentlyPlaying.getTags())); | |
if(isCurrentlyPaused){ | |
System.out.println(" - PAUSED"); | |
} | |
else{ | |
System.out.println(""); | |
} | |
} | |
public void createPlaylist(String playlistName) { | |
// does playlist already exist | |
if(playlists.containsKey(playlistName)){ | |
System.out.println("Cannot create playlist: A playlist with the same name already exists"); | |
return; | |
} | |
// create playlist | |
playlists.put(playlistName, new LinkedList<>()); | |
System.out.println("Successfully created new playlist: " + playlistName); | |
} | |
public void addVideoToPlaylist(String playlistName, String videoId) { | |
// does playlist exist | |
if(!playlists.containsKey(playlistName)){ | |
System.out.println("Cannot add video to " + playlistName + ": Playlist does not exist"); | |
return; | |
} | |
// does video exist | |
if(!doesVideoExist(videoId)){ | |
System.out.println("Cannot add video to " + playlistName + ": Video does not exist"); | |
return; | |
} | |
// is video already in the list | |
Queue<Video> playlist = playlists.get(playlistName); | |
Video video = videoLibrary.getVideo(videoId); | |
if(playlist.contains(video)){ | |
System.out.println("Cannot add video to " + playlistName + ": Video already added"); | |
return; | |
} | |
// add video to playlist | |
playlist.add(video); | |
System.out.println("Added video to " + playlistName + ": " + video.getTitle()); | |
} | |
public void showAllPlaylists() { | |
// are there any playlists yet | |
if(playlists.isEmpty()){ | |
System.out.println("No playlists exist yet"); | |
return; | |
} | |
// get playlist names | |
SortedSet<String> listNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); | |
listNames.addAll(playlists.keySet()); | |
// print list | |
System.out.println("Showing all playlists:"); | |
Iterator<String> iterator = listNames.iterator(); | |
while(iterator.hasNext()){ | |
System.out.println(iterator.next()); | |
} | |
} | |
public void showPlaylist(String playlistName) { | |
// does playlist exist | |
if(!playlists.containsKey(playlistName)){ | |
System.out.println("Cannot show playlist " + playlistName +": Playlist does not exist"); | |
return; | |
} | |
// is playlist empty | |
Queue<Video> playlist = playlists.get(playlistName); | |
System.out.println("Showing playlist: " + playlistName); | |
if(playlist.isEmpty()){ | |
System.out.println("No videos here yet"); | |
return; | |
} | |
// list in order it was created | |
for(int i=0; i < playlist.size(); i++){ | |
Video video = playlist.remove(); | |
System.out.println(video.getTitle() + " (" + video.getVideoId() + ") " + listAndFormatTags(video.getTags())); | |
playlist.add(video); | |
} | |
} | |
public void removeFromPlaylist(String playlistName, String videoId) { | |
//does playlist exist? | |
if(!playlists.containsKey(playlistName)){ | |
System.out.println("Cannot remove video from " + playlistName + ": Playlist does not exist"); | |
return; | |
} | |
//does video exist? | |
if(!doesVideoExist(videoId)){ | |
System.out.println("Cannot remove video from " + playlistName + ": Video does not exist"); | |
return; | |
} | |
//is video already in playlist | |
Queue<Video> playlist = playlists.get(playlistName); | |
Video video = videoLibrary.getVideo(videoId); | |
if(!playlist.remove(video)){ | |
System.out.println("Cannot remove video from " + playlistName + ": Video is not in playlist"); | |
return; | |
} | |
System.out.println("Removed video from " + playlistName + ": " + video.getTitle()); | |
} | |
public void clearPlaylist(String playlistName) { | |
//does playlist exist | |
if(!playlists.containsKey(playlistName)){ | |
System.out.println("Cannot clear playlist " + playlistName + ": Playlist does not exist"); | |
return; | |
} | |
//remove videos | |
playlists.get(playlistName).clear(); | |
System.out.println("Successfully removed all videos from " + playlistName); | |
} | |
public void deletePlaylist(String playlistName) { | |
//does playlist exist? | |
if(!playlists.containsKey(playlistName)){ | |
System.out.println("Cannot delete playlist " + playlistName + ": Playlist does not exist"); | |
return; | |
} | |
//delete playlist | |
playlists.remove(playlistName); | |
System.out.println("Deleted playlist: " + playlistName); | |
} | |
public void searchVideos(String searchTerm) { | |
List<Video> videos = new ArrayList<>(videoLibrary.getVideos()); | |
Map<Integer, String> searchHits = new TreeMap<>(); | |
for(Video video : videos){ | |
if(video.getTitle().toLowerCase().contains(searchTerm.toLowerCase())){ | |
searchHits.put(searchHits.size() + 1, video.getVideoId()); | |
} | |
} | |
if(searchHits.isEmpty()){ | |
System.out.println("No search results for " + searchTerm); | |
} | |
else{ | |
System.out.println("Here are the results for " + searchTerm + ":"); | |
listSearchResults(searchHits); | |
System.out.println("Would you like to play any of the above? If yes, specify the number of the video."); | |
System.out.println("If your answer is not a valid number, we will assume it's a no."); | |
getUserInput(); | |
} | |
} | |
private void listSearchResults(Map<Integer, String> searchHits){ | |
for(int i=1; i <= searchHits.size(); i++){ | |
Video video = videoLibrary.getVideo(searchHits.get(i)); | |
System.out.println(i + ") " + video.getTitle() + " (" + video.getVideoId() + ") " + listAndFormatTags(video.getTags())); | |
} | |
} | |
private Map<String, String> getVideoTitlesAndIds(){ | |
List<Video> videos = new ArrayList<>(videoLibrary.getVideos()); | |
Map<String, String> titles = new HashMap<>(); | |
for(Video video : videos){ | |
titles.put(video.getVideoId(), video.getTitle()); | |
} | |
return titles; | |
} | |
private String getUserInput(){ | |
Scanner scanner = new Scanner(System.in); | |
//System.out.print("YT> "); | |
String input = scanner.nextLine(); | |
return input; | |
} | |
public void searchVideosWithTag(String videoTag) { | |
System.out.println("searchVideosWithTag needs implementation"); | |
} | |
public void flagVideo(String videoId) { | |
System.out.println("flagVideo needs implementation"); | |
} | |
public void flagVideo(String videoId, String reason) { | |
System.out.println("flagVideo needs implementation"); | |
} | |
public void allowVideo(String videoId) { | |
System.out.println("allowVideo needs implementation"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.google; | |
/** A class used to represent a Playlist */ | |
class VideoPlaylist { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment