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

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

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

Резултати

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

Код

module LazyMode
class Date
attr_accessor :year, :month, :day
def initialize(date)
@year, @month, @day = parse(date)
end
def parse(date)
date.split('-').map(&:to_i)
end
def to_s
"%04d-%02d-%02d" % [@year, @month, @day]
end
def ==(other)
@year == other.year and @month == other.month and @day == other.day
end
def same_week(other)
week, date = [], other
1.upto(6) do
week << date
date = date.next
end
week.include? self
end
def next
new_year, new_month, new_day = @year, @month, @day + 1
if new_day == 31
new_day, new_month = 1, new_month + 1
end
if new_month == 13
new_month, new_year = 1, new_year + 1
end
Date.new("#{new_year}-#{new_month}-#{new_day}")
end
def >(other)
@year > other.year or @month > other.month or @day > other.day
end
def repeat(days)
new_date = self.dup
1.upto(days) { new_date = new_date.next }
new_date
end
end
class Note
attr_accessor :header, :file, :tags, :status, :body, :date
def initialize(header, file, *tags, &block)
@header = header
@file = file
@tags = tags
@status = :topostpone
@body = ""
instance_eval &block
end
def status(symbol = nil)
if symbol.nil?
@status
else
@status = symbol
end
end
def body(text = nil)
if text.nil?
@body
else
@body = text
end
end
def scheduled(date)
if match = date.match(/\+(\d+)([mdw])$/)
mapping = {'d' => 1, 'w' => 7, 'm' => 30}
@repeat_by = match[1].to_i * mapping[match[2]]
end
@date = Date.new(date)
end
def scheduled_for_day(date)
return date == @date if @repeat_by.nil?
while date > @date
@date = @date.repeat(@repeat_by)
end
date == @date
end
def scheduled_for_week(date)
return @date.same_week(date) if @repeat_by.nil?
while date > @date
@date = @date.repeat(@repeat_by)
end
@date.same_week(date)
end
def file_name
file.name
end
def note(header, *tags, &block)
file.inner_note(header, *tags, &block)
end
end
class File
attr_accessor :name, :notes
def initialize(name, &block)
@name = name
@notes = []
@inner_note = []
instance_eval &block
@notes = @notes + @inner_note
@inner_note = []
end
def note(header, *tags, &block)
@notes << Note.new(header, self, *tags, &block)
end
def inner_note(header, *tags, &block)
@inner_note << Note.new(header, self, *tags, &block)
end
def daily_agenda(date)
agenda = DailyAgenda.new
agenda.search(self, date)
agenda
end
def weekly_agenda(date)
agenda = WeeklyAgenda.new
agenda.search(self, date)
agenda
end
end
class Agenda
attr_accessor :notes
def initialize(notes = [])
@notes = notes
end
def where(arguments)
tag_search(arguments[:tag])
.text_search(arguments[:text])
.status_search(arguments[:status])
end
def tag_search(tag)
if tag.nil?
return Agenda.new(@notes)
end
notes = @notes.select { |note| note.tags.include? tag }
Agenda.new notes
end
def text_search(text)
if text.nil?
return Agenda.new(@notes)
end
notes = @notes.select {|note| match_text(note, text) }
Agenda.new notes
end
def match_text(note, text)
note.header.match(text) or note.body.match(text)
end
def status_search(status)
if status.nil?
return Agenda.new(@notes)
end
notes = @notes.select { |note| note.status == status }
Agenda.new notes
end
end
class DailyAgenda < Agenda
def search(file, date)
@notes = file.notes.select do |note|
note.scheduled_for_day(date)
end
end
end
class WeeklyAgenda < Agenda
def search(file, date)
@notes = file.notes.select do |note|
note.scheduled_for_week(date)
end
end
end
def self.create_file(name, &block)
File.new(name, &block)
end
end

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

..................FF...........

Failures:

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

  2) 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-p2c3e8/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)>'

Finished in 0.0225 seconds
31 examples, 2 failures

Failed examples:

rspec /tmp/d20160107-5693-p2c3e8/spec.rb:237 # LazyMode#weekly_agenda returns note scheduled without repeater
rspec /tmp/d20160107-5693-p2c3e8/spec.rb:259 # LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater

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

Мила обнови решението на 21.12.2015 17:09 (преди над 8 години)

