slotter 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -0,0 +1,24 @@
1
+ Given /^I have a time slot collection "([^\"]*)"$/ do |name|
2
+ @time_slot_collections ||= {}
3
+ @time_slot_collections[name] = TimeSlotCollection.new
4
+ end
5
+
6
+ Given /^time slot "([^\"]*)" belongs to collection "([^\"]*)"$/ do |slot, collection|
7
+ @time_slot_collections[collection] << @time_slots[slot]
8
+ end
9
+
10
+ When /^I merge time slot collections "([^\"]*)" and "([^\"]*)"$/ do |a, b|
11
+ @result = @time_slot_collections[a].merge(@time_slot_collections[b])
12
+ end
13
+
14
+ When /^I compress time slot collection "([^\"]*)"$/ do |name|
15
+ @result = @time_slot_collections[name].compress
16
+ end
17
+
18
+ Then /^I should have a new collection of ([0-9]+) time slots$/ do |length|
19
+ @result.time_slots.length.should == length.to_i
20
+ end
21
+
22
+ Then /^show the result$/ do
23
+ puts "The result is: \n#{@result}"
24
+ end
@@ -16,8 +16,8 @@ When /^I split time slot "([^\"]*)" into ([0-9]+) second slots$/ do |name, durat
16
16
  end
17
17
 
18
18
  Then /^I should have a time slot between "([^\"]*)" and "([^\"]*)"$/ do |start, finish|
19
- @result.start.should == Chronic.parse(start)
20
- @result.finish.should == Chronic.parse(finish)
19
+ @result.start.should == Chronic.parse("today " + start)
20
+ @result.finish.should == Chronic.parse("today " + finish)
21
21
  end
22
22
 
23
23
  Then /^I should have an array of ([0-9]+) time slots$/ do |size|
@@ -45,4 +45,12 @@ end
45
45
 
46
46
  Then /^the array should be empty$/ do
47
47
  @result.should be_empty
48
- end
48
+ end
49
+
50
+ Then /^"([^\"]*)" and "([^\"]*)" should be disjoint$/ do |a, b|
51
+ @time_slots[a].disjoint?(@time_slots[b]).should == true
52
+ end
53
+
54
+ Then /^I should not be able to add "([^\"]*)" to "([^\"]*)"$/ do |a, b|
55
+ (@time_slots[a] + @time_slots[b]).should == nil
56
+ end
@@ -8,96 +8,82 @@ Feature: Time slot addition
8
8
  Given I have a time slot "A" between "10:00" and "11:00"
9
9
  And I have a time slot "B" between "10:00" and "11:00"
10
10
  When I add time slot "B" to time slot "A"
11
- Then I should have an array of 1 time slots
12
- Then one should be between "10:00" and "11:00"
11
+ Then I should have a time slot between "10:00" and "11:00"
13
12
 
14
13
  # Case 2
15
14
  Scenario: Add A.start == B.start
16
15
  Given I have a time slot "A" between "10:00" and "11:00"
17
16
  And I have a time slot "B" between "10:00" and "12:00"
18
17
  When I add time slot "B" to time slot "A"
19
- Then I should have an array of 1 time slots
20
- Then one should be between "10:00" and "12:00"
18
+ Then I should have a time slot between "10:00" and "12:00"
21
19
 
22
20
  # Case 3
23
21
  Scenario: Add A.start > B.start and A.finish < B.finish
24
22
  Given I have a time slot "A" between "11:00" and "12:00"
25
23
  And I have a time slot "B" between "10:00" and "13:00"
26
24
  When I add time slot "B" to time slot "A"
27
- Then I should have an array of 1 time slots
28
- Then one should be between "10:00" and "13:00"
25
+ Then I should have a time slot between "10:00" and "13:00"
29
26
 
30
27
  # Case 4
31
28
  Scenario: Add A.finish == B.start
32
29
  Given I have a time slot "A" between "10:00" and "11:00"
33
30
  And I have a time slot "B" between "11:00" and "12:00"
