Адриана обнови решението на 20.12.2015 15:57 (преди около 9 години)
+class LazyMode
+
+ def self.create_file(name, &block)
+ File.new(name, &block)
+ end
+
+ class File
+ attr_accessor :name, :notes
+
+ def initialize(name)
+ @name = name
+ self.instance_eval( &Proc.new ) if block_given?
+ end
+
+ def note(note_header, *note_tags, &block)
+ @notes = Array.new if @notes == nil
+ @notes.push(Note.new(@name, note_header, *note_tags, &block))
+ end
+
+ def daily_agenda(date)
+ agenda = Agenda.new
+
+ add_to_agenda(agenda, date)
+
+ agenda
+ end
+
+ def weekly_agenda(date)
+ agenda = Agenda.new
+
+ (0..7).each { |day|
+ new_date = date
+ new_date = new_date.add_days(day)
+ add_to_agenda(agenda, new_date)
+ }
+ agenda
+ end
+
+ def add_to_agenda(agenda, date)
+ @notes.each{ |note|
+ check(note, date, agenda)
+ }
+ end
+
+ def check(note, date, agenda)
+ if note.eligible?(date)
+ agenda.add_note(note, date)
+ end
+ check_inner_tasks(note, date, agenda)
+ end
+
+ def check_inner_tasks(note, date, agenda)
+ note.inner_tasks.each { |inner_task|
+ check_inner_task(inner_task, date, agenda)
+ }
+ end
+
+ def check_inner_task(inner_task, date, agenda)
+ if inner_task.eligible?(date)
+ agenda.add_note(inner_task, date)
+ end
+ end
+
+ end
+
+ module DateHelper
+ def subtract_days(days)
+ new_date = Date.new(self.to_s)
+
+ while days > 30
+ days = days - 30
+ new_date.month = new_date.month - 1
+ end
+
+ new_date.day = new_date.day - days
+
+ new_date
+ end
+
+ def subtract_weeks(weeks)
+ days = 7 * weeks
+ subtract_days(days)
+ end
+
+ def subtract_months(months)
+ new_date = Date.new(self.to_s)
+
+ while(new_date.month - months < 0)
+ new_date.year = new_date.year - 1
+ months = months - 12
+ end
+
+ new_date.month = new_date.month - months
+
+ new_date
+ end
+
+ def add_days(days)
+ new_date = Date.new(self.to_s)
+ if new_date.day + days > 30
+ new_date.month = new_date.month + 1
+ new_date.day = new_date.day + days - 30
+ else
+ new_date.day = new_date.day + days
+ end
+ new_date
+ end
+
+ end
+
+ class Date
+ include DateHelper
+ attr_accessor :year, :month, :day
+
+ def initialize(date)
+ @year, @month, @day = date.split('-').map(&:to_i)
+ raise "Invalid date" if @month > 12 || @day > 30
+ end
+
+ def to_s
+ year, month, day = @year.to_s, @month.to_s, @day.to_s
+
+ year = add_missing_zeroes(year, 4)
+ month = add_missing_zeroes(month, 2)
+ day = add_missing_zeroes(day, 2)
+
+ "#{year}-#{month}-#{day}"
+ end
+
+ def add_missing_zeroes(string, length)
+
+ while(string.length < length)
+ string = "0" << string
+ end
+
+ string
+ end
+
+ def ==(other)
+ @year == other.year && @month == other.month && @day == other.day
+ end
+
+ def <=>(other)
+ if @year < other.year
+ -1
+ elsif @year > other.year
+ 1
+ else
+ compare_months(other)
+ end
+ end
+
+ def compare_months(other)
+ if @month < other.month
+ -1
+ elsif @month > other.month
+ 1
+ else
+ compare_days(other)
+ end
+ end
+
+ def compare_days(other)
+ if @day < other.day
+ -1
+ elsif @day > other.day
+ 1
+ else
+ 0
+ end
+ end
+
+ end
+
+ module NoteHelper
+ def calculate_days(date)
+ new_date = date
+ new_date = new_date.subtract_days(@repetition)
+ new_date == @scheduled
+ end
+
+ def calculate_weeks(date)
+ new_date = date
+ new_date = new_date.subtract_weeks(@repetition)
+ new_date == @scheduled
+ end
+
+ def calculate_months(date)
+ new_date = date
+ new_date = new_date.subtract_months(@repetition)
+ new_date == @scheduled
+ end
+
+ def eligible_for_months_and_weeks?(date)
+ if @interval == 'w'
+ return calculate_weeks(date)
+ else
+ return eligible_for_months?(date)
+ end
+ end
+
+ def eligible_for_months?(date)
+ if @interval == 'm'
+ return calculate_months(date)
+ end
+ end
+
+ end
+
+ class Note
+ include NoteHelper
+
+ STATUSES = [:topostpone, :postponed]
+
+ attr_accessor :header, :file_name, :body, :status, :tags, :scheduled,
+ :repetition, :inner_tasks, :date
+
+ def initialize(file_name, header, *tags, &block)
+ @file_name = file_name
+ @header = header
+
+ #defaults
+ @tags = Array.new.push(*tags)
+ @status = :topostpone
+ @body = ""
+
+ self.instance_eval( &Proc.new ) if block_given?
+ end
+
+ def scheduled(*date)
+ if date.size == 0
+ @scheduled
+ else
+ assign_scheduled(date.first)
+ end
+ end
+
+ def assign_scheduled(date)
+ date, repetition = date.split(' ')
+ @scheduled = Date.new(date)
+
+ if repetition != nil
+ @interval = repetition.split('').last
+ repetition[0], repetition[-1] = '', ''
+ @repetition = repetition.to_i
+ end
+ end
+
+ def status(*note_status)
+ if note_status.size == 0
+ @status
+ elsif(STATUSES.include? note_status.first)
+ @status = note_status.first
+ end
+ end
+
+ def body(*note_body)
+ if note_body.size == 0
+ @body
+ else
+ @body = note_body.first
+ end
+ end
+
+ def note(note_header, *note_tags, &block)
+ @inner_tasks = Array.new if @inner_tasks == nil
+ @inner_tasks.push(Note.new(@file_name, note_header, *note_tags, &block))
+ end
+
+ def eligible?(date)
+
+ return true if @scheduled == date
+
+ if @interval == 'd'
+ return calculate_days(date)
+ else
+ return eligible_for_months_and_weeks?(date)
+ end
+ false
+ end
+ end
+
+ module AgendaHelper
+
+ def check_tag_if_present(note, tag)
+ if tag != ""
+ check_tag(note, tag)
+ end
+ end
+
+ def check_tag(note, tag)
+ unless note.tags.include? tag
+ @notes.delete(note)
+ end
+ end
+
+ def check_text_if_present(note, text)
+ if text != ""
+ check_text(note, text)
+ end
+ end
+
+ def check_text(note, text)
+ if (note.header =~ text) == nil && (note.body =~ text) == nil
+ @notes.delete(note)
+ end
+ end
+
+ def check_status_if_present(note, status)
+ if status != ""
+ check_status(note, status)
+ end
+ end
+
+ def check_status(note, status)
+ unless note.status == status
+ @notes.delete(note)
+ end
+ end
+
+ end
+
+ class Agenda
+ include AgendaHelper
+ attr_accessor :notes, :date
+
+ def initialize
+ @notes = Array.new
+ end
+
+ def add_note(note, date)
+ note.date = date
+ @notes.push(note)
+ end
+
+ def where(tag: "", text: "", status: "")
+
+ where_tag(tag)
+ where_text(text)
+ where_status(status)
+
+ self
+ end
+
+ def where_tag(tag)
+ @notes.each{ |note|
+ check_tag_if_present(note, tag)
+ }
+ end
+
+ def where_text(text)
+ @notes.each { |note|
+ check_text_if_present(note, text)
+ }
+ end
+
+ def where_status(status)
+ @notes.each {|note|
+ check_status_if_present(note, status)
+ }
+ end
+
+ end
+
+end