Николай обнови решението на 31.10.2011 00:44 (преди около 13 години)
+class Song
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(name, artist, genre, subgenre, tags)
+ @name, @artist = name, artist
+ @genre, @subgenre = genre, subgenre
+ @tags = tags
+ end
+
+ def same_name?(name)
+ @name == name
+ end
+
+ def same_artist?(artist)
+ @artist == artist
+ end
+
+ def contain_tags?(tags_list)
+ tags_list = Array(tags_list)
+
+ tags_list.each do |tag|
+ if tag.end_with? '!'
+ if @tags.include? tag.chop then return false end
+ else
+ if not @tags.include? tag then return false end
+ end
+ end
+
+ true
+ end
+
+ def inspect
+ "--
+ name: #{self.name}, aritst: #{self.artist}, genre: #{self.genre},
+ subgenre: #{self.subgenre}, tags: #{self.tags}
+ --"
+ end
+end
+
+class Collection
+
+ def initialize(songs_as_string = '', artist_tags = {})
+ @collection, @artist_tags = [], artist_tags
+ parsed_lines = songs_as_string.lines.to_a
+ @collection = parsed_lines.map{ |line| parse_song line.chomp }
+ end
+
+ def parse_song(song_string)
+ attributes_list = song_string.split('.').each { |str| str.strip! }
+ genre_list = attributes_list[2].split(',').each { |str| str.strip! }
+ tags_list = attributes_list.fetch(3, "")
+ tags_list = tags_list.split(',').each { |str| str.strip! }
+
+ name, artist = attributes_list[0], attributes_list[1]
+ genre, subgenre = genre_list[0], genre_list.fetch(1, nil)
+ tags = tags_list | @artist_tags.fetch(artist, []) | Array(genre.downcase)
+ tags |= Array(subgenre == nil ? nil : subgenre.downcase)
+
+ Song.new name, artist, genre, subgenre, tags
+ end
+
+ def find(criteria = {})
+ result = @collection
+
+ if criteria.has_key? :name
+ result = result.select { |song| song.same_name? criteria[:name] }
+ end
+
+ if criteria.has_key? :artist
+ result = result.select { |song| song.same_artist? criteria[:artist] }
+ end
+
+ if criteria.has_key? :tags
+ result = result.select { |song| song.contain_tags? criteria[:tags] }
+ end
+
+ if criteria.has_key? :filter
+ result = result.select &criteria[:filter]
+ end
+
+ result
+ end
+end