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

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

Към профила на Станимира Влаева

Резултати

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

Код

module LazyMode
def self.create_file(name, &block)
File.new(name, &block)
end
class Date
include Comparable
PREFIX = '0'
DAYS_PER_IDENTIFIER = {d: 1, w: 7, m: 30}
attr_accessor :year, :month, :day, :step
def initialize(string)
date = string.split(' ')[0].split('-').map { |s| s.to_i }
@year = date[0]
@month = date[1]
@day = date[2]
repeat = string.split(' ')[1]
@step = calculate_step(repeat) if not repeat.nil?
end
def <=>(other)
[@year, @month, @day] <=> [other.year, other.month, other.day]
end
def increase_days(step = @step)
@day += step
put_in_ranges
self
end
def to_s
year = add_prefix(@year.to_s, 4, PREFIX)
month = add_prefix(@month.to_s, 2, PREFIX)
day = add_prefix(@day.to_s, 2, PREFIX)
[year, month, day].join('-')
end
private
def add_prefix(string, count, prefix)
string.rjust(count, prefix)
end
def put_in_ranges
@month += (@day % 30 == 0) ? (@day / 30 - 1) : @day / 30
@day = (@day % 30 == 0) ? 30 : (@day % 30)
@year += (@month % 12 == 0) ? (@month / 12 - 1) : @month / 12
@month = (@month % 12 == 0) ? 12 : (@month % 12)
end
def calculate_step(repeat)
period_identifier = repeat.slice(-1).to_sym
count = repeat.slice(1..-1).to_i
DAYS_PER_IDENTIFIER[period_identifier] * count
end
end
class Note
attr_reader :header, :body, :status, :tags
attr_reader :file_name, :file
attr_reader :scheduled, :date
def initialize(header, file, *tags, &block)
@header, @file, @tags = header, file, tags
@file_name = file.name
@body = ''
@status = :topostpone
file.notes << self
instance_eval &block
end
def body(body = nil)
@body = body if body
@body
end
def scheduled(date = nil)
if date
@scheduled = date
@date = Date.new(date)
end
@scheduled
end
def status(status = nil)
@status = status if status
@status
end
def scheduled_for(date)
while(not @date.step.nil? and date > @date)
@date.increase_days
end
@date == date
end
def note(header, *tags, &block)
new_note = self.class.new(header, @file, *tags, &block)
end
end
class File
attr_accessor :name, :notes
def initialize(name, &block)
@name = name
@notes = []
instance_eval &block
end
def note(header, *tags, &block)
new_note = Note.new(header, self, *tags, &block)
end
def daily_agenda(date)
Agenda.new daily_notes(date)
end
def weekly_agenda(from)
week = []
0.upto(6) { |i| week << from.dup.increase_days(i) }
weekly_notes = []
week.each { |day| weekly_notes << daily_notes(day) }
weekly_notes.flatten!
Agenda.new weekly_notes
end
private
def daily_notes(date)
@notes.select { |note| note.scheduled_for(date) }
end
end
class Agenda
attr_accessor :notes
def initialize(notes)
@notes = notes
end
def where(status: nil, tag: nil, text: nil)
notes = @notes.dup
filter_by_status(notes, status) unless status.nil?
filter_by_tag(notes, tag) unless tag.nil?
filter_by_text(notes, text) unless text.nil?
self.class.new(notes)
end
private
def filter_by_status(notes, status)
notes.reject! { |note| note.status != status }
end
def filter_by_tag(notes, tag)
notes.reject! { |note| not (note.tags.include? tag) }
end
def filter_by_text(notes, text)
notes.reject! { |note| not (note.header =~ text or note.body =~ text) }
end
end
end

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

...................FFF.........

Failures:

  1) LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater
     Failure/Error: expect(agenda.notes.map(&:date).map(&:day)).to match_array([11, 12])
       expected collection contained:  [11, 12]
       actual collection contained:    [12, 12]
       the missing elements were:      [11]
       the extra elements were:        [12]
     # /tmp/d20160107-5693-1vwjmvu/spec.rb:280: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: expect(first_note.date.day).to eq(12)
       
       expected: 12
            got: 19
       
       (compared using ==)
     # /tmp/d20160107-5693-1vwjmvu/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)>'

  3) LazyMode#weekly_agenda returns note scheduled with monthly repeater
     Failure/Error: expect(note.date.month).to eq(1)
       
       expected: 1
            got: 3
       
       (compared using ==)
     # /tmp/d20160107-5693-1vwjmvu/spec.rb:333: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.01802 seconds
