slotter 0.0.2 → 0.0.3
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.
- data/VERSION +1 -1
- data/features/step_definitions/time_slot_collection_definitions.rb +24 -0
- data/features/step_definitions/time_slot_definitions.rb +11 -3
- data/features/time_slot_addition.feature +15 -29
- data/features/time_slot_collection_compress.feature +19 -0
- data/features/time_slot_collection_merge.feature +22 -0
- data/lib/slotter.rb +2 -1
- data/lib/slotter/time_slot.rb +51 -10
- data/lib/slotter/time_slot_collection.rb +74 -0
- data/slotter.gemspec +6 -2
- metadata +6 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
51
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
+
|
data/lib/slotter.rb
CHANGED
data/lib/slotter/time_slot.rb
CHANGED
@@ -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
|
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
|
103
|
+
return other_slot.clone
|
63
104
|
end
|
64
105
|
# Case 4
|
65
106
|
if self.finish == other_slot.start
|
66
|
-
return
|
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
|
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
|
-
|
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
|
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
|
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
|
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
|
data/slotter.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{slotter}
|
8
|
-
s.version = "0.0.
|
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-
|
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.
|
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-
|
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
|