boundy 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/lib/boundy.rb +19 -0
  3. data/lib/boundy/bound.rb +65 -0
  4. data/lib/boundy/bound/comparator.rb +67 -0
  5. data/lib/boundy/bound/constrainer.rb +29 -0
  6. data/lib/boundy/bound/infinite.rb +46 -0
  7. data/lib/boundy/bound/infinite/above.rb +12 -0
  8. data/lib/boundy/bound/infinite/below.rb +13 -0
  9. data/lib/boundy/comparator.rb +19 -0
  10. data/lib/boundy/comparators.rb +28 -0
  11. data/lib/boundy/domain.rb +115 -0
  12. data/lib/boundy/domain/anterior.rb +45 -0
  13. data/lib/boundy/domain/builder.rb +31 -0
  14. data/lib/boundy/domain/comparator.rb +26 -0
  15. data/lib/boundy/domain/constrainer.rb +21 -0
  16. data/lib/boundy/domain/finite.rb +64 -0
  17. data/lib/boundy/domain/posterior.rb +43 -0
  18. data/lib/boundy/formatter.rb +9 -0
  19. data/lib/boundy/formatter/sql.rb +26 -0
  20. data/lib/boundy/formatter/sql/domain.rb +20 -0
  21. data/lib/boundy/formatter/sql/domain/plugin.rb +22 -0
  22. data/lib/boundy/formatter/sql/factory.rb +14 -0
  23. data/lib/boundy/formatter/sql/plugin.rb +38 -0
  24. data/lib/boundy/formatters/bound.rb +16 -0
  25. data/lib/boundy/formatters/domain.rb +12 -0
  26. data/lib/boundy/formatters/fixnum.rb +20 -0
  27. data/lib/boundy/formatters/sql/bound.rb +22 -0
  28. data/lib/boundy/formatters/sql/domain.rb +28 -0
  29. data/lib/boundy/formatters/sql/domain/anterior.rb +23 -0
  30. data/lib/boundy/formatters/sql/domain/finite.rb +24 -0
  31. data/lib/boundy/formatters/sql/domain/posterior.rb +23 -0
  32. data/lib/boundy/formatters/time.rb +42 -0
  33. data/lib/boundy/range/comparator.rb +38 -0
  34. data/lib/boundy/range/constrainer.rb +17 -0
  35. data/lib/boundy/time/comparator.rb +37 -0
  36. data/test/integration/boundy_test.rb +37 -0
  37. data/test/integration/domain_test.rb +18 -0
  38. data/test/integration/formatter/sql_test.rb +21 -0
  39. data/test/integration/test_helper.rb +14 -0
  40. data/test/unit/boundy/bound/comparator_test.rb +37 -0
  41. data/test/unit/boundy/bound/constrainer_test.rb +123 -0
  42. data/test/unit/boundy/bound/infinite/above_test.rb +36 -0
  43. data/test/unit/boundy/bound/infinite/below_test.rb +36 -0
  44. data/test/unit/boundy/bound/infinite_test.rb +0 -0
  45. data/test/unit/boundy/bound_test.rb +86 -0
  46. data/test/unit/boundy/comparator_test.rb +0 -0
  47. data/test/unit/boundy/domain/anterior_test.rb +103 -0
  48. data/test/unit/boundy/domain/comparator_test.rb +75 -0
  49. data/test/unit/boundy/domain/constrainer_test.rb +11 -0
  50. data/test/unit/boundy/domain/posterior_test.rb +75 -0
  51. data/test/unit/boundy/domain_test.rb +50 -0
  52. data/test/unit/boundy/formatter/sql/domain/plugin_test.rb +16 -0
  53. data/test/unit/boundy/formatter/sql/plugin_test.rb +50 -0
  54. data/test/unit/boundy/formatter/sql_test.rb +26 -0
  55. data/test/unit/boundy/formatters/bound_test.rb +43 -0
  56. data/test/unit/boundy/formatters/domain_test.rb +12 -0
  57. data/test/unit/boundy/formatters/sql/domain/anterior_test.rb +29 -0
  58. data/test/unit/boundy/formatters/sql/domain/finite_test.rb +35 -0
  59. data/test/unit/boundy/formatters/sql/domain/posterior_test.rb +30 -0
  60. data/test/unit/boundy/formatters/time_test.rb +27 -0
  61. data/test/unit/boundy/range/comparator_test.rb +44 -0
  62. data/test/unit/boundy/range/constrainer_test.rb +11 -0
  63. data/test/unit/boundy/time/comparator_test.rb +40 -0
  64. data/test/unit/test_helper.rb +14 -0
  65. 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
@@ -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,12 @@
1
+ module Boundy
2
+ class Bound
3
+ class Infinite
4
+ class Above < Infinite
5
+ include Comparable
6
+ def <=>(other)
7
+ 1
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Boundy
2
+ class Bound
3
+ class Infinite
4
+ class Below < Infinite
5
+ include Comparable
6
+ def <=>(other)
7
+ -1
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -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