chorewheel 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGELOG.markdown +0 -0
- data/Gemfile +14 -0
- data/LICENSE +23 -0
- data/README.md +5 -0
- data/Rakefile +5 -0
- data/TODO.markdown +1 -0
- data/chorewheel.gemspec +11 -0
- data/lib/chorewheel.rb +168 -0
- data/lib/interval.rb +22 -0
- data/lib/person.rb +5 -0
- data/lib/timespan.rb +21 -0
- data/lib/util.rb +26 -0
- data/spec/chorewheel_spec.rb +145 -0
- data/spec/fixtures/fixtures.rb +0 -0
- data/spec/spec_helper.rb +122 -0
- data/spec/support.rb +3 -0
- metadata +77 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDBhZjI3YmVlMzRhZjNhNDcyZDliYzkxNTViNTU0OTQwM2U0YzE3NQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MmNiMTkxZmFlN2Q5M2EyNjg3NWVhODJhZTUyMTE1NjBiMTBhNjJhNw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NGQ0YWM0NzA4ZTFmNzc3YjNhOTEwM2Q0NzI2YmY1MDMzZWUyMmQxZTJlYjRi
|
10
|
+
MDJkZjQyYTQ3NWNjZmZmYzRkYWE1NTIwMTc3OTMzYzQyNWIyMzk3ZDdjOGQ5
|
11
|
+
ZTVjYTQwZTg3MDhlMjU2YTBiZjdmMDk2MDhiNjczNTQ4ZDhkODc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MDhiN2E5ZDY2YTQ5NzA5ODM5ZWM5MjE5NmU0NTA2ZjViNGE2YzUxZmY3NWVh
|
14
|
+
OTQ1M2Q2ZmM0NjQxOGM0MmMzY2I4YzFlMDA0NjkyNzAxNzc0ODRiOWQ1YmIw
|
15
|
+
YmQ4ZDA4ZTA0MWEzYzM2Y2RhMWFiNWQ0MDQwM2Q4MDcwOTUzY2M=
|
data/CHANGELOG.markdown
ADDED
File without changes
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Aditya Bhargava
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
23
|
+
|
data/README.md
ADDED
data/Rakefile
ADDED
data/TODO.markdown
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
- extra chore i.e. person X needs to make up an extra day of chores
|
data/chorewheel.gemspec
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "chorewheel"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.summary = "Simple chore scheduler in Ruby."
|
5
|
+
s.description = "Make a chore wheel, with options for specifying multiple people, vacation days, etc."
|
6
|
+
s.author = "Aditya Bhargava"
|
7
|
+
s.email = "bluemangroupie@gmail.com"
|
8
|
+
s.files = `git ls-files`.split("\n")
|
9
|
+
s.homepage = "http://github.com/egonSchiele/chorewheel"
|
10
|
+
s.add_dependency("contracts", "~> 0.11")
|
11
|
+
end
|
data/lib/chorewheel.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# A chore schedule takes place over a timespan.
|
2
|
+
# In intervals.
|
3
|
+
# And it is done by some people.
|
4
|
+
|
5
|
+
require "util"
|
6
|
+
require "contracts"
|
7
|
+
require "timespan"
|
8
|
+
require "interval"
|
9
|
+
include Contracts
|
10
|
+
|
11
|
+
class ChoreWheel
|
12
|
+
GenericString = Or[String, Symbol]
|
13
|
+
attr_accessor :workers_per_shift, :people, :timespan, :interval
|
14
|
+
def initialize people, timespan, interval, opts = {}
|
15
|
+
unless people.is_a?(Array)
|
16
|
+
people = [people]
|
17
|
+
end
|
18
|
+
@people = people
|
19
|
+
@timespan = timespan
|
20
|
+
@interval = interval
|
21
|
+
@workers_per_shift = opts[:workers_per_shift] || 1
|
22
|
+
create
|
23
|
+
end
|
24
|
+
|
25
|
+
Contract Hash
|
26
|
+
def chunks
|
27
|
+
@chunks ||= make_chunks @timespan, @interval
|
28
|
+
@chunks
|
29
|
+
end
|
30
|
+
|
31
|
+
def chunks= c
|
32
|
+
@chunks = c
|
33
|
+
end
|
34
|
+
|
35
|
+
def map &blk
|
36
|
+
arr = []
|
37
|
+
chunks.values.map do |val|
|
38
|
+
arr << blk.call[val]
|
39
|
+
end
|
40
|
+
arr
|
41
|
+
end
|
42
|
+
|
43
|
+
Contract ArrayOf[String]
|
44
|
+
def shifts
|
45
|
+
chunks.keys
|
46
|
+
end
|
47
|
+
|
48
|
+
Contract ArrayOf[ArrayOf[GenericString]]
|
49
|
+
def workers
|
50
|
+
chunks.values
|
51
|
+
end
|
52
|
+
|
53
|
+
Contract ArrayOf[[String, ArrayOf[GenericString]]]
|
54
|
+
def to_a
|
55
|
+
chunks.to_a
|
56
|
+
end
|
57
|
+
|
58
|
+
def each &blk
|
59
|
+
chunks.values.each do |val|
|
60
|
+
blk.call(val)
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_each &blk
|
66
|
+
chunks.each do |key, val|
|
67
|
+
chunks[key] = blk.call key
|
68
|
+
end
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def count &blk
|
73
|
+
counter = 0
|
74
|
+
chunks.each do |key, val|
|
75
|
+
result = blk.call key, val
|
76
|
+
counter += 1 if result
|
77
|
+
end
|
78
|
+
counter
|
79
|
+
end
|
80
|
+
|
81
|
+
Contract Timespan::WEEK, Interval::WEEKDAY => Hash
|
82
|
+
def make_chunks timespan, interval
|
83
|
+
make_hash weekdays
|
84
|
+
end
|
85
|
+
|
86
|
+
Contract Timespan::WEEK, Interval::DAY => Hash
|
87
|
+
def make_chunks timespan, interval
|
88
|
+
make_hash days
|
89
|
+
end
|
90
|
+
|
91
|
+
Contract Timespan::WEEK, Interval::SPECIFIC_DAYS => Hash
|
92
|
+
def make_chunks timespan, interval
|
93
|
+
hash = {}
|
94
|
+
interval.days.each do |day|
|
95
|
+
hash[day] = nil
|
96
|
+
end
|
97
|
+
hash
|
98
|
+
end
|
99
|
+
|
100
|
+
Contract Timespan::MONTH, Interval::DAY => Hash
|
101
|
+
def make_chunks timespan, interval
|
102
|
+
hash = {}
|
103
|
+
start = timespan.start_date
|
104
|
+
(start...start.next_month).each do |date|
|
105
|
+
hash[date.to_s] = nil
|
106
|
+
end
|
107
|
+
hash
|
108
|
+
end
|
109
|
+
|
110
|
+
Contract Timespan::MONTH, Interval::WEEKDAY => Hash
|
111
|
+
def make_chunks timespan, interval
|
112
|
+
hash = make_chunks(timespan, Interval::DAY)
|
113
|
+
# delete sundays and saturdays
|
114
|
+
hash.delete_if do |key, _|
|
115
|
+
[0, 6].include?(Date.parse(key).wday)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
Contract Timespan::MONTH, Interval::SPECIFIC_DAYS => Hash
|
120
|
+
def make_chunks timespan, interval
|
121
|
+
hash = make_chunks(timespan, Interval::DAY)
|
122
|
+
hash.delete_if do |key, _|
|
123
|
+
!interval.days.include?(Date.parse(key).strftime("%A").downcase)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
Contract Any, Any => Any
|
128
|
+
def make_chunks timespan, interval
|
129
|
+
fail "don't know how to make timespan with timespan type #{timespan} and interval type #{interval}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def create
|
133
|
+
i = 0
|
134
|
+
_people = people.dup.shuffle
|
135
|
+
set_each do
|
136
|
+
workers = []
|
137
|
+
workers_per_shift.times do
|
138
|
+
if i >= _people.size
|
139
|
+
i = 0
|
140
|
+
_people.shuffle!
|
141
|
+
end
|
142
|
+
workers << _people[i]
|
143
|
+
i += 1
|
144
|
+
end
|
145
|
+
workers
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_hash
|
150
|
+
{
|
151
|
+
"people" => people,
|
152
|
+
"timespan" => timespan,
|
153
|
+
"interval" => interval,
|
154
|
+
"workers_per_shift" => workers_per_shift,
|
155
|
+
"chunks" => chunks
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.from_hash hash
|
160
|
+
cw = ChoreWheel.new(hash["people"], hash["timespan"], hash["interval"], {:workers_per_shift => hash["workers_per_shift"]})
|
161
|
+
cw.chunks = hash["chunks"]
|
162
|
+
cw
|
163
|
+
end
|
164
|
+
|
165
|
+
def ==(other)
|
166
|
+
to_hash == other.to_hash
|
167
|
+
end
|
168
|
+
end
|
data/lib/interval.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "contracts"
|
2
|
+
include Contracts
|
3
|
+
|
4
|
+
class Interval
|
5
|
+
DAY = :day
|
6
|
+
WEEKDAY = :weekday
|
7
|
+
WEEK = :week
|
8
|
+
MONTH = :month
|
9
|
+
YEAR = :year
|
10
|
+
|
11
|
+
class SPECIFIC_DAYS
|
12
|
+
attr_accessor :days
|
13
|
+
|
14
|
+
Contract ArrayOf[String] => Any
|
15
|
+
def initialize days
|
16
|
+
@days = days
|
17
|
+
end
|
18
|
+
def inspect
|
19
|
+
days.inspect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/person.rb
ADDED
data/lib/timespan.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Essentially an ordered hash.
|
2
|
+
# Ruby 1.9 hashes are all ordered.
|
3
|
+
require "util"
|
4
|
+
require "interval"
|
5
|
+
require "contracts"
|
6
|
+
require "date"
|
7
|
+
include Contracts
|
8
|
+
|
9
|
+
class Timespan
|
10
|
+
WEEK = :week
|
11
|
+
YEAR = :year
|
12
|
+
|
13
|
+
class MONTH
|
14
|
+
attr_accessor :start_date
|
15
|
+
|
16
|
+
Contract Date => Any
|
17
|
+
def initialize start_date
|
18
|
+
@start_date = start_date
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/util.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
def weekdays
|
2
|
+
["monday", "tuesday", "wednesday", "thursday", "friday"]
|
3
|
+
end
|
4
|
+
|
5
|
+
def days
|
6
|
+
["sunday"] + weekdays + ["saturday"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def make_hash keys
|
10
|
+
hash = {}
|
11
|
+
keys.each do |key|
|
12
|
+
hash[key] = nil
|
13
|
+
end
|
14
|
+
hash
|
15
|
+
end
|
16
|
+
|
17
|
+
# infinitely keep yielding
|
18
|
+
# elements of the array, starting
|
19
|
+
# from the beginning when you are at the end
|
20
|
+
def cycle arr
|
21
|
+
while true
|
22
|
+
arr.each do |elem|
|
23
|
+
yield elem
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require "date"
|
2
|
+
|
3
|
+
RSpec.describe "ChoreWheel" do
|
4
|
+
describe "chunks" do
|
5
|
+
it "should make chunks for week/day" do
|
6
|
+
t = ChoreWheel.new(:adit, Timespan::WEEK, Interval::DAY)
|
7
|
+
expect(t.shifts).to eq(days)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should make chunks for week/weekday" do
|
11
|
+
t = ChoreWheel.new(:adit, Timespan::WEEK, Interval::WEEKDAY)
|
12
|
+
expect(t.shifts).to eq(weekdays)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should make chunks for week/specific_days" do
|
16
|
+
t = ChoreWheel.new(:adit, Timespan::WEEK, Interval::SPECIFIC_DAYS.new(["tuesday", "thursday", "friday"]))
|
17
|
+
expect(t.shifts).to eq(["tuesday", "thursday", "friday"])
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "chunks for months" do
|
21
|
+
before :each do
|
22
|
+
@month = Timespan::MONTH.new(Date.strptime("2015-09-01", "%Y-%m-%d"))
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should make chunks for month/days" do
|
26
|
+
t = ChoreWheel.new(:adit, @month, Interval::DAY)
|
27
|
+
expect(t.shifts).to eq(["2015-09-01", "2015-09-02", "2015-09-03", "2015-09-04", "2015-09-05", "2015-09-06", "2015-09-07", "2015-09-08", "2015-09-09", "2015-09-10", "2015-09-11", "2015-09-12", "2015-09-13", "2015-09-14", "2015-09-15", "2015-09-16", "2015-09-17", "2015-09-18", "2015-09-19", "2015-09-20", "2015-09-21", "2015-09-22", "2015-09-23", "2015-09-24", "2015-09-25", "2015-09-26", "2015-09-27", "2015-09-28", "2015-09-29", "2015-09-30"])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should make chunks for month/weekdays" do
|
31
|
+
t = ChoreWheel.new(:adit, @month, Interval::WEEKDAY)
|
32
|
+
expect(t.shifts).to eq(["2015-09-01", "2015-09-02", "2015-09-03", "2015-09-04", "2015-09-07", "2015-09-08", "2015-09-09", "2015-09-10", "2015-09-11", "2015-09-14", "2015-09-15", "2015-09-16", "2015-09-17", "2015-09-18", "2015-09-21", "2015-09-22", "2015-09-23", "2015-09-24", "2015-09-25", "2015-09-28", "2015-09-29", "2015-09-30"])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should make chunks for month/specific days" do
|
36
|
+
t = ChoreWheel.new(:adit, @month, Interval::SPECIFIC_DAYS.new(["tuesday", "thursday", "friday"]))
|
37
|
+
expect(t.shifts).to eq(["2015-09-01", "2015-09-03", "2015-09-04", "2015-09-08", "2015-09-10", "2015-09-11", "2015-09-15", "2015-09-17", "2015-09-18", "2015-09-22", "2015-09-24", "2015-09-25", "2015-09-29"])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "interface" do
|
43
|
+
before :each do
|
44
|
+
@t = ChoreWheel.new(:adit, Timespan::WEEK, Interval::WEEKDAY)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "to_a" do
|
48
|
+
expect(@t.to_a).to eq([["monday", [:adit]], ["tuesday", [:adit]], ["wednesday", [:adit]], ["thursday", [:adit]], ["friday", [:adit]]])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "shifts" do
|
52
|
+
expect(@t.shifts).to eq(weekdays)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "workers" do
|
56
|
+
expect(@t.workers).to eq([[:adit], [:adit], [:adit], [:adit], [:adit]])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "create" do
|
61
|
+
people = [
|
62
|
+
[:adit],
|
63
|
+
[:adit, :maggie]
|
64
|
+
]
|
65
|
+
|
66
|
+
specific_days = Interval::SPECIFIC_DAYS.new(["tuesday", "thursday", "friday"])
|
67
|
+
|
68
|
+
create_args = [
|
69
|
+
[Timespan::WEEK, Interval::DAY],
|
70
|
+
[Timespan::WEEK, Interval::WEEKDAY],
|
71
|
+
[Timespan::WEEK, specific_days]
|
72
|
+
]
|
73
|
+
|
74
|
+
expected_shifts = {
|
75
|
+
[Timespan::WEEK, Interval::DAY] => ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"],
|
76
|
+
[Timespan::WEEK, Interval::WEEKDAY] => ["monday", "tuesday", "wednesday", "thursday", "friday"],
|
77
|
+
[Timespan::WEEK, specific_days] => ["tuesday", "thursday", "friday"]
|
78
|
+
}
|
79
|
+
|
80
|
+
people.each do |persons|
|
81
|
+
create_args.each do |args|
|
82
|
+
it "should create timespan for #{args} and #{persons}" do
|
83
|
+
cw = ChoreWheel.new(persons, *args)
|
84
|
+
expect(cw.shifts).to eq(expected_shifts[args])
|
85
|
+
|
86
|
+
check_even_distribution(cw)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "workers_per_shift" do
|
93
|
+
before :each do
|
94
|
+
@cw = ChoreWheel.new([:adit, :maggie], Timespan::WEEK, Interval::WEEKDAY, {:workers_per_shift => 2})
|
95
|
+
end
|
96
|
+
it "should assign 2 workers per shift" do
|
97
|
+
@cw.workers.each do |arr|
|
98
|
+
expect(arr.size).to eq(2)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should assign the shifts evenly" do
|
103
|
+
check_even_distribution(@cw)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "hash" do
|
108
|
+
it "should convert to json correctly" do
|
109
|
+
cw = ChoreWheel.new([:adit, :maggie], Timespan::WEEK, Interval::DAY, {:workers_per_shift => 2})
|
110
|
+
chunks = cw.chunks
|
111
|
+
|
112
|
+
expected = {
|
113
|
+
"people" => [:adit, :maggie],
|
114
|
+
"timespan" => Timespan::WEEK,
|
115
|
+
"interval" => Interval::DAY,
|
116
|
+
"workers_per_shift" => 2,
|
117
|
+
"chunks" => chunks
|
118
|
+
}
|
119
|
+
|
120
|
+
expect(cw.to_hash).to eq(expected)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should convert from json correctly" do
|
124
|
+
cw = ChoreWheel.new([:adit, :maggie], Timespan::WEEK, Interval::DAY, {:workers_per_shift => 2})
|
125
|
+
chunks = cw.chunks
|
126
|
+
|
127
|
+
hash = cw.to_hash
|
128
|
+
|
129
|
+
cw2 = ChoreWheel.from_hash hash
|
130
|
+
|
131
|
+
expect(cw2.people).to eq([:adit, :maggie])
|
132
|
+
expect(cw2.timespan).to eq(Timespan::WEEK)
|
133
|
+
expect(cw2.interval).to eq(Interval::DAY)
|
134
|
+
expect(cw2.workers_per_shift).to eq(2)
|
135
|
+
expect(cw2.chunks).to eq(chunks)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should convert back and forth correctly" do
|
139
|
+
cw = ChoreWheel.new([:adit, :maggie], Timespan::WEEK, Interval::DAY, {:workers_per_shift => 2})
|
140
|
+
hash = cw.to_hash
|
141
|
+
cw2 = ChoreWheel.from_hash hash
|
142
|
+
expect(cw).to eq(cw2)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require "timespan"
|
2
|
+
require "interval"
|
3
|
+
require "chorewheel"
|
4
|
+
require File.expand_path(File.join(__FILE__, "../support"))
|
5
|
+
require File.expand_path(File.join(__FILE__, "../fixtures/fixtures"))
|
6
|
+
|
7
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
8
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
9
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
10
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
11
|
+
#
|
12
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
13
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
14
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
15
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
16
|
+
# a separate helper file that requires the additional dependencies and performs
|
17
|
+
# the additional setup, and require it from the spec files that actually need it.
|
18
|
+
#
|
19
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
20
|
+
# users commonly want.
|
21
|
+
#
|
22
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.pattern = "*.rb"
|
25
|
+
|
26
|
+
# Only load tests who's syntax is valid in the current Ruby
|
27
|
+
[1.9, 2.0, 2.1].each do |ver|
|
28
|
+
config.pattern << ",ruby_version_specific/*#{ver}.rb" if ruby_version >= ver
|
29
|
+
end
|
30
|
+
|
31
|
+
# rspec-expectations config goes here. You can use an alternate
|
32
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
33
|
+
# assertions if you prefer.
|
34
|
+
config.expect_with :rspec do |expectations|
|
35
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
36
|
+
# and `failure_message` of custom matchers include text for helper methods
|
37
|
+
# defined using `chain`, e.g.:
|
38
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
39
|
+
# # => "be bigger than 2 and smaller than 4"
|
40
|
+
# ...rather than:
|
41
|
+
# # => "be bigger than 2"
|
42
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
43
|
+
end
|
44
|
+
|
45
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
46
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
47
|
+
config.mock_with :rspec do |mocks|
|
48
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
49
|
+
# a real object. This is generally recommended, and will default to
|
50
|
+
# `true` in RSpec 4.
|
51
|
+
mocks.verify_partial_doubles = true
|
52
|
+
end
|
53
|
+
|
54
|
+
# These two settings work together to allow you to limit a spec run
|
55
|
+
# to individual examples or groups you care about by tagging them with
|
56
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
57
|
+
# get run.
|
58
|
+
config.filter_run :focus
|
59
|
+
config.run_all_when_everything_filtered = true
|
60
|
+
|
61
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
62
|
+
# For more details, see:
|
63
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
64
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
65
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
66
|
+
config.disable_monkey_patching!
|
67
|
+
|
68
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
69
|
+
# be too noisy due to issues in dependencies.
|
70
|
+
# config.warnings = true
|
71
|
+
|
72
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
73
|
+
# file, and it's useful to allow more verbose output when running an
|
74
|
+
# individual spec file.
|
75
|
+
if config.files_to_run.one?
|
76
|
+
# Use the documentation formatter for detailed output,
|
77
|
+
# unless a formatter has already been configured
|
78
|
+
# (e.g. via a command-line flag).
|
79
|
+
config.default_formatter = "doc"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Print the 10 slowest examples and example groups at the
|
83
|
+
# end of the spec run, to help surface which specs are running
|
84
|
+
# particularly slow.
|
85
|
+
config.profile_examples = 10
|
86
|
+
|
87
|
+
# Run specs in random order to surface order dependencies. If you find an
|
88
|
+
# order dependency and want to debug it, you can fix the order by providing
|
89
|
+
# the seed, which is printed after each run.
|
90
|
+
# --seed 1234
|
91
|
+
# Unable to use it now
|
92
|
+
config.order = :random
|
93
|
+
|
94
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
95
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
96
|
+
# test failures related to randomization by passing the same `--seed` value
|
97
|
+
# as the one that triggered the failure.
|
98
|
+
Kernel.srand config.seed
|
99
|
+
|
100
|
+
# Callbacks
|
101
|
+
config.after :each do
|
102
|
+
::Contract.restore_failure_callback
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def check_even_distribution cw
|
107
|
+
# get the number of shifts for each person
|
108
|
+
shifts = cw.people.map do |name|
|
109
|
+
cw.count do |shift, workers|
|
110
|
+
workers.include?(name)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# each person should have not more than 1 away from the avg number of shifts
|
115
|
+
avg = shifts.inject(:+) / shifts.size.to_f
|
116
|
+
|
117
|
+
cw.people.zip(shifts).each do |name, shift|
|
118
|
+
if (shift - avg).abs > 1
|
119
|
+
raise "Person #{name} is doing #{shift} shifts, but the average is #{avg}."
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/spec/support.rb
ADDED
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chorewheel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aditya Bhargava
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: contracts
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.11'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.11'
|
27
|
+
description: Make a chore wheel, with options for specifying multiple people, vacation
|
28
|
+
days, etc.
|
29
|
+
email: bluemangroupie@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- .rspec
|
36
|
+
- .rubocop.yml
|
37
|
+
- .travis.yml
|
38
|
+
- CHANGELOG.markdown
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- TODO.markdown
|
44
|
+
- chorewheel.gemspec
|
45
|
+
- lib/chorewheel.rb
|
46
|
+
- lib/interval.rb
|
47
|
+
- lib/person.rb
|
48
|
+
- lib/timespan.rb
|
49
|
+
- lib/util.rb
|
50
|
+
- spec/chorewheel_spec.rb
|
51
|
+
- spec/fixtures/fixtures.rb
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
- spec/support.rb
|
54
|
+
homepage: http://github.com/egonSchiele/chorewheel
|
55
|
+
licenses: []
|
56
|
+
metadata: {}
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.4.8
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: Simple chore scheduler in Ruby.
|
77
|
+
test_files: []
|