boundy 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/boundy.rb +19 -0
- data/lib/boundy/bound.rb +65 -0
- data/lib/boundy/bound/comparator.rb +67 -0
- data/lib/boundy/bound/constrainer.rb +29 -0
- data/lib/boundy/bound/infinite.rb +46 -0
- data/lib/boundy/bound/infinite/above.rb +12 -0
- data/lib/boundy/bound/infinite/below.rb +13 -0
- data/lib/boundy/comparator.rb +19 -0
- data/lib/boundy/comparators.rb +28 -0
- data/lib/boundy/domain.rb +115 -0
- data/lib/boundy/domain/anterior.rb +45 -0
- data/lib/boundy/domain/builder.rb +31 -0
- data/lib/boundy/domain/comparator.rb +26 -0
- data/lib/boundy/domain/constrainer.rb +21 -0
- data/lib/boundy/domain/finite.rb +64 -0
- data/lib/boundy/domain/posterior.rb +43 -0
- data/lib/boundy/formatter.rb +9 -0
- data/lib/boundy/formatter/sql.rb +26 -0
- data/lib/boundy/formatter/sql/domain.rb +20 -0
- data/lib/boundy/formatter/sql/domain/plugin.rb +22 -0
- data/lib/boundy/formatter/sql/factory.rb +14 -0
- data/lib/boundy/formatter/sql/plugin.rb +38 -0
- data/lib/boundy/formatters/bound.rb +16 -0
- data/lib/boundy/formatters/domain.rb +12 -0
- data/lib/boundy/formatters/fixnum.rb +20 -0
- data/lib/boundy/formatters/sql/bound.rb +22 -0
- data/lib/boundy/formatters/sql/domain.rb +28 -0
- data/lib/boundy/formatters/sql/domain/anterior.rb +23 -0
- data/lib/boundy/formatters/sql/domain/finite.rb +24 -0
- data/lib/boundy/formatters/sql/domain/posterior.rb +23 -0
- data/lib/boundy/formatters/time.rb +42 -0
- data/lib/boundy/range/comparator.rb +38 -0
- data/lib/boundy/range/constrainer.rb +17 -0
- data/lib/boundy/time/comparator.rb +37 -0
- data/test/integration/boundy_test.rb +37 -0
- data/test/integration/domain_test.rb +18 -0
- data/test/integration/formatter/sql_test.rb +21 -0
- data/test/integration/test_helper.rb +14 -0
- data/test/unit/boundy/bound/comparator_test.rb +37 -0
- data/test/unit/boundy/bound/constrainer_test.rb +123 -0
- data/test/unit/boundy/bound/infinite/above_test.rb +36 -0
- data/test/unit/boundy/bound/infinite/below_test.rb +36 -0
- data/test/unit/boundy/bound/infinite_test.rb +0 -0
- data/test/unit/boundy/bound_test.rb +86 -0
- data/test/unit/boundy/comparator_test.rb +0 -0
- data/test/unit/boundy/domain/anterior_test.rb +103 -0
- data/test/unit/boundy/domain/comparator_test.rb +75 -0
- data/test/unit/boundy/domain/constrainer_test.rb +11 -0
- data/test/unit/boundy/domain/posterior_test.rb +75 -0
- data/test/unit/boundy/domain_test.rb +50 -0
- data/test/unit/boundy/formatter/sql/domain/plugin_test.rb +16 -0
- data/test/unit/boundy/formatter/sql/plugin_test.rb +50 -0
- data/test/unit/boundy/formatter/sql_test.rb +26 -0
- data/test/unit/boundy/formatters/bound_test.rb +43 -0
- data/test/unit/boundy/formatters/domain_test.rb +12 -0
- data/test/unit/boundy/formatters/sql/domain/anterior_test.rb +29 -0
- data/test/unit/boundy/formatters/sql/domain/finite_test.rb +35 -0
- data/test/unit/boundy/formatters/sql/domain/posterior_test.rb +30 -0
- data/test/unit/boundy/formatters/time_test.rb +27 -0
- data/test/unit/boundy/range/comparator_test.rb +44 -0
- data/test/unit/boundy/range/constrainer_test.rb +11 -0
- data/test/unit/boundy/time/comparator_test.rb +40 -0
- data/test/unit/test_helper.rb +14 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 55bb89b47f6477f182a1e2f5dc6409a386a3593c
|
4
|
+
data.tar.gz: e54945d291b401d501003dacce33a5696dae01d2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 80d51de835f5509772835a640a17c0c98b8c8d010cfcaf65ab22ebf54b61d1b97f2415898424092365414c01e167124fee92cefe2a824ae8124baee91989b640
|
7
|
+
data.tar.gz: 775bb5bdfaedf3247ab54a4e39ad23a6b94b70a7dcbd45ab1a6f5037a9f4046d76af55d41d3a72c06b94e58a58954e8447bf9e59c2c9371ab5d3180a8f9c6b45
|
data/lib/boundy.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Boundy
|
2
|
+
|
3
|
+
class << self
|
4
|
+
def logger
|
5
|
+
return @logger if @logger
|
6
|
+
|
7
|
+
@logger = Logger.new(STDOUT)
|
8
|
+
@logger.formatter = proc { |severity, datetime, progname, msg|
|
9
|
+
"[#{datetime}, #{severity}] #{msg}\n"
|
10
|
+
}
|
11
|
+
@logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger=(logger)
|
15
|
+
@logger = logger
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/boundy/bound.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'boundy/bound'
|
2
|
+
require 'boundy/bound/infinite'
|
3
|
+
require 'boundy/comparators'
|
4
|
+
|
5
|
+
#require 'manacle/proxy'
|
6
|
+
|
7
|
+
module Boundy
|
8
|
+
class Bound
|
9
|
+
def initialize(datum)
|
10
|
+
if datum.class <= self.class || datum.class < Boundy::Bound::Infinite
|
11
|
+
raise "Datum is a Bound already!"
|
12
|
+
end
|
13
|
+
|
14
|
+
if datum.nil?
|
15
|
+
raise "Datum passed is nil!"
|
16
|
+
end
|
17
|
+
@datum = datum
|
18
|
+
end
|
19
|
+
|
20
|
+
def after?(subject)
|
21
|
+
Comparators.comparator(self, subject).after?
|
22
|
+
end
|
23
|
+
|
24
|
+
def before?(subject)
|
25
|
+
Comparators.comparator(self, subject).before?
|
26
|
+
end
|
27
|
+
|
28
|
+
def within?(subject)
|
29
|
+
Comparators.comparator(self, subject).within?
|
30
|
+
end
|
31
|
+
|
32
|
+
def finite?
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def infinite?
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def inspect
|
41
|
+
"#<#{self.class.name} bounded at #{@datum.inspect}>"
|
42
|
+
end
|
43
|
+
|
44
|
+
def comparator
|
45
|
+
Boundy::Bound::Comparator
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_reader :datum
|
49
|
+
|
50
|
+
include Comparable
|
51
|
+
|
52
|
+
def <=>(other)
|
53
|
+
case other
|
54
|
+
when Boundy::Bound::Infinite::Above
|
55
|
+
(other <=> self) * -1
|
56
|
+
when Boundy::Bound::Infinite::Below
|
57
|
+
(other <=> self) * -1
|
58
|
+
when Boundy::Bound
|
59
|
+
datum <=> other.datum
|
60
|
+
else
|
61
|
+
raise "Can not compare a Bound to a #{other.class}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'boundy/bound'
|
2
|
+
require 'boundy/bound/infinite'
|
3
|
+
|
4
|
+
module Boundy
|
5
|
+
class Bound
|
6
|
+
class Comparator
|
7
|
+
def initialize(a, b)
|
8
|
+
@a = a
|
9
|
+
@b = b
|
10
|
+
end
|
11
|
+
|
12
|
+
Bound = Boundy::Bound
|
13
|
+
|
14
|
+
COMPARISONS = {
|
15
|
+
Bound::Infinite::Above => {
|
16
|
+
Bound::Infinite::Above => :equal,
|
17
|
+
Bound::Infinite::Below => :left,
|
18
|
+
Bound => :left
|
19
|
+
},
|
20
|
+
Bound::Infinite::Below => {
|
21
|
+
Bound::Infinite::Above => :right,
|
22
|
+
Bound::Infinite::Below => :equal,
|
23
|
+
Bound => :right
|
24
|
+
},
|
25
|
+
Bound => {
|
26
|
+
Bound::Infinite::Above => :right,
|
27
|
+
Bound::Infinite::Below => :left
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
def before?
|
32
|
+
compare == :left
|
33
|
+
end
|
34
|
+
|
35
|
+
def after?
|
36
|
+
compare == :right
|
37
|
+
end
|
38
|
+
|
39
|
+
def within?
|
40
|
+
compare == :equal
|
41
|
+
end
|
42
|
+
|
43
|
+
def compare
|
44
|
+
result = nil
|
45
|
+
if COMPARISONS.has_key?(@a.class)
|
46
|
+
part_comp = COMPARISONS[@a.class]
|
47
|
+
if part_comp.has_key?(@b.class)
|
48
|
+
result = part_comp[@b.class]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
map = {
|
53
|
+
-1 => :right,
|
54
|
+
0 => :equal,
|
55
|
+
1 => :left
|
56
|
+
}
|
57
|
+
|
58
|
+
if result.nil?
|
59
|
+
map[@a.datum <=> @b.datum]
|
60
|
+
else
|
61
|
+
result
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'boundy/bound/comparator'
|
2
|
+
|
3
|
+
module Boundy
|
4
|
+
class Bound
|
5
|
+
class Constrainer
|
6
|
+
def initialize(a, b)
|
7
|
+
@a = a
|
8
|
+
@b = b
|
9
|
+
@comparator = Boundy::Bound::Comparator.new(a,b)
|
10
|
+
end
|
11
|
+
|
12
|
+
def max
|
13
|
+
if @comparator.compare == :left
|
14
|
+
@a
|
15
|
+
else
|
16
|
+
@b
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def min
|
21
|
+
if @comparator.compare == :right
|
22
|
+
@a
|
23
|
+
else
|
24
|
+
@b
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Boundy
|
2
|
+
# An Anterior domain date has a beginning, but no end -- hence, is
|
3
|
+
# anterior-domain.
|
4
|
+
class Bound
|
5
|
+
class Infinite
|
6
|
+
def after?(date_range)
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def before?(date_range)
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
def within?(date_range)
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def in_time_zone(tz)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_midnight
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def date
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def finite?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def infinite?
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
def <=>(other)
|
39
|
+
raise ""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'boundy/bound/infinite/above'
|
46
|
+
require 'boundy/bound/infinite/below'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'boundy/comparators'
|
2
|
+
|
3
|
+
module Boundy
|
4
|
+
module Comparator
|
5
|
+
def self.included(base)
|
6
|
+
types = if base.respond_to?(:type)
|
7
|
+
[base.type]
|
8
|
+
elsif base.respond_to?(:types)
|
9
|
+
base.types
|
10
|
+
else
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
|
14
|
+
types.each do |t|
|
15
|
+
Boundy::Comparators.add(t, base)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'punchout'
|
4
|
+
require 'punchout/matcher/class'
|
5
|
+
|
6
|
+
module Boundy
|
7
|
+
module Comparators
|
8
|
+
extend Punchout::Punchable
|
9
|
+
|
10
|
+
|
11
|
+
def self.add(type, comparator)
|
12
|
+
matchable = Punchout::Matcher::Klass.new(type).punches(comparator)
|
13
|
+
puncher.add(matchable)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.comparator(datum,subject)
|
17
|
+
comparator = if subject.respond_to?(:comparator)
|
18
|
+
subject.comparator
|
19
|
+
else
|
20
|
+
puncher.punch(subject.class)
|
21
|
+
end
|
22
|
+
|
23
|
+
comparator.new(datum, subject)
|
24
|
+
rescue
|
25
|
+
raise "I can't compare myself to a #{subject.class}: #{subject.inspect}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'boundy/bound'
|
2
|
+
|
3
|
+
require 'boundy/domain/comparator'
|
4
|
+
require 'boundy/domain/constrainer'
|
5
|
+
require 'boundy/range/constrainer'
|
6
|
+
|
7
|
+
module Boundy
|
8
|
+
module Domain
|
9
|
+
module Plugin
|
10
|
+
def self.included(base)
|
11
|
+
Domain.builder.add(base)
|
12
|
+
base.instance_eval do
|
13
|
+
include InstanceMethods
|
14
|
+
attr_reader :from
|
15
|
+
attr_reader :to
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Builder
|
21
|
+
def initialize
|
22
|
+
@klasses = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(domain_klass)
|
26
|
+
builder = domain_klass.builder
|
27
|
+
|
28
|
+
bound_types = builder[:bounds]
|
29
|
+
builder_method = builder[:builder]
|
30
|
+
|
31
|
+
@klasses[bound_types] = builder_method
|
32
|
+
end
|
33
|
+
|
34
|
+
def build(a,b)
|
35
|
+
builder = @klasses[{from: a.class, to: b.class}]
|
36
|
+
|
37
|
+
if builder.nil?
|
38
|
+
raise "Could not find class for #{a.class} and #{b.class}"
|
39
|
+
end
|
40
|
+
|
41
|
+
builder.call(a,b)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def self.builder
|
47
|
+
@builder ||= Builder.new
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def self.translate(bound)
|
52
|
+
if bound.class <= Boundy::Bound or bound.class < Boundy::Bound::Infinite
|
53
|
+
bound
|
54
|
+
else
|
55
|
+
Boundy::Bound.new(bound)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.new(b,e=nil)
|
60
|
+
if b.class <= Boundy::Domain::Plugin
|
61
|
+
b
|
62
|
+
else
|
63
|
+
b = translate(b)
|
64
|
+
e = translate(e)
|
65
|
+
|
66
|
+
built = builder.build(b,e)
|
67
|
+
unless built.class < Plugin
|
68
|
+
raise
|
69
|
+
end
|
70
|
+
built
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module InstanceMethods
|
75
|
+
|
76
|
+
def within?(subject)
|
77
|
+
@from.within?(subject) || @from.after?(subject) and
|
78
|
+
@to.within?(subject) || @to.before?(subject)
|
79
|
+
end
|
80
|
+
|
81
|
+
def joinable?(subject)
|
82
|
+
strictly_earlier?(subject) || strictly_later?(subject)
|
83
|
+
end
|
84
|
+
|
85
|
+
def constrain_to(subject)
|
86
|
+
constrainer(subject).constrain
|
87
|
+
end
|
88
|
+
|
89
|
+
def constrainer(subject)
|
90
|
+
if subject.class == ::Range
|
91
|
+
Boundy::Range::Constrainer.new(self, subject)
|
92
|
+
elsif subject.class < Boundy::Domain::Plugin
|
93
|
+
Boundy::Domain::Constrainer.new(self, subject)
|
94
|
+
else
|
95
|
+
raise "I can't constrain myself against a #{subject.class}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def comparator
|
100
|
+
Boundy::Domain::Comparator
|
101
|
+
end
|
102
|
+
|
103
|
+
def format(formatter)
|
104
|
+
if from.finite?
|
105
|
+
elsif to.finite?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
require 'boundy/domain/anterior'
|
114
|
+
require 'boundy/domain/finite'
|
115
|
+
require 'boundy/domain/posterior'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'boundy/domain'
|
2
|
+
require 'boundy/bound'
|
3
|
+
require 'boundy/bound/infinite/above'
|
4
|
+
|
5
|
+
module Boundy
|
6
|
+
module Domain
|
7
|
+
# An Anterior domain datum has a beginning, but no end -- hence, is
|
8
|
+
# anterior-domain.
|
9
|
+
class Anterior
|
10
|
+
def self.builder
|
11
|
+
{
|
12
|
+
bounds: {
|
13
|
+
from: Boundy::Bound,
|
14
|
+
to: Boundy::Bound::Infinite::Above
|
15
|
+
},
|
16
|
+
builder: Proc.new {|b,e| self.new(b) }
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
include Domain::Plugin
|
21
|
+
|
22
|
+
def initialize(datum)
|
23
|
+
if datum.nil?
|
24
|
+
raise
|
25
|
+
end
|
26
|
+
|
27
|
+
@from = case datum
|
28
|
+
when Boundy::Bound
|
29
|
+
datum
|
30
|
+
else
|
31
|
+
Boundy::Bound.new(datum)
|
32
|
+
end
|
33
|
+
@to = Boundy::Bound::Infinite::Above.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def cute
|
37
|
+
"[#{@from.datum}, infinity]"
|
38
|
+
end
|
39
|
+
|
40
|
+
def inspect
|
41
|
+
"#<#{self.class.name} bounded below by #{@from.inspect}>"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|