31 examples, 3 failures

Failed examples:

rspec /tmp/d20160107-5693-1vwjmvu/spec.rb:259 # LazyMode#weekly_agenda returns multiple notes with different dates when scheduled with daily repeater
rspec /tmp/d20160107-5693-1vwjmvu/spec.rb:283 # LazyMode#weekly_agenda returns note scheduled with weekly repeater
rspec /tmp/d20160107-5693-1vwjmvu/spec.rb:315 # LazyMode#weekly_agenda returns note scheduled with monthly repeater

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

Станимира обнови решението на 20.12.2015 23:29 (преди над 8 години)

+module LazyMode
+ def self.create_file(name, &block)
+ File.new(name, &block)
+ end
+
+ class Date
+ include Comparable
+ PREFIX = '0'
+ DAYS_PER_IDENTIFIER = {d: 1, w: 7, m: 30}
+ attr_accessor :year, :month, :day, :step
+
+ def initialize(string)
+ date = string.split(' ')[0].split('-').map { |s| s.to_i }
+ @year = date[0]
+ @month = date[1]
+ @day = date[2]
+
+ repeat = string.split(' ')[1]
+ @step = calculate_step(repeat) if not repeat.nil?
+ end
+
+ def <=>(other)
+ [@year, @month, @day] <=> [other.year, other.month, other.day]
+ end
+
+ def increase_days(step = @step)
+ @day += step
+ put_in_ranges
+ end
+
+ def in_interval?(from, to = from)
+ while(not @step.nil? and from > self)
+ self.increase_days
+ end
+ from <= self and self <= to
+ end
+
+ def to_s
+ year = add_prefix(@year.to_s, 4, PREFIX)
+ month = add_prefix(@month.to_s, 2, PREFIX)
+ day = add_prefix(@day.to_s, 2, PREFIX)
+
+ [year, month, day].join('-')
+ end
+
+ private
+
+ def add_prefix(string, count, prefix)
+ string.rjust(count, prefix)
+ end
+
+ def put_in_ranges
+ @month += (@day % 30 == 0) ? (@day / 30 - 1) : @day / 30
+ @day = (@day % 30 == 0) ? 30 : (@day % 30)
+
+ @year += (@month % 12 == 0) ? (@month / 12 - 1) : @month / 12
+ @month = (@month % 12 == 0) ? 12 : (@month % 12)
+ end
+
+ def calculate_step(repeat)
+ period_identifier = repeat.slice(-1).to_sym
+ count = repeat.slice(1..-1).to_i
+ DAYS_PER_IDENTIFIER[period_identifier] * count
+ end
+ end
+
+ class Note
+ attr_reader :header, :body, :status, :tags
+ attr_reader :file_name, :file
+ attr_reader :scheduled, :date
+
+ def initialize(header, file, *tags, &block)
+ @header, @file, @tags = header, file, tags
+ @file_name = file.name
+ @body = ''
+ @status = :topostpone
+
+ file.notes << self
+ instance_eval &block
+ end
+
+ def body(body = nil)
+ @body = body if body
+ @body
+ end
+
+ def scheduled(date = nil)
+ if date
+ @scheduled = date
+ @date = Date.new(date)
+ end
+ @scheduled
+ end
+
+ def status(status = nil)
+ @status = status if status
+ @status
+ end
+
+ def note(header, *tags, &block)
+ new_note = self.class.new(header, @file, *tags, &block)
+ end
+ end
+
+ class File
+ attr_accessor :name, :notes
+
+ def initialize(name, &block)
+ @name = name
+ @notes = []
+ instance_eval &block
+ end
+
+ def note(header, *tags, &block)
+ new_note = Note.new(header, self, *tags, &block)
+ end
+
+ def daily_agenda(date)
+ agenda = @notes.select { |note| note.date.in_interval? date }
+ Agenda.new(agenda)
+ end
+
+ def weekly_agenda(from)
+ to = from.dup
+ to.increase_days(7)
+
+ agenda = @notes.select { |note| note.date.in_interval?(from, to) }
+ Agenda.new(agenda)
+ end
+ end
+
+ class Agenda
+ attr_accessor :notes
+
+ def initialize(notes)
+ @notes = notes
+ end
+
+ def where(status: nil, tag: nil, text: nil)
+ notes = @notes.dup
+ filter_by_status(notes, status) unless status.nil?
+ filter_by_tag(notes, tag) unless tag.nil?
+ filter_by_text(notes, text) unless text.nil?
+
+ self.class.new(notes)
+ end
+
+ private
+
+ def filter_by_status(notes, status)
+ notes.reject! { |note| note.status != status }
+ end
+
+ def filter_by_tag(notes, tag)
+ notes.reject! { |note| not (note.tags.include? tag) }
+ end
+
+ def filter_by_text(notes, text)
+ notes.reject! { |note| not (note.header =~ text or note.body =~ text) }
+ end
+ end
+end

