Иван обнови решението на 04.11.2013 11:32 (преди около 11 години)
+class TodoTask
+ attr_reader :status, :description, :priority, :tags
+
+ def initialize(status, description, priority, tags)
+ @status = status
+ @description = description
+ @priority = priority
+ @tags = tags
+ end
+end
+
+class TaskComparer
+ attr_reader :comparable
+
+ def initialize (comparable)
+ @comparable = comparable
+ end
+
+ def compare (tasks)
+ comparable.(tasks)
+ end
+
+ def &(other)
+ old_comparable = comparable
+ @comparable = ->(tasks) {old_comparable.(tasks) & other.compare(tasks)}
+ self
+ end
+
+ def |(other)
+ old_comparable = comparable
+ @comparable = ->(tasks) {old_comparable.(tasks) | other.compare(tasks)}
+ self
+ end
+end
+
+class Criteria
+ def Criteria.status (status)
+ compare = -> (task) { task.status == status}
+ return TaskComparer.new(-> (tasks) { tasks.select &compare })
+ end
+
+ def Criteria.priority (priority)
+ compare = -> (task) { task.priority == priority }
+ return TaskComparer.new(->(tasks) { tasks.select &compare })
+ end
+
+ def Criteria.tags (tags)
+ compare = -> (task) { (task.tags | tags) == task.tags }
+ return TaskComparer.new( ->(tasks) { tasks.select &compare })
+ end
+end
+
+class TaskParser
+ def TaskParser.parse_line (text)
+ TodoTask.new(status(text[0]), desc(text[1]), priority(text[2]), tags(text[3]))
+ end
+
+ def TaskParser.status (text)
+ case(text)
+ when "TODO" then :todo
+ when "CURRENT" then :current
+ when "DONE" then :done
+ end
+ end
+
+ def TaskParser.desc (text)
+ text
+ end
+
+ def TaskParser.priority (text)
+ case(text)
+ when "High" then :high
+ when "Normal" then :normal
+ when "Low" then :low
+ end
+ end
+
+ def TaskParser.tags (text)
+ text.split(',').each(&:strip!)
+ end
+end
+
+class TodoList
+ include Enumerable
+ attr_accessor :tasks
+
+ def initialize (tasks)
+ @tasks = tasks
+ end
+
+ def each
+ tasks.each{|task| yield task}
+ end
+
+ def TodoList.parse (text)
+ strip_line = ->(line) { line.split('|').each(&:strip!) }
+ tasks = text.each_line.map{|line| TaskParser.parse_line (strip_line.(line)) }
+ TodoList.new tasks
+ end
+
+ def filter (comparer)
+ TodoList.new comparer.compare(tasks)
+ end
+
+ def adjoin(todo_list)
+ TodoList.new (tasks | todo_list.tasks)
+ end
+
+ def tasks_todo
+ tasks.select { |task| task.status == :todo}.count
+ end
+
+ def tasks_in_progress
+ tasks.select { |task| task.status == :current}.count
+ end
+
+ def tasks_completed
+ tasks.select { |task| task.status == :done}.count
+ end
+
+ def completed?
+ tasks.all? { |task| task.status == :done}
+ end
+end