-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathims
267 lines (236 loc) · 7.8 KB
/
ims
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#!/usr/bin/env ruby
require "minitest/autorun"
require "minitest/spec"
require "pstore"
require "./music_storage"
class IMS
def initialize(storage_name)
#initialize the terminate flag
#if @terminate flag is true, then mainLoop stops
@terminate = false
@storage = MusicStorage.new(storage_name)
end
def main_loop()
#if @terminate flag is true, end loop
while !@terminate
print "> "
parse_command(gets.chomp)
end
end
# The main parser for all the commands
def parse_command(command)
# i following an re to ignore cases
if /^exit$/i =~ command
exit()
elsif /^help$/i =~ command
help()
elsif /^info$/i =~ command
summary()
elsif /^info track \s*(.+)$/i =~ command
track_number = $~[1]
track_info(track_number)
elsif /^info artist \s*(.+)$/i =~ command
artist_id = $~[1]
artist_info(artist_id)
# Using (?-i) to preserve the case of artist and track names
elsif /^add artist \s*((?-i).+)$/i =~ command
artist_name = $~[1]
add_artist(artist_name)
elsif /^add track \s*((?-i).+) by (\w+)$/i =~ command
track_name = $~[1]
artist_id = $~[2]
add_track(track_name, artist_id)
elsif /^play track \s*(.+)$/i =~ command
track_number = $~[1]
play_track(track_number)
elsif /^count tracks by \s*(.+)$/i =~ command
artist_id = $~[1]
count_tracks(artist_id)
elsif /^list tracks by \s*(\w+)$/i =~ command
artist_id = $~[1]
list_tracks(artist_id)
else
puts "Command not recognized, enter \'help\' for a list of supported commands and their usages."
end
end
def exit()
#save state and change flag @terminate to true
@storage.save
@terminate = true
end
# display the help message
def help()
help = "Commands for IMS:\n"\
"1. help - Display this help message\n"\
"2. exit - Save the current state and exit the program\n"\
"3. info - Display a summary of the current status\n"\
"4. info track <track_number> - Display some info about a track. \n"\
" Example: info track 2\n"\
"5. info artist <artist_id> - Display some info about an artist. \n"\
" Example: info track jh\n"\
"6. add artist <artist_name> - Add an artist to ims. \n"\
" Example: add artist Joe Hisaishi\n"\
"7. add track <track_name> by <artist_id> - Add a track for an existing artist. \n"\
" Example: add track One Summer's Day by jh\n"\
"8. play track <track_number> - Play a track, IMS will record it as played. \n"\
" Example: play track 2\n"\
"9. count tracks by <artist_id> - Count the number of tracks by an given artist.\n"\
" Example: count tracks by jh\n"\
"10. list tracks by <artist_id> - Display all the tracks by the given artist.\n"\
" Example: list tracks by jh\n"
puts help
end
def summary()
#display a summary of the current state
puts "Total number of tracks #{@storage.get_total_track_count}"
puts "Total number of artists #{@storage.get_total_artist_count}"
puts "Last played tracks:"
last_played = @storage.get_last_played
last_played.each do |track|
artist = @storage.get_artist(track.artist_id)
puts "\t#{track.name} by #{artist.name}"
end
end
# List the information about a given track
def track_info(track_number)
# if track_number is in a legal format
if is_track_number(track_number)
# check if the track is in the storage or not
if @storage.has_track(track_number)
track = @storage.get_track(track_number)
artist = @storage.get_artist(track.artist_id)
info = "Info about track #{track_number}:\n"\
"\tName: #{track.name}\n"\
"\tArtist: #{artist.name}\n"\
"\tArtist ID: #{artist.id}\n"
puts info
else
puts "Error: Unknown track number #{track_number}"
end
end
end
# List the information about a given artist
def artist_info(artist_id)
if is_artist_id(artist_id)
if @storage.has_artist(artist_id)
artist = @storage.get_artist(artist_id)
info = "Info about artist #{artist_id}:\n"\
"\tArtist Name: #{artist.name}\n"\
"\tArtist ID: #{artist.id}\n"\
"\tNumber of Tracks: #{artist.tracks.size}"
puts info
else
puts "Error: Unknown artist ID #{artist_id}"
end
end
end
# add a track to the storage
def add_track(track_name, artist_id)
# check if the artist ID exists
if [email protected]_artist(artist_id)
puts "Error: Unrecognized artist ID"
else
number = make_track_number
@storage.add_track(track_name, number, artist_id)
puts "Added #{track_name} as track, track number is #{number}"
end
end
# add an artist to the storage
# artist doesn't have any tracks associated at this point
def add_artist(artist_name)
id = makeartist_id(artist_name)
@storage.add_artist(artist_name, id)
puts "Added #{artist_name} as artist, artist ID is #{id}"
end
# record the given track as played
def play_track(track_number)
@storage.play_track(track_number)
end
# count the total number of tracks in storage for the given artist
def count_tracks(artist_id)
#display the number of tracks know by the specified artist
if is_artist_id(artist_id)
if @storage.has_artist(artist_id)
tracks = @storage.get_tracks_by(artist_id)
puts "Artist #{artist_id} has #{tracks.size} track(s)."
else
puts "Error: Unrecognized artist ID"
end
end
end
# list all the tracks by number and name, for the given artist
def list_tracks(artist_id)
# check if the artist ID exists
if [email protected]_artist(artist_id)
puts "Error: Unrecognized artist ID"
else
artist = @storage.get_artist(artist_id)
artist_tracks = artist.tracks
puts "Tracks by #{artist.name}:"
artist_tracks.each do |track|
puts "\tTrack ##{track.number} - #{track.name}"
end
end
end
# generate an id for a given artist name
def makeartist_id(artist_name)
num = 0
splitName = artist_name.downcase.split
initials = splitName.map {|word| word[0]}.join
id = initials
# if the initials already exist in storage, add a number to it.
if @storage.has_artist(id)
id += num.to_s
num += 1
end
# keep increasing the number until the id doesn't exist in storage.
while @storage.has_artist(id)
id = initials + num.to_s
num += 1
end
return id
end
# track number is just the total number of tracks in storage + 1
def make_track_number()
number = @storage.get_total_track_count + 1
# Convert number to string, so that in @storage, track number is stored as a string
return number.to_s
end
# methods for checking the fomats of track numbers or artist IDs.
def is_track_number(track_number)
if /^\d+$/ =~ track_number
return true
else
puts "Invalid track number, must be digits."
return false
end
end
def is_artist_id(artist_id)
if /^\w+$/ =~ artist_id
return true
else
puts "Invalid artist ID, must be a series of alphanumerical characters."
return false
end
end
end
ims = IMS.new("music_storage.pstore")
ims.main_loop()
describe "Parsing test" do
it "should parse commands correctly" do
t = IMS.new("test.pstore")
t.makeartist_id("Test Artist").must_equal "ta"
t.parse_command("Add Artist Test Artist")
t.makeartist_id("Test Artist").must_equal "ta0"
t.parse_command("add Track Test Track by ta")
t.parse_command("ADD track Test Track 1 by tz")
t.parse_command("play track 1")
t.parse_command("play track 1")
t.parse_command("play track 1")
t.parse_command("play track 1")
t.parse_command("exit")
s = MusicStorage.new("test.pstore")
s.get_tracks_by("ta").size.must_equal 1
s.get_last_played.size.must_equal 3
end
end