34
31
  When I add time slot "B" to time slot "A"
35
- Then I should have an array of 1 time slots
36
- Then one should be between "10:00" and "12:00"
32
+ Then I should have a time slot between "10:00" and "12:00"
37
33
 
38
34
  # Case 5
39
35
  Scenario: Add A.start == B.finish
40
36
  Given I have a time slot "A" between "11:00" and "12:00"
41
37
  And I have a time slot "B" between "10:00" and "11:00"
42
38
  When I add time slot "B" to time slot "A"
43
- Then I should have an array of 1 time slots
44
- Then one should be between "10:00" and "12:00"
39
+ Then I should have a time slot between "10:00" and "12:00"
45
40
 
46
41
  # Case 6
47
42
  Scenario: Add non-intersecting A.finish < B.start
48
43
  Given I have a time slot "A" between "10:00" and "11:00"
49
44
  And I have a time slot "B" between "12:00" and "13:00"
50
- When I add time slot "B" to time slot "A"
51
- Then I should have an array of 1 time slots
52
- And one should be between "10:00" and "11:00"
53
- And one should be between "12:00" and "13:00"
45
+ Then "A" and "B" should be disjoint
46
+ And I should not be able to add "B" to "A"
54
47
 
55
48
  # Case 7
56
49
  Scenario: Add non-intersecting A.start > B.finish
57
50
  Given I have a time slot "A" between "12:00" and "13:00"
58
51
  And I have a time slot "B" between "10:00" and "11:00"
59
- When I add time slot "B" to time slot "A"
60
- Then I should have an array of 2 time slots
61
- And one should be between "10:00" and "11:00"
62
- And one should be between "12:00" and "13:00"
63
-
52
+ Then "A" and "B" should be disjoint
53
+ And I should not be able to add "B" to "A"
54
+
64
55
  # Case 8
65
56
  Scenario: Add A.start == B.start and A.finish > B.finish
66
57
  Given I have a time slot "A" between "10:00" and "12:00"
67
58
  And I have a time slot "B" between "10:00" and "11:00"
68
59
  When I add time slot "B" to time slot "A"
69
- Then I should have an array of 1 time slots
70
- And one should be between "10:00" and "12:00"
60
+ Then I should have a time slot between "10:00" and "12:00"
71
61
 
72
62
  # Case 9
73
63
  Scenario: Add A.start < B.start and A.finish == B.finish
74
64
  Given I have a time slot "A" between "10:00" and "12:00"
75
65
  And I have a time slot "B" between "11:00" and "12:00"
76
66
  When I add time slot "B" to time slot "A"
77
- Then I should have an array of 1 time slots
78
- And one should be between "10:00" and "12:00"
67
+ Then I should have a time slot between "10:00" and "12:00"
79
68
 
80
69
  # Case 10
81
70
  Scenario: Add A.start < B.start and A.finish > B.finish
82
71
  Given I have a time slot "A" between "10:00" and "13:00"
83
72
  And I have a time slot "B" between "11:00" and "12:00"
84
73
  When I add time slot "B" to time slot "A"
85
- Then I should have an array of 1 time slots
86
- And one should be between "10:00" and "13:00"
74
+ Then I should have a time slot between "10:00" and "13:00"
87
75
 
88
76
  # Case 11
89
77
  Scenario: Add a half intersecting time slot (A.finish < B.finish)
90
78
  Given I have a time slot "A" between "10:00" and "12:00"
91
79
  And I have a time slot "B" between "11:00" and "13:00"
92
80
  When I add time slot "B" to time slot "A"
93
- Then I should have an array of 1 time slots
94
- And one should be between "10:00" and "13:00"
81
+ Then I should have a time slot between "10:00" and "13:00"
95
82
 
96
83
  # Case 12
97
84
  Scenario: Add a half intersecting time slot (A.start > B.start)
98
85
  Given I have a time slot "A" between "11:00" and "13:00"
99
86
  And I have a time slot "B" between "10:00" and "12:00"
100
87
  When I add time slot "B" to time slot "A"