Станимира обнови решението на 21.12.2015 16:33 (преди над 8 години)

module LazyMode
def self.create_file(name, &block)
File.new(name, &block)
end
class Date
include Comparable
PREFIX = '0'
DAYS_PER_IDENTIFIER = {d: 1, w: 7, m: 30}
attr_accessor :year, :month, :day, :step
def initialize(string)
date = string.split(' ')[0].split('-').map { |s| s.to_i }
@year = date[0]
@month = date[1]
@day = date[2]
repeat = string.split(' ')[1]
@step = calculate_step(repeat) if not repeat.nil?
end
def <=>(other)
[@year, @month, @day] <=> [other.year, other.month, other.day]
end
def increase_days(step = @step)
@day += step
put_in_ranges
+ self
end
- def in_interval?(from, to = from)
- while(not @step.nil? and from > self)
- self.increase_days
- end
- from <= self and self <= to
- end
-
def to_s
year = add_prefix(@year.to_s, 4, PREFIX)
month = add_prefix(@month.to_s, 2, PREFIX)
day = add_prefix(@day.to_s, 2, PREFIX)
[year, month, day].join('-')
end
private
def add_prefix(string, count, prefix)
string.rjust(count, prefix)
end
def put_in_ranges
@month += (@day % 30 == 0) ? (@day / 30 - 1) : @day / 30
@day = (@day % 30 == 0) ? 30 : (@day % 30)
@year += (@month % 12 == 0) ? (@month / 12 - 1) : @month / 12
@month = (@month % 12 == 0) ? 12 : (@month % 12)
end
def calculate_step(repeat)
period_identifier = repeat.slice(-1).to_sym
count = repeat.slice(1..-1).to_i
DAYS_PER_IDENTIFIER[period_identifier] * count
end
end
class Note
attr_reader :header, :body, :status, :tags
attr_reader :file_name, :file
attr_reader :scheduled, :date
def initialize(header, file, *tags, &block)
@header, @file, @tags = header, file, tags
@file_name = file.name
@body = ''
@status = :topostpone
file.notes << self
instance_eval &block
end
def body(body = nil)
@body = body if body
@body
end
def scheduled(date = nil)
if date
@scheduled = date
@date = Date.new(date)
end
@scheduled
end
def status(status = nil)
@status = status if status
@status
end
+ def scheduled_for(date)
+ while(not @date.step.nil? and date > @date)
+ @date.increase_days
+ end
+ @date == date
+ end
+
def note(header, *tags, &block)
new_note = self.class.new(header, @file, *tags, &block)
end
end
class File
attr_accessor :name, :notes
def initialize(name, &block)
@name = name
@notes = []
instance_eval &block
end
def note(header, *tags, &block)
new_note = Note.new(header, self, *tags, &block)
end
def daily_agenda(date)
- agenda = @notes.select { |note| note.date.in_interval? date }
- Agenda.new(agenda)
+ Agenda.new daily_notes(date)
end
def weekly_agenda(from)
- to = from.dup
- to.increase_days(7)
+ week = []
+ 0.upto(6) { |i| week << from.dup.increase_days(i) }
- agenda = @notes.select { |note| note.date.in_interval?(from, to) }
- Agenda.new(agenda)
+ weekly_notes = []
+ week.each { |day| weekly_notes << daily_notes(day) }
+ weekly_notes.flatten!
+
+ Agenda.new weekly_notes
+ end
+
+ private
+
+ def daily_notes(date)
+ @notes.select { |note| note.scheduled_for(date) }
end
end
class Agenda
attr_accessor :notes
def initialize(notes)
@notes = notes
end
def where(status: nil, tag: nil, text: nil)
notes = @notes.dup
filter_by_status(notes, status) unless status.nil?
filter_by_tag(notes, tag) unless tag.nil?
filter_by_text(notes, text) unless text.nil?
self.class.new(notes)
end
private
def filter_by_status(notes, status)
notes.reject! { |note| note.status != status }
end
def filter_by_tag(notes, tag)
notes.reject! { |note| not (note.tags.include? tag) }
end
def filter_by_text(notes, text)
notes.reject! { |note| not (note.header =~ text or note.body =~ text) }
end
end
end