Георги обнови решението на 31.10.2011 16:16 (преди около 13 години)
+class Song
+ def initialize(name, artist, genre, subgenre, tags)
+ @name = name
+ @artist = artist
+ @genre = genre
+ @subgenre = subgenre
+ @tags = tags
+ end
+
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def has_tags?(tags_array)
+ with_excl = tags_array.select{ |tag| tag.end_with?("!") }
+ without_excl = tags_array - with_excl
+ (without_excl == (@tags & without_excl)) && ([] == (@tags & with_excl))
+ end
+end
+
+
+class Collection
+ def initialize(songs_as_string, artist_tags)
+ @all_songs = songs_factory(songs_as_string, artist_tags)
+ @found_songs = []
+ end
+
+ def find(criteria)
+ if criteria.empty?
+ return @all_songs
+ end
+ @found_songs = []
+ if criteria.has_key?(:name)
+ find_song_by_name(criteria[:name])
+ end
+ if criteria.has_key?(:artist)
+ find_song_by_artist(criteria[:artist])
+ end
+ if criteria.has_key?(:tags)
+ find_song_by_tags(criteria[:tags])
+ end
+ if criteria.has_key?(:filter)
+ find_song_by_filter(criteria[:filter])
+ end
+ @found_songs
+ end
+
+ private
+ def songs_factory(songs_as_string, artist_tags)
+ all_songs = []
+ songs_as_string.each_line do |song_line|
+ song = create_song_from_line(song_line, artist_tags)
+ all_songs << song
+ end
+ all_songs
+ end
+
+ def create_song_from_line(song_line, artist_tags)
+ song_fields = song_line.split(".").collect(&:strip)
+ song_name, song_artist = song_fields[0], song_fields[1]
+ genre, subgenre = song_fields[2].split(",").collect(&:strip)
+ if song_fields[3] != nil
+ all_tags = Array(song_fields[3].split(",")).collect(&:strip)
+ else
+ all_tags = []
+ end
+ all_tags << genre.downcase
+ all_tags << subgenre.downcase if subgenre != nil
+ if artist_tags.has_key?(song_artist)
+ all_tags += artist_tags[song_artist]
+ end
+ Song.new(song_name, song_artist, genre, subgenre, all_tags)
+ end
+
+ def find_song_by_name(name)
+ if @found_songs.empty?
+ @all_songs.each{ |song| @found_songs << song if song.name == name }
+ else
+ @found_songs = @found_songs.select{ |song| song.name == name }
+ end
+ end
+
+ def find_song_by_artist(artist)
+ if @found_songs.empty?
+ @all_songs.each{ |song| @found_songs << song if song.artist == artist }
+ else
+ @found_songs = @found_songs.select{ |song| song.artist == artist }
+ end
+ end
+
+ def find_song_by_tags(tags)
+ tags_array = Array[tags]
+ if @found_songs.empty?
+ @all_songs.each{ |sg| @found_songs << sg if sg.has_tags?(tags_array) }
+ else
+ @found_songs = @found_songs.select{ |song| song.has_tags?(tags_array) }
+ end
+ end
+
+ def find_song_by_filter(filter)
+ if @found_songs.empty?
+ @all_songs.each{ |song| @found_songs << song if filter.(song) }
+ else
+ @found_songs = @found_songs.select{ |song| filter.(song) }
+ end
+ end
+end