101
- Then I should have an array of 1 time slots
102
- And one should be between "10:00" and "13:00"
88
+ Then I should have a time slot between "10:00" and "13:00"
103
89
 
@@ -0,0 +1,19 @@
1
+ Feature: Time slot collection compress
2
+ In order to compress collections of time slots
3
+ As a developer
4
+ I want to be able to compress a time slot collection through code
5
+
6
+ Scenario: compress time slot collection
7
+ Given I have a time slot collection "X"
8
+ And I have a time slot "A" between "09:00" and "10:00"
9
+ And I have a time slot "B" between "09:00" and "14:00"
10
+ And I have a time slot "C" between "15:00" and "16:00"
11
+ And I have a time slot "D" between "10:00" and "11:00"
12
+ And time slot "A" belongs to collection "X"
13
+ And time slot "B" belongs to collection "X"
14
+ And time slot "C" belongs to collection "X"
15
+ And time slot "B" belongs to collection "X"
16
+ When I compress time slot collection "X"
17
+ Then I should have a new collection of 2 time slots
18
+ And one should be between "09:00" and "14:00"
19
+ And one should be between "15:00" and "16:00"
@@ -0,0 +1,22 @@
1
+ Feature: Time slot collection merge
2
+ In order to merge sets of time slots
3
+ As a developer
4
+ I want to be able to merge sets of time slots through code
5
+
6
+ Scenario: merge a set of time slots with another
7
+ Given I have a time slot collection "X"
8
+ And I have a time slot collection "Y"
9
+ And I have a time slot "A" between "09:00" and "10:00"
10
+ And I have a time slot "B" between "09:00" and "11:00"
11
+ And I have a time slot "C" between "13:00" and "13:30"
12
+ And I have a time slot "D" between "13:30" and "17:00"
13
+ And time slot "A" belongs to collection "X"
14
+ And time slot "B" belongs to collection "Y"
15
+ And time slot "C" belongs to collection "Y"
16
+ And time slot "D" belongs to collection "X"
17
+ When I merge time slot collections "X" and "Y"
18
+ Then I should have a new collection of 2 time slots
19
+ And one should be between "09:00" and "11:00"
20
+ And one should be between "13:00" and "17:00"
21
+
22
+
@@ -1,2 +1,3 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
- require 'slotter/time_slot'
2
+ require 'slotter/time_slot'
3
+ require 'slotter/time_slot_collection'
@@ -13,9 +13,48 @@ class TimeSlot
13
13
  (self.finish - self.start)
14
14
  end
15
15
 
16
+ # Returns true if this TimeSlot intersects with <i>other_slot</i> otherwise
17
+ # false.
18
+ def intersects_with?(other_slot)
19
+ !disjoint?(other_slot)
20
+ end
21
+
22
+ # Returns true if this TimeSlot does not intersect with <i>other_slot</i>
23
+ # otherwise false.
24
+ def disjoint?(other_slot)
25
+ (self.start > other_slot.finish) or
26
+ (self.finish < other_slot.start)
27
+ end
28
+
29
+ # Returns true if this TimeSlot contains the <i>other_slot</i> otherwise
30
+ # false.
31
+ def contains?(other_slot)
32
+ (self.contains_start_of?(other_slot) and
33
+ self.contains_finish_of?(other_slot))
34
+ end
35
+
36
+ # Returns true if this TimeSlot is within the <i>other_slot</i> otherwise
37
+ # false.
38
+ def within?(other_slot)
39
+ other_slot.contains?(self)
40
+ end
41
+
42
+ # Returns true if this TimeSlot contains the start of <i>other_slot</i>
43
+ # otherwise false.
44
+ def contains_start_of?(other_slot)
45
+ (self.start < other_slot.start and self.finish > other_slot.start)
46
+ end
47
+
48
+ # Returns true if this TimeSlot contains the finish of <i>other_slot</i>
49
+ # otherwise false.
50
+ def contains_finish_of?(other_slot)
51
+ (self.start < other_slot.finish and self.finish > other_slot.finish)
52
+ end
53
+
16
54
  # Subtraction---Returns a set of new TimeSlot(s) that are the result of
