Решение на Седма задача от Веселин Русинов

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

Към профила на Веселин Русинов

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 25 успешни тест(а)
  • 6 неуспешни тест(а)

Код

module LazyMode
class Date
attr_accessor :day, :month, :year
def initialize(date_string)
@year, @month, @day = * date_string.split('-').map(&:to_i)
end
def to_s
"#{ "%04d" % @year }-#{ "%02d" % @month }-#{ "%02d" % @day }"
end
def add_days(count)
if (@day + count > 30)
add_months(1)
@day += count - 30
else
@day += count
end
self
end
def add_weeks(count)
add_days(7 * count)
self
end
def add_months(count)
if ( @month + count > 12 )
add_years(1)
@month += count - 12
else
@month += count
end
self
end
def add_years(count)
@year += count
self
end
def ==(other)
@year == other.year && @month == other.month && @day == other.day
end
def <=>(other)
[@year, @month, @day] <=> [other.year, other.month, other.day]
end
end
def self.create_file(file_name, &block)
file = File.new(file_name)
file.instance_eval(&block)
file
end
class DailyAgenda
def initialize(file, date)
@file, @date = file, date
if @file.notes != nil
filter_notes
end
end
def filter_notes
@file.notes.each { |note| note.scheduled @date.to_s }
end
def where(*parameters)
FilteredNotes.new(@file.dup, parameters)
end
def notes
@file.notes
end
end
class WeeklyAgenda
def initialize(file, date)
@file = file
@date = date
@file.notes = loop_days
end
def loop_days
result = []
(0.upto(7)).each do |day|
result << collect_weekly_notes(day)
end
result.flatten.uniq
end
def collect_weekly_notes(day)
result = []
if result.size != @file.notes.size
result << get_notes_for_day(day)
end
result
end
def get_notes_for_day(day)
@file.notes.select { |note| note.valid?(@date.dup.add_days(day)) }
end
def notes
@file.notes
end
def where(*parameters)
FilteredNotes.new(@file.dup, parameters)
end
end
class FilteredNotes
def initialize(file, parameters)
@file = file.dup
filter_by_text(parameters[0][:text])
filter_by_status(parameters[0][:status])
filter_by_tag(parameters[0][:tag])
end
def filter_by_tag(tag)
result = []
if tag
collect_tags(tag)
end
result.flatten
end
def collect_tags(tag)
@file.notes = @file.notes.select { |note| note.tags.include? tag }
end
def filter_by_status(status)
result = []
if status
result << collect_status(status)
end
result.flatten
end
def collect_status(status)
@file.notes = @file.notes.select { |note| note.status == status }
end
def notes
@file.notes
end
def filter_by_text(text)
result = []
if text
result << collect_text(text)
end
result.flatten
end
def collect_text(text)
result = []
result << @file.notes.select { |note| note.body =~ text }
result << @file.notes.select { |note| note.header =~ text }
@file.notes = result.flatten.uniq
end
end
class File
attr_accessor :name, :notes
def initialize(file_name)
@name = file_name
@notes = []
end
def daily_agenda(date)
file = self.dup
file.notes.select! { |note| note.valid?(date) }
DailyAgenda.new(file, date)
end
def weekly_agenda(date)
WeeklyAgenda.new(self.dup, date)
end
def note(header, *tags, &block)
note = Note.new(header, tags, self)
note.file_name = @name
note.instance_eval(&block)
@notes << note
end
def add_note(note)
@notes << note
end
def where(*parameters)
FilteredNotes.new(self, parameters)
end
end
class Note
attr_accessor :header, :file_name, :body, :status, :tags, :children, :period
def initialize(header, tags, file)
@tags = tags
@header = header
@status = :topostpone
@file = file
@period = []
end
def note(header, *tags, &block)
note = Note.new(header, tags, @file)
note.instance_eval(&block)
@file.add_note(note)
end
def status(value = nil)
@status = value if value
@status
end
def body(value = nil)
@body = value if value
@body
end
def scheduled(date_string)
@period, split_date = [], date_string.split(' ')
start_date = LazyMode::Date.new(split_date.first)
@period << start_date
repeat = split_date.last[-1]
split_date.last[1.. -2].to_i.downto 1 do |duration|
repeat_by(repeat, start_date, duration)
end
end
def repeat_by(repeat, start_date, duration)
@period << (start_date.dup.add_weeks (duration)) if repeat == 'w'
@period << (start_date.dup.add_months (duration)) if repeat == 'm'
@period << (start_date.dup.add_days (duration)) if repeat == 'd'
@period.reverse
end
def valid?(date)
@period.include?(date)
end
def date
@period.first
end
end
end

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

