Решение на Седма задача от Теодор Климентов

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

Към профила на Теодор Климентов

Резултати

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

Код

class LazyMode
class Date
DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/
MONTHS = 30
YEARS = MONTHS * 12
def initialize(date_string)
raise RuntimeError unless date_string =~ DATE_PATTERN
year, month, day = date_string.match(DATE_PATTERN).captures
@total_days = day.to_i - 1 +
month.to_i.pred * MONTHS +
year.to_i.pred * YEARS
end
def year
1 + @total_days / YEARS
end
def month
1 + @total_days % YEARS / MONTHS
end
def day
@total_days % MONTHS % YEARS + 1
end
def +(days)
date = Date.new(self.to_s)
date.instance_eval { @total_days += days }
date
end
def -(other)
@total_days - other.total_days
end
def to_s
'%04d-%02d-%02d' % [year, month, day]
end
protected
def total_days
@total_days
end
end
end
class LazyMode
class Occurrence
OCCURRENCE_PATTERN = /^(.{10})(?: \+(\d+)([dwm]))?$/
PERIODS = {'d' => 1, 'w' => 7, 'm' => 30}
def self.empty_occurrence
Occurrence.new '0000-00-00 +0d' do
def match(date)
false
end
end
end
def initialize(string)
date, times, period = string.match(OCCURRENCE_PATTERN).captures
@date = Date.new(date)
@period = times ? times.to_i * PERIODS[period] : 0
end
def match(date)
return false if date - @date < 0
(@period == 0 && (date - @date) == 0) ||
(@period != 0 && (date - @date) % @period == 0)
end
end
end
class LazyMode
module NotesCollection
def note(header, *tags, &block)
builder = create_note_builder(header, tags)
builder.instance_eval(&block) if block_given?
push_note(builder.get_note)
end
end
end
class LazyMode
class NoteBuilder
include NotesCollection
def initialize(file, header, tags)
@note = Note.new(file, header, tags)
@note.body = ''
@note.status = :topostpone
@note.occurrence = Occurrence.empty_occurrence
@note.notes = []
end
def scheduled(occurrence)
@note.occurrence = Occurrence.new occurrence
end
def status(status)
@note.status = status
end
def body(body)
@note.body = body
end
def get_note
@note
end
def push_note(sub_note)
@note.notes.push sub_note
end
def create_note_builder(header, tags)
NoteBuilder.new(@note.file_name, header, tags)
end
end
end
class LazyMode
class Note
attr_accessor :file_name, :header, :tags
attr_accessor :body, :status, :notes, :occurrence
def initialize(file, header, tags)
@file_name = file
@header = header
@tags = tags
end
end
end
class LazyMode
class Agenda
attr_reader :notes
def initialize(date, days, notes)
@date = date
@days = days
@notes = notes
end
def where(status: nil, tag: nil, text: nil)
notes = filter_by_status(@notes, status)
notes = filter_by_text(notes, text)
notes = filter_by_tag(notes, tag)
Agenda.new(@date, @days, notes)
end
private
def filter_by_status(notes, status)
return notes unless status
notes.select { |note| note.status == status }
end
def filter_by_text(notes, text)
return notes unless text
notes.select { |note| note.header =~ text || note.body =~ text }
end
def filter_by_tag(notes, tag)
return notes unless tag
notes.select { |note| note.tags.include? tag }
end
end
end
class LazyMode
class PeriodAgenda < Agenda
def initialize(date, days, notes)
super(date, days, select_notes(date, days, notes))
end
private
def select_notes(date, days, notes)
(0...days).reduce [] do |result, day|
result.concat(select_notes_for_day(notes, date + day))
end
end
def select_notes_for_day(notes, day)
notes.reduce [] do |result, note|
push_note_for_day(result, note, day)
result.concat(select_notes_for_day(note.notes, day))
end
end
def push_note_for_day(notes, note, day)
if note.occurrence.match day
notes.push(note_for_day(note, day))
end
end
def note_for_day(note, day)
new_note = note.clone
new_note.define_singleton_method(:date) do
day
end
new_note
end
end
end
class LazyMode
class File
include NotesCollection
attr_reader :notes, :name
def initialize(name, &block)
@name = name
@notes = []
end
def daily_agenda(date)
PeriodAgenda.new(date, 1, @notes)
end
def weekly_agenda(date)
PeriodAgenda.new(date, 7, @notes)
end
protected
def push_note(note)
@notes.push note
end
def create_note_builder(header, tags)
NoteBuilder.new(@name, header, tags)
end
end
end
class LazyMode
def self.create_file(name, &block)
file = File.new name
file.instance_eval(&block) if block_given?
file
end
end

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