17
55
  # removing the other_slot from this slot.
18
56
  def -(other_slot)
57
+ return self unless other_slot
19
58
  # Case 1, Case 2 or Case 3
20
59
  if (self.start == other_slot.start and self.finish == other_slot.finish) or
21
60
  (self.start == other_slot.start and self.finish < other_slot.finish) or
@@ -50,43 +89,45 @@ class TimeSlot
50
89
  end
51
90
 
52
91
  # Concatenation---Returns a set of new TimeSlot(s) that are the result of
53
- # concatenating the other_slot to this slot.
92
+ # concatenating the other_slot to this slot. Returns nil if the slots are
93
+ # disjoint.
54
94
  def +(other_slot)
95
+ return self unless other_slot
55
96
  # Case 1
56
97
  if self.start == other_slot.start and self.finish == other_slot.finish
57
- return [self.clone]
98
+ return self.clone
58
99
  end
59
100
  # Case 2 or Case 3
60
101
  if (self.start == other_slot.start and self.finish < other_slot.finish) or
61
102
  (self.start > other_slot.start and self.finish < other_slot.finish)
62
- return [other_slot.clone]
103
+ return other_slot.clone
63
104
  end
64
105
  # Case 4
65
106
  if self.finish == other_slot.start
66
- return [TimeSlot.new(self.start, other_slot.finish)]
107
+ return TimeSlot.new(self.start, other_slot.finish)
67
108
  end
68
109
  # Case 5
69
110
  if self.start == other_slot.finish
70
- return [TimeSlot.new(other_slot.start, self.finish)]
111
+ return TimeSlot.new(other_slot.start, self.finish)
71
112
  end
72
- # Case 6 or Case 7
113
+ # Case 6 or Case 7 (Disjoint)
73
114
  if (self.finish < other_slot.start) or
74
115
  (self.start > other_slot.finish)
75
- return [self.clone, other_slot.clone].sort!
116
+ return nil
76
117
  end
77
118
  # Case 8, Case 9 or Case 10
78
119
  if (self.start == other_slot.start and self.finish > other_slot.finish) or
79
120
  (self.start < other_slot.start and self.finish == other_slot.finish) or
80
121
  (self.start < other_slot.start and self.finish > other_slot.finish)
81
- return [self.clone]
122
+ return self.clone
82
123
  end
83
124
  # Case 11
84
125
  if self.start < other_slot.start and self.finish < other_slot.finish and self.finish > other_slot.start
85
- return [TimeSlot.new(self.start, other_slot.finish)]
126
+ return TimeSlot.new(self.start, other_slot.finish)
86
127
  end
87
128
  # Case 12
88
129
  if self.start > other_slot.start and self.finish > other_slot.finish and self.start < other_slot.finish
89
- return [TimeSlot.new(other_slot.start, self.finish)]
130
+ return TimeSlot.new(other_slot.start, self.finish)
90
131
  end
91
132
  end
92
133
 
