Решение на Седма задача от Денис Михайлов

Обратно към всички решения

Към профила на Денис Михайлов

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 21 успешни тест(а)
  • 10 неуспешни тест(а)

Код

module LazyMode
class << self
def create_file(file_name, &block)
File.new(file_name, &block)
end
end
end
module LazyMode::Notable
def notes
if @notes_as_array
@notes_as_array
else
@notes_as_array = get_notes_as_array
end
end
private
def note(header, *tags, &block)
@notes << LazyMode::Note.new(header, @name || @file_name, *tags, &block)
end
def get_notes_as_array
@notes.inject([]) do |all_notes, note|
all_notes << note
all_notes += note.notes
end
end
end
class LazyMode::Date
attr_accessor :year, :month, :day
def initialize(date_string = "")
@year, @month, @day = date_string.split('-').map {|part| part.to_i}
end
def to_s
"#{'%04d' % @year}-#{'%02d' % @month}-#{'%02d' % @day}"
end
def -(other)
to_days - other.to_days
end
def is_after?(other)
to_days > other.to_days
end
def to_days
@year * 360 + @month * 30 + @day
end
def travel_in_time(days)
self.class.from_days(to_days + days)
end
class << self
def from_days(days)
year, month, day = days / 360, days / 30 % 12, days % 30
self.new("#{year}-#{month}-#{day}")
end
end
end
class LazyMode::File
include LazyMode::Notable
attr_reader :name
def initialize(file_name, &block)
@name, @notes = file_name, []
instance_eval(&block)
end
def daily_agenda(date)
LazyMode::Agenda.new(notes, date, :daily)
end
def weekly_agenda(date)
LazyMode::Agenda.new(notes, date, :weekly)
end
end
class LazyMode::Agenda
attr_reader :notes
def initialize(notes, date, type)
@notes = notes.select {|note| note.belongs_to_agenda?(date, type)}
@notes = @notes.map {|note| note.reschedule(date)}
end
def where(text: //, tag: nil, status: nil)
filtered_tasks = self.dup
filtered_tasks.notes.select! do |note|
select_note?(note, text, tag, status)
end
filtered_tasks
end
private
def select_note?(note, text, tag, status)
(text === note.body or text === note.header) and
(tag ? note.tags.include?(tag) : true) and
(status ? note.status == status : true)
end
end
class LazyMode::Note
include LazyMode::Notable
attr_reader :header, :tags, :file_name
attr_accessor :date
RECURRENCE_INTERVAL = {'m' => 30, 'w' => 7, 'd' => 1}
def initialize(header, file_name, *tags, &block)
@header, @file_name, @tags, @notes = header, file_name, tags ? tags : [], []
instance_eval(&block)
end
def body(body = @body)
@body = body
end
def status(status = @status || :topostpone)
@status = status
end
def scheduled(date = nil)
if date
date, recurrence = date.split(" ")
set_recurrence(recurrence)
@date = LazyMode::Date.new(date)
else
@date
end
end
def belongs_to_agenda?(date, type)
if (type == :weekly)
(0..6) === days_to_closest_occurrence(date)
else
days_to_closest_occurrence(date) == 0
end
end
def reschedule(date)
rescheduled = self.dup
rescheduled.date = date.travel_in_time(days_to_closest_occurrence(date))
rescheduled
end
private
def set_recurrence(recurrence)
if recurrence
days = RECURRENCE_INTERVAL[recurrence[2]]
@recurrence_interval = recurrence[1].to_i * days
end
end
def days_to_closest_occurrence(date)
days = scheduled - date
@recurrence_interval ? days % @recurrence_interval : days
end
end

Лог от изпълнението

.....F.....FFFF.F.FFF.F........

Failures:

  1) LazyMode LazyMode::Note can have nested notes
     Failure/Error: expect(file.notes.first.body).to eq('')
       
       expected: ""
            got: nil
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:114:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) LazyMode LazyMode::Note #body can have no body
     Failure/Error: expect(file.notes.first.body).to eq('')
       
       expected: ""
            got: nil
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:94:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) LazyMode#daily_agenda returns note scheduled without repeater
     Failure/Error: expect(note.date.year).to eq(2012)
       
       expected: 2012
            got: 2013
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:136:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) LazyMode#daily_agenda returns note scheduled with daily repeater
     Failure/Error: expect(note.date.year).to eq(2012)
       
       expected: 2012
            got: 2013
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:158:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) LazyMode#daily_agenda returns note scheduled with weekly repeater
     Failure/Error: expect(note.date.year).to eq(2012)
       
       expected: 2012
            got: 2013
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:180:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) LazyMode#daily_agenda does not return note whose start date is in the future
     Failure/Error: expect(agenda.notes.size).to eq(0)
       
       expected: 0
            got: 1
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:216:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) LazyMode#weekly_agenda returns note scheduled without repeater
     Failure/Error: expect(note.date.year).to eq(2012)
       
       expected: 2012
            got: 2013
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:254:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater
     Failure/Error: expect(agenda.notes.size).to eq(2)
       
       expected: 2
            got: 1
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:271:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) LazyMode#weekly_agenda returns note scheduled with weekly repeater
     Failure/Error: expect(first_note.date.year).to eq(2012)
       
       expected: 2012
            got: 2013
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:301:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  10) LazyMode#weekly_agenda does not return note whose start date is in the future
     Failure/Error: expect(agenda.notes.size).to eq(0)
       
       expected: 0
            got: 1
       
       (compared using ==)
     # /tmp/d20160107-5693-uke2ab/spec.rb:345:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.02396 seconds
31 examples, 10 failures

Failed examples:

