Николай обнови решението на 31.10.2011 00:06 (преди около 13 години)
+module AdditionalFunctions
+ def split_and_strip(list, split_char)
+ list.split(split_char).map(&:strip)
+ end
+end
+
+module SongFunctions
+ def find_songs_by_special_filter(songs, filter)
+ songs.select { |song| filter.(song) }
+ end
+
+ def find_songs_by_tags(songs, tags)
+ pos_tags = []
+ neg_tags = []
+ if not tags.instance_of?(Array)
+ tags.end_with?("!") ? neg_tags << tags.delete('!') : pos_tags << tags
+ else
+ tags.each do |tag|
+ tag.end_with?("!") ? neg_tags << tag.chop : pos_tags << tag
+ end
+ end
+ if pos_tags == []
+ songs.select { |song| !comm_elem(song.tags, neg_tags) }
+ else
+ songs.select do |song|
+ comm_elem(song.tags, pos_tags) and !comm_elem(song.tags, neg_tags)
+ end
+ end
+ end
+
+ def find_songs_by_name(songs, song_name)
+ songs.select { |song| song.name == song_name }
+ end
+
+ def find_songs_by_artist(songs, artist_name)
+ songs.select { |song| song.artist == artist_name }
+ end
+
+end
+
+class Song
+ include AdditionalFunctions
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(parsed_line)
+ @name, @artist, @genre = parsed_line[0..2]
+ @tags = []
+ if parsed_line[3] != nil
+ [split_and_strip(parsed_line[3], ',').each { |tag| tags << tag }]
+ end
+ parsed_line.each_with_index do |column, index|
+ if(column.include? "," and index == 2)
+ genres = split_and_strip(column, ",")
+ @genre = genres[0]
+ @subgenre = genres[1]
+ end
+ end
+ @tags << genre.downcase if not tags.include? genre
+ if not tags.include? subgenre and subgenre != nil
+ @tags << subgenre.downcase
+ end
+ end
+end
+
+class Collection
+ include AdditionalFunctions
+ include SongFunctions
+ attr_accessor :songs_as_string, :artist_tags, :songs
+
+ def initialize(songs_as_string, artist_tags)
+ @songs_as_string, @artist_tags = songs_as_string, artist_tags
+ create_songs
+ add_artist_tags
+ end
+
+ def create_songs()
+ songs = []
+ songs_as_string.lines do |line|
+ songs << Song.new(split_and_strip(line, "."))
+ end
+ @songs = songs
+ end
+
+ def add_artist_tags()
+ artist_tags.each do |key, value|
+ songs.select{ |song| song.artist == key}.each do |song|
+ song.tags << value if not comm_elem(song.tags, value)
+ song.tags = song.tags.flatten
+ end
+ end
+ end
+
+ def find(criteria)
+ found_songs = []
+ return songs if criteria == {}
+ criteria.each do |key, value|
+ if(key == :name)
+ found_songs = find_songs_by_name(songs, value)
+ elsif(key == :tags)
+ found_songs = find_songs_by_tags(songs, value)
+ elsif(key == :filter)
+ found_songs = find_songs_by_special_filter(songs, value)
+ elsif(key == :artist)
+ found_songs = find_songs_by_artist(songs, value)
+ end
+ end
+ found_songs
+ end
+
+ def comm_elem(first_list, second_list)
+ return first_list & second_list != []
+ end
+
+end