Марк обнови решението на 21.12.2015 14:56 (преди около 9 години)
+class LazyMode
+ def self.create_file(file_name, &block)
+ file = File.new(file_name)
+ file.instance_eval &block if block_given?
+ file
+ end
+
+ class Date
+ attr_accessor :period
+
+ def initialize(date)
+ @year = date.split("-")[0].rjust(4, "0")
+ @month = date.split("-")[1].rjust(2, "0")
+ @day = date.split("-")[2].rjust(2, "0")
+ end
+
+ def day
+ @day.to_i
+ end
+
+ def year
+ @year.to_i
+ end
+
+ def month
+ @month.to_i
+ end
+
+ def to_s
+ [@year, @month, @day].join("-")
+ end
+
+ def add_day
+ @day == "30" ? @day = "01" : @day = (day + 1).to_s.rjust(2,"0")
+ add_month if @day == "01"
+ end
+
+ def add_month
+ @month == "12" ? @month = "01" : @month = (month + 1).to_s.rjust(2,"0")
+ @year = (year + 1).to_s.rjust(4,"0") if @month == "01"
+ end
+ end
+
+ class Note
+ attr_accessor :file_name, :body, :status, :date
+ attr_reader :header, :tags
+
+ def initialize(header, *tags, file_name)
+ @header = header
+ @tags = tags.flatten
+ @file_name = file_name
+ @body = ""
+ @status = :topostpone
+ end
+
+ def clone_with_different_date(date)
+ note = self.clone
+ note.date = date
+ note
+ end
+ end
+
+ class Agenda
+
+ def initialize(date)
+ @date = date
+ end
+
+ def days_between_dates(note)
+ difference_year = @date.year - note.date.year
+ difference_month = @date.month - note.date.month
+ difference_day = @date.day - note.date.day
+ difference_year * 360 + difference_month * 30 + difference_day
+ end
+ end
+
+ class DailyAgenda < Agenda
+
+ def initialize(date, notes)
+ @date = date
+ @notes = notes
+ daily_notes
+ end
+
+ def daily_notes
+ @daily_notes = []
+ @notes.each { |note| add_daily_note?(note) }
+ end
+
+ def notes
+ @daily_notes
+ end
+
+ def add_daily_note?(note)
+ if note.date.to_s == @date.to_s
+ @daily_notes.push(note)
+ elsif(note.date.period && days_between_dates(note) % note.date.period == 0)
+ @daily_notes.push(note.clone_with_different_date(@date))
+ end
+ end
+ end
+
+ class WeeklyAgenda
+
+ def initialize(date, notes)
+ @date = date
+ @notes = notes
+ weekly_notes
+ end
+
+ def weekly_notes
+ @weekly_notes = []
+ date = @date
+ (0...7).each do
+ @weekly_notes.concat(DailyAgenda.new(date, @notes).notes)
+ date.add_day
+ end
+ @filtered_notes = @weekly_notes
+ end
+
+ def notes
+ @weekly_notes
+ end
+
+ def where(filter_hash, filter_1 = {}, filter_2 = {})
+ filter_hash.merge!(filter_1).merge!(filter_2)
+ @filtered_notes.delete_if do |note|
+ check_tag(filter_hash.fetch(:tag, nil), note) ||
+ check_text(filter_hash.fetch(:text, //), note) ||
+ check_status(filter_hash.fetch(:status, nil))
+ end
+ FilteredAgenda.new(@filtered_notes)
+ end
+
+ def check_tag(tag, note)
+ tag == nil ? false : !note.tags.include?(tag)
+ end
+
+ def check_status(status)
+ status == nil ? false : !(status == :topostpone || status == :postponed)
+ end
+
+ def check_text(text, note)
+ !((note.header + note.body) =~ text)
+ end
+ end
+
+
+ class EvaluateNote
+
+ def initialize(header, *tags, file_name)
+ @file_name = file_name
+ @note = Note.new(header, tags, file_name)
+ @notes = []
+ end
+
+ def body(body)
+ @note.body = body
+ end
+
+ def status(status)
+ @note.status = status
+ end
+
+ def scheduled(date)
+ @note.date = Date.new(date.split("+")[0])
+ calculate_period(date.split("+")[1]) if date.split("+")[1]
+ end
+
+ def calculate_period(period_string)
+ period = period_string.slice!(-1)
+ @note.date.period = period_string.to_i if period == "d"
+ @note.date.period = period_string.to_i * 7 if period == "w"
+ @note.date.period = period_string.to_i * 30 if period == "m"
+ end
+
+ def note(header, *tags, &block)
+ @notes.push(@note)
+ @note = Note.new(header, tags, @file_name)
+ self.instance_eval &block
+ end
+
+ def notes
+ @notes.push(@note)
+ end
+ end
+
+ class FilteredAgenda
+ def initialize(notes)
+ @notes = notes
+ end
+
+ def notes
+ @notes
+ end
+ end
+
+ class File
+ attr_accessor :name
+ def initialize(name)
+ @name = name
+ @notes = []
+ end
+
+ def notes
+ @notes
+ end
+
+ def note(header, *tags, &block)
+ object = EvaluateNote.new(header, tags, @name)
+ object.instance_eval &block if block_given?
+ @notes.concat(object.notes)
+ end
+
+ def daily_agenda(date)
+ DailyAgenda.new(date,@notes)
+ end
+
+ def weekly_agenda(date)
+ WeeklyAgenda.new(date,@notes)
+ end
+ end
+end