Replaced KeySelection class with a more logical

Finder class.
This commit is contained in:
2010-08-24 13:17:18 +03:00
parent f98472c0ae
commit be464ec298
7 changed files with 447 additions and 214 deletions

View File

@@ -11,8 +11,9 @@ require 'digest/sha1'
require 'redistat/database'
require 'redistat/date'
require 'redistat/event'
require 'redistat/finder'
require 'redistat/finder/date_set'
require 'redistat/key'
require 'redistat/key_selection'
require 'redistat/label'
require 'redistat/model'
require 'redistat/scope'

90
lib/redistat/finder.rb Normal file
View File

@@ -0,0 +1,90 @@
module Redistat
class Finder
attr_reader :options
def initialize(options = {})
@options = options
end
def builder
end
def valid_options?
return true if !@options[:scope].blank? && !@options[:label].blank? && !@options[:from].blank? && !@options[:till].blank?
false
end
class << self
def scope(scope)
new.scope(scope)
end
def label(label)
new.label(label)
end
def dates(from, till)
new.dates(from, till)
end
alias :date :dates
def from(date)
new.from(date)
end
def till(date)
new.till(date)
end
alias :untill :till
def depth(unit)
new.depth(unit)
end
def interval(unit)
new.interval(unit)
end
end
def scope(scope)
@options[:scope] = scope
self
end
def label(label)
@options[:label] = label
self
end
def dates(from, till)
from(from).till(till)
end
alias :date :dates
def from(date)
@options[:from] = date
self
end
def till(date)
@options[:till] = date
self
end
alias :until :till
def depth(unit)
@options[:depth] = unit
self
end
def interval(unit)
@options[:interval] = unit
self
end
end
end

View File

@@ -0,0 +1,95 @@
module Redistat
class Finder
class DateSet < Array
def initialize(start_date = nil, end_date = nil, depth = nil, interval = false)
if !start_date.nil? && !end_date.nil?
find_date_sets(start_date, end_date, depth, interval)
end
end
def find_date_sets(start_date, end_date, depth = nil, interval = false)
start_date = start_date.to_time if start_date.is_a?(::Date)
end_date = end_date.to_time if end_date.is_a?(::Date)
if !interval
find_date_sets_by_magic(start_date, end_date, depth)
else
find_date_sets_by_interval(start_date, end_date, depth)
end
end
private
def find_date_sets_by_magic(start_date, end_date, depth = nil)
depth ||= :hour
depths = Date::DEPTHS[Date::DEPTHS.index(:year), Date::DEPTHS.index(depth)+1].reverse
depths.each_with_index do |d, i|
sets = [find_start_keys_for(d, start_date, end_date, (i == 0))]
sets << find_end_keys_for(d, start_date, end_date, (i == 0))
sets.each do |set|
self << set if set != { :add => [], :sub => [] }
end
end
self
end
def find_date_sets_by_interval(start_date, end_date, depth, inclusive = true)
depth ||= :hour
self << { :add => start_date.map_beginning_of_each(depth, :include_start => inclusive, :include_end => inclusive).until(end_date) { |t| t.to_rs.to_s(depth) }, :sub => [] }
end
def find_start_keys_for(unit, start_date, end_date, lowest_depth = false)
return find_start_year_for(start_date, end_date, lowest_depth) if unit == :year
index = Date::DEPTHS.index(unit)
nunit = Date::DEPTHS[(index > 0) ? index-1 : index]
if start_date < start_date.round(nunit) || start_date.next(nunit).beginning_of(nunit) > end_date.beginning_of(nunit)
add = []
start_date.beginning_of_each(unit, :include_start => lowest_depth).until(start_date.end_of(nunit)) do |t|
add << t.to_rs.to_s(unit) if t < end_date.beginning_of(unit)
end
{ :add => add, :sub => [] }
else
{ :add => [start_date.beginning_of(nunit).to_rs.to_s(nunit)],
:sub => start_date.beginning_of(nunit).map_beginning_of_each(unit, :include_start => true, :include_end => !lowest_depth).until(start_date) { |t| t.to_rs.to_s(unit) } }
end
end
def find_end_keys_for(unit, start_date, end_date, lowest_depth = false)
return find_end_year_for(start_date, end_date, lowest_depth) if unit == :year
index = Date::DEPTHS.index(unit)
nunit = Date::DEPTHS[(index > 0) ? index-1 : index]
has_nunit = end_date.prev(nunit).beginning_of(nunit) >= start_date.beginning_of(nunit)
nearest_nunit = end_date.round(nunit)
if end_date >= nearest_nunit && has_nunit
add = []
end_date.beginning_of(nunit).beginning_of_each(unit, :include_start => true, :include_end => lowest_depth).until(end_date) do |t|
add << t.to_rs.to_s(unit) if t > start_date.beginning_of(unit)
end
{ :add => add, :sub => [] }
elsif has_nunit
{ :add => [end_date.beginning_of(nunit).to_rs.to_s(nunit)],
:sub => end_date.map_beginning_of_each(unit, :include_start => !lowest_depth).until(end_date.end_of(nunit)) { |t| t.to_rs.to_s(unit) } }
else
{ :add => [], :sub => [] }
end
end
def find_start_year_for(start_date, end_date, lowest_depth = false)
if start_date.years_since(1).beginning_of_year < end_date.beginning_of_year
{ :add => start_date.map_beginning_of_each_year(:include_end => lowest_depth).until(end_date) { |t| t.to_rs.to_s(:year) }, :sub => [] }
else
{ :add => [], :sub => [] }
end
end
def find_end_year_for(start_date, end_date, lowest_depth = false)
if lowest_depth
{ :add => [end_date.beginning_of_year.to_rs.to_s(:year)], :sub => [] }
else
{ :add => [], :sub => [] }
end
end
end
end
end