rspec /tmp/d20160107-5693-uke2ab/spec.rb:98 # LazyMode LazyMode::Note can have nested notes
rspec /tmp/d20160107-5693-uke2ab/spec.rb:88 # LazyMode LazyMode::Note #body can have no body
rspec /tmp/d20160107-5693-uke2ab/spec.rb:119 # LazyMode#daily_agenda returns note scheduled without repeater
rspec /tmp/d20160107-5693-uke2ab/spec.rb:141 # LazyMode#daily_agenda returns note scheduled with daily repeater
rspec /tmp/d20160107-5693-uke2ab/spec.rb:163 # LazyMode#daily_agenda returns note scheduled with weekly repeater
rspec /tmp/d20160107-5693-uke2ab/spec.rb:208 # LazyMode#daily_agenda does not return note whose start date is in the future
rspec /tmp/d20160107-5693-uke2ab/spec.rb:237 # LazyMode#weekly_agenda returns note scheduled without repeater
rspec /tmp/d20160107-5693-uke2ab/spec.rb:259 # LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater
rspec /tmp/d20160107-5693-uke2ab/spec.rb:283 # LazyMode#weekly_agenda returns note scheduled with weekly repeater
rspec /tmp/d20160107-5693-uke2ab/spec.rb:337 # LazyMode#weekly_agenda does not return note whose start date is in the future

История (1 версия и 0 коментара)

Денис обнови решението на 20.12.2015 23:34 (преди около 9 години)

+module LazyMode
+
+ class << self
+
+ def create_file(file_name, &block)
+ File.new(file_name, &block)
+ end
+
+ end
+
+end
+
+module LazyMode::Notable
+
+ def notes
+ if @notes_as_array
+ @notes_as_array
+ else
+ @notes_as_array = get_notes_as_array
+ end
+ end
+
+ private
+
+ def note(header, *tags, &block)
+ @notes << LazyMode::Note.new(header, @name || @file_name, *tags, &block)
+ end
+
+ def get_notes_as_array
+ @notes.inject([]) do |all_notes, note|
+ all_notes << note
+ all_notes += note.notes
+ end
+ end
+
+end
+
+class LazyMode::Date
+ attr_accessor :year, :month, :day
+
+ def initialize(date_string = "")
+ @year, @month, @day = date_string.split('-').map {|part| part.to_i}
+ end
+
+ def to_s
+ "#{'%04d' % @year}-#{'%02d' % @month}-#{'%02d' % @day}"
+ end
+
+ def -(other)
+ to_days - other.to_days
+ end
+
+ def is_after?(other)
+ to_days > other.to_days
+ end
+
+ def to_days
+ @year * 360 + @month * 30 + @day
+ end
+
+ def travel_in_time(days)
+ self.class.from_days(to_days + days)
+ end
+
+ class << self
+
+ def from_days(days)
+ year, month, day = days / 360, days / 30 % 12, days % 30
+ self.new("#{year}-#{month}-#{day}")
+ end
+
+ end
+
+end
+
+class LazyMode::File
+ include LazyMode::Notable
+ attr_reader :name
+
+ def initialize(file_name, &block)
+ @name, @notes = file_name, []
+ instance_eval(&block)
+ end
+
+ def daily_agenda(date)
+ LazyMode::Agenda.new(notes, date, :daily)
+ end
+
+ def weekly_agenda(date)
+ LazyMode::Agenda.new(notes, date, :weekly)
+ end
+
+end
+
+class LazyMode::Agenda
+ attr_reader :notes
+
+ def initialize(notes, date, type)
+ @notes = notes.select {|note| note.belongs_to_agenda?(date, type)}
+ @notes = @notes.map {|note| note.reschedule(date)}
+ end
+
+ def where(text: //, tag: nil, status: nil)
+ filtered_tasks = self.dup
+ filtered_tasks.notes.select! do |note|
+ select_note?(note, text, tag, status)
+ end
+ filtered_tasks
+ end
+
+ private
+
+ def select_note?(note, text, tag, status)
+ (text === note.body or text === note.header) and
+ (tag ? note.tags.include?(tag) : true) and
+ (status ? note.status == status : true)
+ end
+
+end
+
+class LazyMode::Note
+ include LazyMode::Notable
+ attr_reader :header, :tags, :file_name
+ attr_accessor :date
+
+ RECURRENCE_INTERVAL = {'m' => 30, 'w' => 7, 'd' => 1}
+
+ def initialize(header, file_name, *tags, &block)
+ @header, @file_name, @tags, @notes = header, file_name, tags ? tags : [], []
+ instance_eval(&block)
+ end
+
+ def body(body = @body)
+ @body = body
+ end
+
+ def status(status = @status || :topostpone)
+ @status = status
+ end
+
+ def scheduled(date = nil)
+ if date
+ date, recurrence = date.split(" ")
+ set_recurrence(recurrence)
+ @date = LazyMode::Date.new(date)
+ else
+ @date
+ end
+ end
+
+ def belongs_to_agenda?(date, type)
+ if (type == :weekly)
+ (0..6) === days_to_closest_occurrence(date)
+ else
+ days_to_closest_occurrence(date) == 0
+ end
+ end
+
+ def reschedule(date)
+ rescheduled = self.dup
+ rescheduled.date = date.travel_in_time(days_to_closest_occurrence(date))
+ rescheduled
+ end
+
+ private
+
+ def set_recurrence(recurrence)
+ if recurrence
+ days = RECURRENCE_INTERVAL[recurrence[2]]
+ @recurrence_interval = recurrence[1].to_i * days
+ end
+ end
+
+ def days_to_closest_occurrence(date)
+ days = scheduled - date
+ @recurrence_interval ? days % @recurrence_interval : days
+ end
+
+end