@@ -0,0 +1,74 @@
1
+ # A TimeSlotCollection object holds a collection of TimeSlot objects
2
+ class TimeSlotCollection
3
+ attr_reader :time_slots
4
+
5
+ # Returns a new collection of time slots where the default is empty.
6
+ def initialize(time_slots = [])
7
+ @time_slots = Array.new(time_slots)
8
+ end
9
+
10
+ # Append---Pushes <i>slot</i> to the end of the internal collection of
11
+ # <i>time_slots</i> if <i>slot</i> is not already a part of it. This
12
+ # expression returns <i>self</i>, so several appends may be chained together.
13
+ def <<(slot)
14
+ @time_slots << slot unless @time_slots.include?(slot)
15
+ return self
16
+ end
17
+
18
+ # Returns a new collection that contains all slots from <i>self</i> and
19
+ # <i>other_collection</i>.
20
+ def union(other_collection)
21
+ result = self.clone
22
+ for slot in other_collection.time_slots
23
+ result << slot
24
+ end
25
+ return result
26
+ end
27
+
28
+ # Returns a copy of <i>self</i> where all intersecting slots have been
29
+ # joined.
30
+ #
31
+ # x = [09:00 to 13:00, 12:00 to 14:00]
32
+ #
33
+ # x.compress #=> [09:00 to 14:00]
34
+ #
35
+ def compress
36
+ result = TimeSlotCollection.new
37
+ for slot_a in @time_slots
38
+ current_slot = slot_a
39
+ for slot_b in @time_slots
40
+ current_slot += slot_b unless current_slot.disjoint?(slot_b)
41
+ end
42
+ result << current_slot
43
+ end
44
+ return result
45
+ end
46
+
47
+ # Joins all intersecting slots in time_slots. Returns nil if no changes
48
+ # where made.
49
+ def compress!
50
+ result = self.compress.time_slots
51
+ (result == @time_slots)? nil : self
52
+ end
53
+
54
+ # Creates a new collection that contains the compressed union of
55
+ # <i>self</i>.time_slots and <i>other_collection</i>.time_slots.
56
+ def merge(other_collection)
57
+ self.union(other_collection).compress
58
+ end
59
+
60
+ # Calls <i>block</i> once for each element in <i>self</i>.time_slots, passing
61
+ # that element as a parameter.
62
+ def each(&block)
63
+ for slot in time_slots
64
+ yield(slot)
65
+ end
66
+ end
67
+
68
+ alias :+ :merge
69
+
70
+ # Returns <i>self</i>.time_slots.to_s
71
+ def to_s
72
+ "#{@time_slots}"
73
+ end
74
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{slotter}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bjarki Gudlaugsson"]
12
- s.date = %q{2009-11-01}
12
+ s.date = %q{2009-11-03}
13
13
  s.description = %q{the gem allows you to perform operations like addition, subtraction and splitting on time slots}
14
14
  s.email = %q{bjarkigud@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -25,14 +25,18 @@ Gem::Specification.new do |s|
25
25
  "VERSION",
26
26
  "features/case_subtraction.txt",
27
27
  "features/cases_addition.txt",
28
+ "features/step_definitions/time_slot_collection_definitions.rb",
28
29
  "features/step_definitions/time_slot_definitions.rb",
29
30
  "features/support/env.rb",
30
31
  "features/time_slot_addition.feature",
32
+ "features/time_slot_collection_compress.feature",
33
+ "features/time_slot_collection_merge.feature",
31
34
  "features/time_slot_intersection.feature",
32
35
  "features/time_slot_split.feature",
33
36
  "features/time_slot_subtraction.feature",
34
37
  "lib/slotter.rb",
35
38
  "lib/slotter/time_slot.rb",
39
+ "lib/slotter/time_slot_collection.rb",
36
40
  "slotter.gemspec",
37
41
  "spec/spec.opts",
38
42
  "spec/spec_helper.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slotter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bjarki Gudlaugsson
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-01 00:00:00 +00:00
12
+ date: 2009-11-03 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -60,14 +60,18 @@ files:
60
60
  - VERSION
61
61
  - features/case_subtraction.txt
62
62
  - features/cases_addition.txt
63
+ - features/step_definitions/time_slot_collection_definitions.rb
63
64
  - features/step_definitions/time_slot_definitions.rb
64
65
  - features/support/env.rb
65
66
  - features/time_slot_addition.feature
67
+ - features/time_slot_collection_compress.feature
68
+ - features/time_slot_collection_merge.feature
66
69
  - features/time_slot_intersection.feature
67
70
  - features/time_slot_split.feature
68
71
  - features/time_slot_subtraction.feature
69
72
  - lib/slotter.rb
70
73
  - lib/slotter/time_slot.rb
74
+ - lib/slotter/time_slot_collection.rb
71
75
  - slotter.gemspec
72
76
  - spec/spec.opts
73
77
  - spec/spec_helper.rb