View File

@@ -16,6 +16,13 @@ module Redistat
{ :depth => :day }
end
def prefix
key = "#{@scope}"
key << "/" + ((@options[:label_hash].nil? || @options[:label_hash] == true) ? @label.hash : @label.name) if !label.nil?
key << ":"
key
end
def date=(input)
@date = (input.instance_of?(Redistat::Date)) ? input : Date.new(input) # Redistat::Date, not ::Date
end
@@ -38,9 +45,9 @@ module Redistat
def to_s(depth = nil)
depth ||= @options[:depth]
key = "#{@scope}"
key << "/" + ((@options[:label_hash].nil? || @options[:label_hash] == true) ? @label.hash : @label.name) if !label.nil?
key << ":#{@date.to_s(depth)}"
key = self.prefix
key << @date.to_s(depth)
key
end
end

View File

@@ -1,93 +0,0 @@
module Redistat
class KeySelection
attr_reader :sets
def initialize(start_date, end_date, depth = nil, interval = false)
@sets = self.class.find_date_sets(start_date, end_date, depth, interval)
end
def self.find_date_sets(start_date, end_date, depth = nil, interval = false)
start_date = start_date.to_time if start_date.is_a?(::Date)
end_date = end_date.to_time if end_date.is_a?(::Date)
if !interval
find_date_sets_by_magic(start_date, end_date, depth)
else
find_date_sets_by_interval(start_date, end_date, depth)
end
end
private
def self.find_date_sets_by_magic(start_date, end_date, depth = nil)
depth ||= :hour
depths = Date::DEPTHS[Date::DEPTHS.index(:year), Date::DEPTHS.index(depth)+1].reverse
sets = []
depths.each_with_index do |d, i|
sets << find_start_keys_for(d, start_date, end_date, (i == 0))
sets << find_end_keys_for(d, start_date, end_date, (i == 0))
end
sets
end
def self.find_date_sets_by_interval(start_date, end_date, depth)
depth ||= :hour
[{ :add => start_date.map_beginning_of_each(depth, :include_start => true, :include_end => true).until(end_date) { |t| t.to_rs.to_s(depth) },
:sub => [] }]
end
def self.find_start_keys_for(unit, start_date, end_date, lowest_depth = false)
return find_start_year_for(start_date, end_date, lowest_depth) if unit == :year
index = Date::DEPTHS.index(unit)
nunit = Date::DEPTHS[(index > 0) ? index-1 : index]
if start_date < start_date.round(nunit) || start_date.next(nunit).beginning_of(nunit) > end_date.beginning_of(nunit)
add = []
start_date.beginning_of_each(unit, :include_start => lowest_depth).until(start_date.end_of(nunit)) do |t|
add << t.to_rs.to_s(unit) if t < end_date.beginning_of(unit)
end
{ :add => add, :sub => [] }
else
{ :add => [start_date.beginning_of(nunit).to_rs.to_s(nunit)],
:sub => start_date.beginning_of(nunit).map_beginning_of_each(unit, :include_start => true, :include_end => !lowest_depth).until(start_date) { |t| t.to_rs.to_s(unit) } }
end
end
def self.find_end_keys_for(unit, start_date, end_date, lowest_depth = false)
return find_end_year_for(start_date, end_date, lowest_depth) if unit == :year
index = Date::DEPTHS.index(unit)
nunit = Date::DEPTHS[(index > 0) ? index-1 : index]
has_nunit = end_date.prev(nunit).beginning_of(nunit) >= start_date.beginning_of(nunit)
nearest_nunit = end_date.round(nunit)
if end_date >= nearest_nunit
add = []
end_date.beginning_of(nunit).beginning_of_each(unit, :include_start => true, :include_end => lowest_depth).until(end_date) do |t|
add << t.to_rs.to_s(unit) if t > start_date.beginning_of(unit)
end
{ :add => add, :sub => [] }
elsif has_nunit
{ :add => [end_date.beginning_of(nunit).to_rs.to_s(nunit)],
:sub => end_date.map_beginning_of_each(unit, :include_start => !lowest_depth).until(end_date.end_of(nunit)) { |t| t.to_rs.to_s(unit) } }
else
{ :add => [], :sub => [] }
end
end
def self.find_start_year_for(start_date, end_date, lowest_depth = false)
if start_date.years_since(1).beginning_of_year < end_date.beginning_of_year
{ :add => start_date.map_beginning_of_each_year(:include_end => lowest_depth).until(end_date) { |t| t.to_rs.to_s(:year) }, :sub => [] }
else
{ :add => [], :sub => [] }
end
end
def self.find_end_year_for(start_date, end_date, lowest_depth = false)
if lowest_depth
{ :add => [end_date.beginning_of_year.to_rs.to_s(:year)], :sub => [] }
else
{ :add => [], :sub => [] }
end
end
end
end