..............F.....F..........

Failures:

  1) LazyMode#daily_agenda returns note scheduled with weekly repeater
     Failure/Error: scheduled '2012-12-5 +1w'
     NoMethodError:
       undefined method `captures' for nil:NilClass
     # /tmp/d20160107-5693-7a45q5/solution.rb:64:in `initialize'
     # /tmp/d20160107-5693-7a45q5/solution.rb:103:in `new'
     # /tmp/d20160107-5693-7a45q5/solution.rb:103:in `scheduled'
     # /tmp/d20160107-5693-7a45q5/spec.rb:166:in `block (5 levels) in <top (required)>'
     # /tmp/d20160107-5693-7a45q5/solution.rb:82:in `instance_eval'
     # /tmp/d20160107-5693-7a45q5/solution.rb:82:in `note'
     # /tmp/d20160107-5693-7a45q5/spec.rb:165:in `block (4 levels) in <top (required)>'
     # /tmp/d20160107-5693-7a45q5/solution.rb:249:in `instance_eval'
     # /tmp/d20160107-5693-7a45q5/solution.rb:249:in `create_file'
     # /tmp/d20160107-5693-7a45q5/spec.rb:164: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 note scheduled with weekly repeater
     Failure/Error: scheduled '2012-12-5 +1w'
     NoMethodError:
       undefined method `captures' for nil:NilClass
     # /tmp/d20160107-5693-7a45q5/solution.rb:64:in `initialize'
     # /tmp/d20160107-5693-7a45q5/solution.rb:103:in `new'
     # /tmp/d20160107-5693-7a45q5/solution.rb:103:in `scheduled'
     # /tmp/d20160107-5693-7a45q5/spec.rb:286:in `block (5 levels) in <top (required)>'
     # /tmp/d20160107-5693-7a45q5/solution.rb:82:in `instance_eval'
     # /tmp/d20160107-5693-7a45q5/solution.rb:82:in `note'
     # /tmp/d20160107-5693-7a45q5/spec.rb:285:in `block (4 levels) in <top (required)>'
     # /tmp/d20160107-5693-7a45q5/solution.rb:249:in `instance_eval'
     # /tmp/d20160107-5693-7a45q5/solution.rb:249:in `create_file'
     # /tmp/d20160107-5693-7a45q5/spec.rb:284: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.02045 seconds
31 examples, 2 failures

Failed examples:

rspec /tmp/d20160107-5693-7a45q5/spec.rb:163 # LazyMode#daily_agenda returns note scheduled with weekly repeater
rspec /tmp/d20160107-5693-7a45q5/spec.rb:283 # LazyMode#weekly_agenda returns note scheduled with weekly repeater

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

Теодор обнови решението на 21.12.2015 16:39 (преди над 8 години)

