Решение на Седма задача от Алекс Николов

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

Към профила на Алекс Николов

Резултати

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

Код

class LazyMode
def self.create_file(name, &block)
new_file = LazyMode::File.new(name)
new_file.instance_eval(&block)
new_file
end
class Date
attr_accessor :year, :month, :day
def initialize(date)
@date = date
format_date
@year = @date[0..3].to_i
@month = @date[5..6].to_i
@day = @date[8..9].to_i
end
def to_s
@date
end
def match_date?(date)
old_total_days = LazyMode::Date.new(date).total_days
return total_days == old_total_days if date.length == 10
cycle_period = cycle_period_to_days(date)
(total_days - old_total_days) % cycle_period == 0
end
def match_day_of_week(date)
old_total_days = LazyMode::Date.new(date).total_days
equal_day = (total_days..total_days + 6).find { |d| d == old_total_days }
return equal_day if date.size == 10
cycle_period = cycle_period_to_days(date)
(total_days..total_days + 6).find do |days|
days % cycle_period == old_total_days % cycle_period
end
end
def self.total_days_to_s(total_days)
days_to_s = (total_days / 360).to_s << '-'
days_to_s << ((total_days % 360 / 30) + 1).to_s << "-"
days_to_s << (total_days % 30).to_s
Date.new(days_to_s).to_s
end
def cycle_period_to_days(date)
cycle_period = date[11..-2].to_i
case date[-1]
when 'w' then cycle_period *= 7
when 'm' then cycle_period *= 30
end
cycle_period
end
def total_days
@year * 360 + (@month - 1) * 30 + @day
end
private
def format_date
year_month_day = @date.split(/-| /)
(4 - year_month_day[0].length).times { @date.insert(0, '0') }
(2 - year_month_day[1].length).times { @date.insert(5, '0') }
(2 - year_month_day[2].length).times { @date.insert(8, '0') }
end
end
class Note
attr_accessor :header, :file_name, :tags, :notes
def initialize(file_name, header, *tags)
@file_name = file_name
@header = header
@status = :topostpone
@body = ''
@tags = tags.flatten
@notes = Array.new
end
def body(*note_content)
if note_content.length == 1
@body = note_content.first
else
@body
end
end
def status(*symbols)
if symbols.length == 1
@status = symbols.first
else
@status
end
end
def scheduled(*date)
if date.length == 1
@scheduled = LazyMode::Date.new(date.first).to_s
else
@scheduled
end
end
def note(header, *tags, &block)
new_note = Note.new(@file_name, header, tags)
new_note.instance_eval(&block)
@notes << new_note
@notes += new_note.notes if new_note.notes.size > 0
end
def scheduled_date_in_week(date)
(@total_days...@total_days + 7).find do |days|
days % cycle_period == old_total_days % cycle_period
end
end
class AgendaNote < Note
attr_reader :date
def initialize(note, date)
@file_name = note.file_name
@header, @body = note.header, note.body
@status = note.status
@tags = note.tags
@notes = note.notes
@date = date
end
end
end
class File
attr_reader :name, :notes
def initialize(name)
@name = name
@notes = Array.new
end
def note(header, *tags, &block)
new_note = Note.new(@name, header, tags)
new_note.instance_eval(&block)
@notes << new_note
@notes += new_note.notes if new_note.notes.size > 0
end
def daily_agenda(date)
share_date = -> (note) { date.match_date?(note.scheduled) }
scheduled_notes = @notes.select &share_date
new_agenda_note = -> (note) { Note::AgendaNote.new(note, date) }
scheduled_agenda_notes = scheduled_notes.map &new_agenda_note
Agenda.new(scheduled_agenda_notes)
end
def weekly_agenda(date)
date_within_week = -> (note) { date.match_day_of_week(note.scheduled) }
scheduled_notes = @notes.select &date_within_week
new_agenda_note = -> (note) do
match_days = date.match_day_of_week(note.scheduled)
Note::AgendaNote.new(note, Date.new(Date.total_days_to_s(match_days)))
end
Agenda.new(scheduled_notes.map &new_agenda_note)
end
class Agenda < File
def initialize(scheduled_notes)
@notes = scheduled_notes
end
def where(tag: nil, text: nil, status: nil)
filtered = Array.new
#Тук трябваше да е arity, но sceptic не го прие като английска дума
a = nil_to_i(tag) + nil_to_i(text) + nil_to_i(status)
filtered = filter_tag(filtered, tag: tag)
filtered = filter_text(filtered, text: text)
filtered = filter_status(filtered, status: status)
Agenda.new(filtered.select { |n| filtered.count(n) == a }.uniq)
end
private
def nil_to_i(argument)
argument == nil ? 0 : 1
end
def filter_tag(filtered, tag: nil)
filter_note_tag = -> (n) { n.tags.include? tag }
filtered += @notes.select &filter_note_tag if tag
filtered
end
def filter_text(filtered, text: nil)
filter_note_text = -> (n) { text.match n.header or text.match n.body }
filtered += @notes.select &filter_note_text if text
filtered
end
def filter_status(filtered, status: nil)
filter_note_status = -> (n) { n.status == status }
filtered += @notes.select &filter_note_status if status
filtered
end
end
end
end

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

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