+module LazyMode
+
+ class Date
+
+ attr_accessor :year, :month, :day
+
+ def initialize(date)
+ @year, @month, @day = parse(date)
+ end
+
+ def parse(date)
+ date.split('-').map(&:to_i)
+ end
+
+ def to_s
+ "%04d-%02d-%02d" % [@year, @month, @day]
+ end
+
+ def ==(other)
+ @year == other.year and @month == other.month and @day == other.day
+ end
+
+ def same_week(other)
+ week, date = [], other
+ 1.upto(6) do
+ week << date
+ date = date.next
+ end
+ week.include? self
+ end
+
+ def next
+ new_year, new_month, new_day = @year, @month, @day + 1
+ if new_day == 31
+ new_day, new_month = 1, new_month + 1
+ end
+ if new_month == 13
+ new_month, new_year = 1, new_year + 1
+ end
+ Date.new("#{new_year}-#{new_month}-#{new_day}")
+ end
+
+
+ def >(other)
+ @year > other.year or @month > other.month or @day > other.day
+ end
+
+ def repeat(days)
+ new_date = self.dup
+ 1.upto(days) { new_date = new_date.next }
+ new_date
+ end
+ end
+
+ class Note
+
+ attr_accessor :header, :file, :tags, :status, :body, :date
+
+ def initialize(header, file, *tags, &block)
+ @header = header
+ @file = file
+ @tags = tags
+ @status = :topostpone
+ @body = ""
+ instance_eval &block
+ end
+
+ def status(symbol = nil)
+ if symbol.nil?
+ @status
+ else
+ @status = symbol
+ end
+ end
+
+ def body(text = nil)
+ if text.nil?
+ @body
+ else
+ @body = text
+ end
+ end
+
+ def scheduled(date)
+ if match = date.match(/\+(\d+)([mdw])$/)
+ mapping = {'d' => 1, 'w' => 7, 'm' => 30}
+ @repeat_by = match[1].to_i * mapping[match[2]]
+ end
+ @date = Date.new(date)
+ end
+
+ def scheduled_for_day(date)
+ return date == @date if @repeat_by.nil?
+ while date > @date
+ @date = @date.repeat(@repeat_by)
+ end
+ date == @date
+ end
+
+ def scheduled_for_week(date)
+ return @date.same_week(date) if @repeat_by.nil?
+ while date > @date
+ @date = @date.repeat(@repeat_by)
+ end
+ @date.same_week(date)
+ end
+
+ def file_name
+ file.name
+ end
+
+ def note(header, *tags, &block)
+ file.inner_note(header, *tags, &block)
+ end
+ end
+
+ class File
+ attr_accessor :name, :notes
+
+ def initialize(name, &block)
+ @name = name
+ @notes = []
+ @inner_note = []
+ instance_eval &block
+ @notes = @notes + @inner_note
+ @inner_note = []
+ end
+
+ def note(header, *tags, &block)
+ @notes << Note.new(header, self, *tags, &block)
+ end
+
+ def inner_note(header, *tags, &block)
+ @inner_note << Note.new(header, self, *tags, &block)
+ end
+
+ def daily_agenda(date)
+ agenda = DailyAgenda.new
+ agenda.search(self, date)
+ agenda
+ end
+
+ def weekly_agenda(date)
+ agenda = WeeklyAgenda.new
+ agenda.search(self, date)
+ agenda
+ end
+
+ end
+
+ class Agenda
+
+ attr_accessor :notes
+
+ def initialize(notes = [])
+ @notes = notes
+ end
+
+ def where(arguments)
+ tag_search(arguments[:tag])
+ .text_search(arguments[:text])
+ .status_search(arguments[:status])
+ end
+
+ def tag_search(tag)
+ if tag.nil?
+ return Agenda.new(@notes)
+ end
+ notes = @notes.select { |note| note.tags.include? tag }
+ Agenda.new notes
+ end
+
+ def text_search(text)
+ if text.nil?
+ return Agenda.new(@notes)
+ end
+ notes = @notes.select {|note| match_text(note, text) }
+ Agenda.new notes
+ end
+
+ def match_text(note, text)
+ note.header.match(text) or note.body.match(text)
+ end
+
+ def status_search(status)
+ if status.nil?
+ return Agenda.new(@notes)
+ end
+ notes = @notes.select { |note| note.status == status }
+ Agenda.new notes
+ end
+ end
+
+ class DailyAgenda < Agenda
+
+ def search(file, date)
+ @notes = file.notes.select do |note|
+ note.scheduled_for_day(date)
+ end
+ end
+
+ end
+
+ class WeeklyAgenda < Agenda
+
+ def search(file, date)
+ @notes = file.notes.select do |note|
+ note.scheduled_for_week(date)
+ end
+ end
+
+ end
+
+ def self.create_file(name, &block)
+ File.new(name, &block)
+ end
+
+end