+class LazyMode
+ class Date
+ DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/
+ MONTHS = 30
+ YEARS = MONTHS * 12
+
+ def initialize(date_string)
+ raise RuntimeError unless date_string =~ DATE_PATTERN
+ year, month, day = date_string.match(DATE_PATTERN).captures
+
+ @total_days = day.to_i - 1 +
+ month.to_i.pred * MONTHS +
+ year.to_i.pred * YEARS
+ end
+
+ def year
+ 1 + @total_days / YEARS
+ end
+
+ def month
+ 1 + @total_days % YEARS / MONTHS
+ end
+
+ def day
+ @total_days % MONTHS % YEARS + 1
+ end
+
+ def +(days)
+ date = Date.new(self.to_s)
+ date.instance_eval { @total_days += days }
+ date
+ end
+
+ def -(other)
+ @total_days - other.total_days
+ end
+
+ def to_s
+ '%04d-%02d-%02d' % [year, month, day]
+ end
+
+ protected
+
+ def total_days
+ @total_days
+ end
+ end
+end
+
+class LazyMode
+ class Occurrence
+ OCCURRENCE_PATTERN = /^(.{10})(?: \+(\d+)([dwm]))?$/
+ PERIODS = {'d' => 1, 'w' => 7, 'm' => 30}
+
+ def self.empty_occurrence
+ Occurrence.new '0000-00-00 +0d' do
+ def match(date)
+ false
+ end
+ end
+ end
+
+ def initialize(string)
+ date, times, period = string.match(OCCURRENCE_PATTERN).captures
+ @date = Date.new(date)
+ @period = times ? times.to_i * PERIODS[period] : 0
+ end
+
+ def match(date)
+ return false if date - @date < 0
+ (@period == 0 && (date - @date) == 0) ||
+ (@period != 0 && (date - @date) % @period == 0)
+ end
+ end
+end
+
+class LazyMode
+ module NotesCollection
+ def note(header, *tags, &block)
+ builder = create_note_builder(header, tags)
+
+ builder.instance_eval(&block) if block_given?
+
+ push_note(builder.get_note)
+ end
+ end
+end
+
+class LazyMode
+ class NoteBuilder
+ include NotesCollection
+
+ def initialize(file, header, tags)
+ @note = Note.new(file, header, tags)
+
+ @note.body = ''
+ @note.status = :topostpone
+ @note.occurrence = Occurrence.empty_occurrence
+ @note.notes = []
+ end
+
+ def scheduled(occurrence)
+ @note.occurrence = Occurrence.new occurrence
+ end
+
+ def status(status)
+ @note.status = status
+ end
+
+ def body(body)
+ @note.body = body
+ end
+
+ def get_note
+ @note
+ end
+
+ def push_note(sub_note)
+ @note.notes.push sub_note
+ end
+
+ def create_note_builder(header, tags)
+ NoteBuilder.new(@note.file_name, header, tags)
+ end
+ end
+end
+
+class LazyMode
+ class Note
+ attr_accessor :file_name, :header, :tags
+ attr_accessor :body, :status, :notes, :occurrence
+
+ def initialize(file, header, tags)
+ @file_name = file
+ @header = header
+ @tags = tags
+ end
+ end
+end
+
+class LazyMode
+ class Agenda
+ attr_reader :notes
+
+ def initialize(date, days, notes)
+ @date = date
+ @days = days
+ @notes = notes
+ end
+
+ def where(status: nil, tag: nil, text: nil)
+ notes = filter_by_status(@notes, status)
+ notes = filter_by_text(notes, text)
+ notes = filter_by_tag(notes, tag)
+ Agenda.new(@date, @days, notes)
+ end
+
+ private
+
+ def filter_by_status(notes, status)
+ return notes unless status
+ notes.select { |note| note.status == status }
+ end
+
+ def filter_by_text(notes, text)
+ return notes unless text
+ notes.select { |note| note.header =~ text || note.body =~ text }
+ end
+
+ def filter_by_tag(notes, tag)
+ return notes unless tag
+ notes.select { |note| note.tags.include? tag }
+ end
+ end
+end
+
+class LazyMode
+ class PeriodAgenda < Agenda
+ def initialize(date, days, notes)
+ super(date, days, select_notes(date, days, notes))
+ end
+
+ private
+
+ def select_notes(date, days, notes)
+ (0...days).reduce [] do |result, day|
+ result.concat(select_notes_for_day(notes, date + day))
+ end
+ end
+
+ def select_notes_for_day(notes, day)
+ notes.reduce [] do |result, note|
+ push_note_for_day(result, note, day)
+ result.concat(select_notes_for_day(note.notes, day))
+ end
+ end
+
+ def push_note_for_day(notes, note, day)
+ if note.occurrence.match day
+ notes.push(note_for_day(note, day))
+ end
+ end
+
+ def note_for_day(note, day)
+ new_note = note.clone
+ new_note.define_singleton_method(:date) do
+ day
+ end
+ new_note
+ end
+ end
+end
+
+class LazyMode
+ class File
+ include NotesCollection
+
+ attr_reader :notes, :name
+
+ def initialize(name, &block)
+ @name = name
+ @notes = []
+ end
+
+ def daily_agenda(date)
+ PeriodAgenda.new(date, 1, @notes)
+ end
+
+ def weekly_agenda(date)
+ PeriodAgenda.new(date, 7, @notes)
+ end
+
+ protected
+
+ def push_note(note)
+ @notes.push note
+ end
+
+ def create_note_builder(header, tags)
+ NoteBuilder.new(@name, header, tags)
+ end
+ end
+end
+
+class LazyMode
+ def self.create_file(name, &block)
+ file = File.new name
+
+ file.instance_eval(&block) if block_given?
+
+ file
+ end
+end