Failures:

  1) 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-bhlsgf/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)>'

  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-bhlsgf/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)>'

  3) 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-bhlsgf/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.01898 seconds
31 examples, 3 failures

Failed examples:

rspec /tmp/d20160107-5693-bhlsgf/spec.rb:208 # LazyMode#daily_agenda does not return note whose start date is in the future
rspec /tmp/d20160107-5693-bhlsgf/spec.rb:259 # LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater
rspec /tmp/d20160107-5693-bhlsgf/spec.rb:337 # LazyMode#weekly_agenda does not return note whose start date is in the future

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

Алекс обнови решението на 19.12.2015 16:34 (преди над 8 години)

+class LazyMode
+ def self.create_file(name, &block)
+ new_file = LazyMode::File.new(name)
+
+ new_file.instance_eval(&block)
+ new_file
+ end
+
+ class Date
+ attr_accessor :year, :month, :day
+
+ def initialize(date)
+ @date = date
+ format_date
+
+ @year = @date[0..3].to_i
+ @month = @date[5..6].to_i
+ @day = @date[8..9].to_i
+ end
+
+ def to_s
+ @date
+ end
+
+ def match_date?(date)
+ old_total_days = LazyMode::Date.new(date).total_days
+ return total_days == old_total_days if date.length == 10
+
+ cycle_period = cycle_period_to_days(date)
+ (total_days - old_total_days) % cycle_period == 0
+ end
+
+ def match_day_of_week(date)
+ old_total_days = LazyMode::Date.new(date).total_days
+ equal_day = (total_days..total_days + 6).find { |d| d == old_total_days }
+ return equal_day if date.size == 10
+
+ cycle_period = cycle_period_to_days(date)
+ (total_days..total_days + 6).find do |days|
+ days % cycle_period == old_total_days % cycle_period
+ end
+ end
+
+ def self.total_days_to_s(total_days)
+ days_to_s = (total_days / 360).to_s << '-'
+ days_to_s << ((total_days % 360 / 30) + 1).to_s << "-"
+ days_to_s << (total_days % 30).to_s
+ Date.new(days_to_s).to_s
+ end
+
+ def cycle_period_to_days(date)
+ cycle_period = date[11..-2].to_i
+ case date[-1]
+ when 'w' then cycle_period *= 7
+ when 'm' then cycle_period *= 30
+ end
+ cycle_period
+ end
+
+ def total_days
+ @year * 360 + (@month - 1) * 30 + @day
+ end
+
+ private
+
+ def format_date
+ year_month_day = @date.split(/-| /)
+
+ (4 - year_month_day[0].length).times { @date.insert(0, '0') }
+ (2 - year_month_day[1].length).times { @date.insert(5, '0') }
+ (2 - year_month_day[2].length).times { @date.insert(8, '0') }
+ end
+ end
+
+ class Note
+ attr_accessor :header, :file_name, :tags, :notes
+
+ def initialize(file_name, header, *tags)
+ @file_name = file_name
+ @header = header
+ @status = :topostpone
+ @body = ''
+ @tags = tags.flatten
+ @notes = Array.new
+ end
+
+ def body(*note_content)
+ if note_content.length == 1
+ @body = note_content.first
+ else
+ @body
+ end
+ end
+
+ def status(*symbols)
+ if symbols.length == 1
+ @status = symbols.first
+ else
+ @status
+ end
+ end
+
+ def scheduled(*date)
+ if date.length == 1
+ @scheduled = LazyMode::Date.new(date.first).to_s
+ else
+ @scheduled
+ end
+ end
+
+ def note(header, *tags, &block)
+ new_note = Note.new(@file_name, header, tags)
+
+ new_note.instance_eval(&block)
+ @notes << new_note
+ @notes += new_note.notes if new_note.notes.size > 0
+ end
+
+ def scheduled_date_in_week(date)
+ (@total_days...@total_days + 7).find do |days|
+ days % cycle_period == old_total_days % cycle_period
+ end
+ end
+
+ class AgendaNote < Note
+ attr_reader :date
+
+ def initialize(note, date)
+ @file_name = note.file_name
+ @header, @body = note.header, note.body
+ @status = note.status
+ @tags = note.tags
+ @notes = note.notes
+ @date = date
+ end
+ end
+ end
+
+ class File
+ attr_reader :name, :notes
+
+ def initialize(name)
+ @name = name
+ @notes = Array.new
+ end
+
+ def note(header, *tags, &block)
+ new_note = Note.new(@name, header, tags)
+
+ new_note.instance_eval(&block)
+ @notes << new_note
+ @notes += new_note.notes if new_note.notes.size > 0
+ end
+
+ def daily_agenda(date)
+ share_date = -> (note) { date.match_date?(note.scheduled) }
+ scheduled_notes = @notes.select &share_date
+
+ new_agenda_note = -> (note) { Note::AgendaNote.new(note, date) }
+ scheduled_agenda_notes = scheduled_notes.map &new_agenda_note
+ Agenda.new(scheduled_agenda_notes)
+ end
+
+ def weekly_agenda(date)
+ date_within_week = -> (note) { date.match_day_of_week(note.scheduled) }
+ scheduled_notes = @notes.select &date_within_week
+
+ new_agenda_note = -> (note) do
+ match_days = date.match_day_of_week(note.scheduled)
+ Note::AgendaNote.new(note, Date.new(Date.total_days_to_s(match_days)))
+ end
+ Agenda.new(scheduled_notes.map &new_agenda_note)
+ end
+
+ class Agenda < File
+ def initialize(scheduled_notes)
+ @notes = scheduled_notes
+ end
+
+ def where(tag: nil, text: nil, status: nil)
+ filtered = Array.new
+ #Тук трябваше да е arity, но sceptic не го прие като английска дума
+ a = nil_to_i(tag) + nil_to_i(text) + nil_to_i(status)
+
+ filtered = filter_tag(filtered, tag: tag)
+ filtered = filter_text(filtered, text: text)
+ filtered = filter_status(filtered, status: status)
+
+ Agenda.new(filtered.select { |n| filtered.count(n) == a }.uniq)
+ end
+
+ private
+
+ def nil_to_i(argument)
+ argument == nil ? 0 : 1
+ end
+
+ def filter_tag(filtered, tag: nil)
+ filter_note_tag = -> (n) { n.tags.include? tag }
+ filtered += @notes.select &filter_note_tag if tag
+ filtered
+ end
+
+ def filter_text(filtered, text: nil)
+ filter_note_text = -> (n) { text.match n.header or text.match n.body }
+ filtered += @notes.select &filter_note_text if text
+ filtered
+ end
+
+ def filter_status(filtered, status: nil)
+ filter_note_status = -> (n) { n.status == status }
+ filtered += @notes.select &filter_note_status if status
+ filtered
+ end
+ end
+ end
+end