.....F.....F......FFFF.........

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-o9gfk5/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-o9gfk5/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#weekly_agenda returns note scheduled without repeater
     Failure/Error: expect(agenda.notes.size).to eq(1)
       
       expected: 1
            got: 2
       
       (compared using ==)
     # /tmp/d20160107-5693-o9gfk5/spec.rb:249: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#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-o9gfk5/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)>'

  5) LazyMode#weekly_agenda returns note scheduled with weekly repeater
     Failure/Error: expect(first_note.date.day).to eq(12)
       
       expected: 12
            got: 5
       
       (compared using ==)
     # /tmp/d20160107-5693-o9gfk5/spec.rb:303: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#weekly_agenda returns note scheduled with monthly repeater
     Failure/Error: expect(agenda.notes.size).to eq(1)
       
       expected: 1
            got: 2
       
       (compared using ==)
     # /tmp/d20160107-5693-o9gfk5/spec.rb:327: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.02127 seconds
31 examples, 6 failures

Failed examples:

rspec /tmp/d20160107-5693-o9gfk5/spec.rb:98 # LazyMode LazyMode::Note can have nested notes
rspec /tmp/d20160107-5693-o9gfk5/spec.rb:88 # LazyMode LazyMode::Note #body can have no body
rspec /tmp/d20160107-5693-o9gfk5/spec.rb:237 # LazyMode#weekly_agenda returns note scheduled without repeater
rspec /tmp/d20160107-5693-o9gfk5/spec.rb:259 # LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater
rspec /tmp/d20160107-5693-o9gfk5/spec.rb:283 # LazyMode#weekly_agenda returns note scheduled with weekly repeater
rspec /tmp/d20160107-5693-o9gfk5/spec.rb:315 # LazyMode#weekly_agenda returns note scheduled with monthly repeater

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

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

