Методи обнови решението на 04.11.2013 17:27 (преди около 11 години)
+module Criteria
+ def status(status)
+ -> (task) { task.status == status }
+ end
+
+ def priority(priority)
+ -> (task) { task.priority == priority }
+ end
+
+ def tags(tags)
+ -> (task) { task.has_them_all? tags }
+ end
+
+ def &(criteria)
+ -> (task) { criteria.call(task) and call(task) }
+ end
+
+ def |(criteria)
+ -> (task) { criteria.call(task) or call(task) }
+ end
+
+ def !()
+ -> (task) { not call(task) }
+ end
+
+end
+
+class Hash
+ def status
+ self[:status].strip.downcase.to_sym
+ end
+
+ def description
+ self[:description].strip
+ end
+
+ def priority
+ self[:priority].strip.downcase.to_sym
+ end
+
+ def tags
+ if self[:tags] then
+ self[:tags].scan(/[^,]+/).map(&:strip)
+ else
+ []
+ end
+ end
+
+ def has_them_all?(tags)
+ tags.all? { |tag| self.tags.include? tag }
+ end
+
+end
+
+module TodoList
+ include Criteria
+
+ def parse(raw_list)
+ list_fields = [:status, :description, :priority, :tags]
+ raw_list.scan(/[^\n]+/).map do |task|
+ Hash[list_fields.zip task.scan(/[^\|]+/)]
+ end
+ end
+
+ def filter(criterias)
+ select { |task| criterias.call task}
+ end
+
+ def adjoin(list)
+ self + list
+ end
+
+ def tasks_todo
+ filter Criteria.status(:todo)
+ end
+
+ def tasks_in_progress
+ filter Criteria.status(:current)
+ end
+
+ def tasks_completed
+ filter(Criteria.status(:done)).length
+ end
+
+ def completed?
+ all? { |task| task.status == :done }
+ end
+
+end
+include TodoList