Александър обнови решението на 31.10.2011 04:53 (преди около 13 години)
+class Song
+ attr_reader :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(name, artist, genre, subgenre, tags)
+ @name = name
+ @artist = artist
+ @genre = genre
+ @subgenre = subgenre
+ @tags = tags
+ end
+end
+
+class Collection
+
+ def initialize(songs_as_string, artist_tags={})
+ @collection = []
+ @artist_tags = artist_tags
+ songs_as_string.each_line { |song|
+ song_splitted = process_song_info(song.split('.'))
+ @collection << Song.new(
+ song_splitted[0], song_splitted[1], song_splitted[2],
+ song_splitted[3], song_splitted[4])
+ }
+ end
+
+ def process_song_info(song_splitted)
+ song_splitted = song_splitted.map {|i| i.strip}
+ genre_splitted = song_splitted[2].split(', ')
+ song_splitted[2] = genre_splitted[0]
+ song_splitted.insert(3, genre_splitted[1])
+ genre_splitted = genre_splitted.map {|i| i.downcase}
+ if song_splitted[4]
+ song_splitted[4] = song_splitted[4].split(", ")
+ song_splitted[4] |= genre_splitted | Array(@artist_tags[song_splitted[1]])
+ else
+ song_splitted[4] = genre_splitted | Array(@artist_tags[song_splitted[1]])
+ end
+ song_splitted
+ end
+
+ def find(criteria)
+ @criteria = criteria
+ name_criteria = lambda { |song| return true if not @criteria[:name]
+ song.name == @criteria[:name]
+ }
+ artist_criteria = lambda { |song| return true if not @criteria[:artist]
+ song.artist == @criteria[:artist]
+ }
+ filter_criteria = @criteria[:filter] || lambda { |song| return true }
+ @collection.select { |song|
+ name_criteria.(song) and artist_criteria.(song) and
+ filter_criteria.(song) and tags_criteria(song)
+ }
+ end
+
+ def tags_criteria(song)
+ Array(@criteria[:tags]).each do |tag|
+ return false if tag.end_with?('!') and song.tags.include?(tag.chop)
+ return false if not tag.end_with?('!') and not song.tags.include?(tag)
+ end
+ true
+ end
+end