+module LazyMode
+
+ class Date
+
+ attr_accessor :day, :month, :year
+
+ def initialize(date_string)
+ @year, @month, @day = * date_string.split('-').map(&:to_i)
+ end
+
+ def to_s
+ "#{ "%04d" % @year }-#{ "%02d" % @month }-#{ "%02d" % @day }"
+ end
+
+ def add_days(count)
+ if (@day + count > 30)
+ add_months(1)
+ @day += count - 30
+ else
+ @day += count
+ end
+ self
+ end
+
+ def add_weeks(count)
+ add_days(7 * count)
+ self
+ end
+
+ def add_months(count)
+ if ( @month + count > 12 )
+ add_years(1)
+ @month += count - 12
+ else
+ @month += count
+ end
+ self
+ end
+
+ def add_years(count)
+ @year += count
+ self
+ end
+
+ def ==(other)
+ @year == other.year && @month == other.month && @day == other.day
+ end
+
+ def <=>(other)
+ [@year, @month, @day] <=> [other.year, other.month, other.day]
+ end
+
+ end
+
+ def self.create_file(file_name, &block)
+ file = File.new(file_name)
+ file.instance_eval(&block)
+ file
+ end
+
+ class DailyAgenda
+
+ def initialize(file, date)
+ @file, @date = file, date
+ if @file.notes != nil
+ filter_notes
+ end
+ end
+
+ def filter_notes
+ @file.notes.each { |note| note.scheduled @date.to_s }
+ end
+
+ def where(*parameters)
+ FilteredNotes.new(@file.dup, parameters)
+ end
+
+ def notes
+ @file.notes
+ end
+ end
+
+ class WeeklyAgenda
+
+ def initialize(file, date)
+ @file = file
+ @date = date
+
+ @file.notes = loop_days
+ end
+
+ def loop_days
+ result = []
+ (0.upto(7)).each do |day|
+ result << collect_weekly_notes(day)
+ end
+ result.flatten.uniq
+ end
+
+ def collect_weekly_notes(day)
+ result = []
+ if result.size != @file.notes.size
+ result << get_notes_for_day(day)
+ end
+ result
+ end
+
+ def get_notes_for_day(day)
+ @file.notes.select { |note| note.valid?(@date.dup.add_days(day)) }
+ end
+
+ def notes
+ @file.notes
+ end
+
+ def where(*parameters)
+ FilteredNotes.new(@file.dup, parameters)
+ end
+ end
+
+ class FilteredNotes
+
+ def initialize(file, parameters)
+ @file = file.dup
+ filter_by_text(parameters[0][:text])
+ filter_by_status(parameters[0][:status])
+ filter_by_tag(parameters[0][:tag])
+ end
+
+ def filter_by_tag(tag)
+ result = []
+ if tag
+ collect_tags(tag)
+ end
+ result.flatten
+ end
+
+ def collect_tags(tag)
+ @file.notes = @file.notes.select { |note| note.tags.include? tag }
+ end
+
+ def filter_by_status(status)
+ result = []
+ if status
+ result << collect_status(status)
+ end
+ result.flatten
+ end
+
+ def collect_status(status)
+ @file.notes = @file.notes.select { |note| note.status == status }
+ end
+
+ def notes
+ @file.notes
+ end
+
+ def filter_by_text(text)
+ result = []
+ if text
+ result << collect_text(text)
+ end
+ result.flatten
+ end
+
+ def collect_text(text)
+ result = []
+ result << @file.notes.select { |note| note.body =~ text }
+ result << @file.notes.select { |note| note.header =~ text }
+ @file.notes = result.flatten.uniq
+ end
+ end
+
+ class File
+
+ attr_accessor :name, :notes
+
+ def initialize(file_name)
+ @name = file_name
+ @notes = []
+ end
+
+ def daily_agenda(date)
+ file = self.dup
+ file.notes.select! { |note| note.valid?(date) }
+ DailyAgenda.new(file, date)
+ end
+
+ def weekly_agenda(date)
+ WeeklyAgenda.new(self.dup, date)
+ end
+
+ def note(header, *tags, &block)
+ note = Note.new(header, tags, self)
+ note.file_name = @name
+ note.instance_eval(&block)
+ @notes << note
+ end
+
+ def add_note(note)
+ @notes << note
+ end
+
+ def where(*parameters)
+ FilteredNotes.new(self, parameters)
+ end
+
+ end
+
+ class Note
+
+ attr_accessor :header, :file_name, :body, :status, :tags, :children, :period
+
+ def initialize(header, tags, file)
+ @tags = tags
+ @header = header
+ @status = :topostpone
+ @file = file
+ @period = []
+ end
+
+ def note(header, *tags, &block)
+ note = Note.new(header, tags, @file)
+ note.instance_eval(&block)
+ @file.add_note(note)
+ end
+
+ def status(value = nil)
+ @status = value if value
+ @status
+ end
+
+ def body(value = nil)
+ @body = value if value
+ @body
+ end
+
+ def scheduled(date_string)
+ @period, split_date = [], date_string.split(' ')
+ start_date = LazyMode::Date.new(split_date.first)
+ @period << start_date
+ repeat = split_date.last[-1]
+ split_date.last[1.. -2].to_i.downto 1 do |duration|
+ repeat_by(repeat, start_date, duration)
+ end
+ end
+
+ def repeat_by(repeat, start_date, duration)
+ @period << (start_date.dup.add_weeks (duration)) if repeat == 'w'
+ @period << (start_date.dup.add_months (duration)) if repeat == 'm'
+ @period << (start_date.dup.add_days (duration)) if repeat == 'd'
+ @period.reverse
+ end
+
+ def valid?(date)
+ @period.include?(date)
+ end
+
+ def date
+ @period.first
+ end
+ end
+
+end