Мартина обнови решението на 21.12.2015 16:59 (преди над 9 години)
+# Defines helper functions to detect if a date meets a periodicity condition
+module DateArithmetic
+ def detect_periodicity_type(periodicity)
+ case periodicity
+ when /^.w$/ then return :week
+ when /^.m$/ then return :month
+ when /^.y$/ then return :year
+ when /^.d$/ then return :day
+ end
+ end
+
+ def check_periodicity(date, agenda, option)
+ return false if agenda < date
+ case detect_periodicity_type(option)
+ when :year then return (date - agenda) % (option[0].to_i * 360) == 0
+ when :month then return (date - agenda) % (option[0].to_i * 30) == 0
+ when :week then return (date - agenda) % (option[0].to_i * 7) == 0
+ when :day then return (date - agenda) % option[0].to_i == 0
+ end
+ end
+end
+
+# Defines a lazy 'ToDo list'
+module LazyMode
+ def self.create_file(file_name, &block)
+ file = LazyMode::File.new(file_name)
+ file.instance_eval(&block) if block_given?
+ file
+ end
+
+
+ class DateHelper
+ def self.pad_date_initialize(index, date)
+ if index == 0
+ pad_date(:year, date.first)
+ else
+ pad_date(:not_year, date[index])
+ end
+ end
+
+ def self.pad_date(type, date_element)
+ type == :year ? pad_size = 4 : pad_size = 2
+ date_element.prepend('0' * (pad_size - date_element.length))
+ end
+ end
+ # Defines a date in the form 'yyyy-mm-dd'
+ class Date
+ attr_reader :option
+
+ def initialize(date)
+ @date = date.split('-')
+ @date.each_with_index do |_, index|
+ DateHelper.pad_date_initialize(index, @date)
+ end
+ end
+
+
+ def ==(other)
+ year == other.year && month == other.month && day == other.day
+ end
+
+ def -(other)
+ # finds the difference between two dates in days
+ (year - other.year) * 360 + (month - other.month) * 30 + day - other.day
+ end
+
+ def <(other)
+ self - other < 0
+ end
+
+ def year
+ @date.first.to_i
+ end
+
+ def month
+ @date[1].to_i
+ end
+
+ def day
+ @date.last.to_i
+ end
+
+ def to_s
+ @date.join('-')
+ end
+
+ end
+
+ # Defines a "ToDo List" note
+ class Note
+ attr_reader :header, :tags, :schedule, :sub_notes
+ attr_accessor :file_name, :date
+
+ def initialize(header, *tags)
+ @header = header
+ @tags = *tags
+ @sub_notes = []
+ @status = :topostpone
+ end
+
+ private
+
+ def add_sub_note(sub_note)
+ @sub_notes << sub_note
+ end
+
+ def note(header, *tags, &block)
+ note = Note.new(header, *tags)
+ note.instance_eval(&block)
+ add_sub_note(note)
+ end
+
+ def method_missing(name, argument = nil)
+ # puts "Inside method_missing, name = #{name}"
+ if [:status, :body].include?(name) && !argument.nil?
+ instance_variable_set("@#{name}", argument)
+ elsif [:status, :body].include?(name) && argument.nil?
+ end
+ instance_variable_get("@#{name}")
+ end
+
+ def scheduled(date)
+ if date.count('+') > 0
+ @schedule = date.split('+')
+ @schedule[0] = Date.new(@schedule.first.strip!)
+ else
+ @schedule = [Date.new(date), nil]
+ end
+ end
+ end
+
+ # Defines a note container
+ class NoteContainer
+ attr_reader :notes
+ def initialize
+ @notes = []
+ end
+
+ def add(note)
+ @notes << note
+ end
+ end
+
+ # Defines a logical file, used for note storage
+ class File
+ include DateArithmetic
+ attr_reader :name, :notes
+
+ def initialize(file_name)
+ @name = file_name
+ @notes = []
+ end
+
+ def daily_agenda(date)
+ container = LazyMode::NoteContainer.new
+ agenda(date).each { |n| container.add n }
+ container
+ end
+
+ def agenda(date)
+ agenda_notes = []
+ @notes.each do |note|
+ agenda_helper(date, note, agenda_notes)
+ end
+ agenda_notes
+ end
+
+ def agenda_helper(date, note, agenda_notes)
+ if (note.schedule.last.nil? && (date == note.schedule.first)) ||\
+ (!note.schedule.last.nil? && \
+ check_periodicity(note.schedule.first, date, note.schedule.last))
+ note.date = date
+ agenda_notes << note
+ end
+ end
+
+ private
+
+ def add_note(note)
+ @notes << note
+ return if note.sub_notes.length == 0
+ note.sub_notes.each { |sub_note| @notes << sub_note } # add recursive note
+ end
+
+ def note(header, *tags, &block)
+ note = Note.new(header, *tags)
+ note.instance_eval(&block)
+ note.file_name = @name
+ add_note(note)
+ end
+ end
+end