garoupa 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f05bd1da55dd8ace5e6f7417b7892bc250e062ac
4
+ data.tar.gz: 2944585ad2dee367cdc5ffbd258f0b1ef12a37d8
5
+ SHA512:
6
+ metadata.gz: 260e13489af06ad5f8044f2a4cc01d74390276f990199ca780fb1f300aa12b4924e37430a0628109ffd2567a155ad751af3c36d281fda1ff8dc975566f0e5aee
7
+ data.tar.gz: c7676caf8c9e86175017aa916b369ad1916e9e58677614836d212752e291ef2c54f3deff52c96e459b59acb3a1210dd77ab431931f16e85300c26c90f72c6ad6
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+ - ruby-head
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: ruby-head
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in garoupa.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Torey Hickman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # Garoupa
2
+
3
+ ![Travis CI Build Status](https://api.travis-ci.org/toreyhickman/garoupa.svg?branch=master)
4
+
5
+ Garoupa was written to facilitate the assignment of groups at Dev Bootcamp where students are assigned to weekly groups. It should be generalizable to other contexts, taking an item list and returning a new Garoupa object with the assigned groups. Options allow for specifying a target group size, a maximum difference in group sizes if the number of list items is not evenly divisible by the target group size, and providing past groups so that list items can be grouped with new groupmates.
6
+
7
+ [Garoupa is apparently a Portugese name, from which the name of the grouper fish is believed to be derived](http://en.wikipedia.org/wiki/Grouper#Name_origin). The things you learn when the desired name for your gem is taken ...
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'garoupa'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install garoupa
22
+
23
+ ## Usage
24
+
25
+ The Garoupa library consists of one class: `Garoupa`. The class has two publicly defined class methods:
26
+
27
+ - `.make_groups`
28
+ - `.past_groupmates`
29
+
30
+ ### `.make_groups`
31
+
32
+ ```ruby
33
+ groups = Garoupa.make_groups [:a, :b, :c, :d, :e, :f, :g, :h]
34
+
35
+ => #<Garoupa:0x007fb523552938
36
+ @groups=[[:a, :h, :b, :g], [:f, :d, :c, :e]],
37
+ @list=[:a, :b, :c, :d, :e, :f, :g, :h],
38
+ @past_groupmates={:a=>[], :b=>[], :c=>[],
39
+ :d=>[], :e=>[], :f=>[],
40
+ :g=>[], :h=>[]}
41
+ >
42
+ ```
43
+ *Figure 1*. Making groups from a list.
44
+
45
+ `.make_groups` takes a list of arguments (i.e., an array) and returns the groups within an instance of the `Garoupa` class (see Figure 1).
46
+
47
+ The `.make_groups` methods also accepts an options hash where you can specify
48
+
49
+ - target group size
50
+ - a max difference in group sizes
51
+ - past groups
52
+
53
+ #### :target_size
54
+
55
+ ```ruby
56
+ list = [:a, :b, :c, :d, :e, :f, :g, :h]
57
+
58
+ groups = Garoupa.make_groups list, { target_size: 3 }
59
+ => #<Garoupa:0x007fb523572f80
60
+ @groups=[[:c, :d, :h], [:f, :a, :e], [:b, :g]],
61
+ @list=[:a, :b, :c, :d, :e, :f, :g, :h],
62
+ @past_groupmates={:a=>[], ... }>
63
+ ```
64
+ *Figure 2*. Making groups with a target size.
65
+
66
+ The `Garoupa` class has a constant, `DEFAULT_GROUP_SIZE`, that is used to determine the size of each group. This can be overwritten by providing a target size when calling `.make_groups` (see Figure 2). As many groups as possible will be make with the target group size. If the number of list items is not evenly divisible by the target size, the last group will have less members than the target size. This is evident in Figure 2 where the eight list items were divided into two groups of three, the target size, and one group of two.
67
+
68
+ #### :max_difference
69
+
70
+ ```ruby
71
+ list = [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j]
72
+
73
+ groups = Garoupa.make_groups list, { target_size: 3, max_difference: 1 }
74
+ => #<Garoupa:0x007fb5235900a8
75
+ @groups=[[:d, :g, :c, :b], [:f, :a, :e], [:i, :j, :h]],
76
+ @list=[:a, :b, :c, :d, :e, :f, :g, :h, :i, :j],
77
+ @past_groupmates={:a=>[], ... }>
78
+ ```
79
+
80
+ *Figure 3*. Making groups with a target size and maximum difference in group size.
81
+
82
+ If the groups will not be even, a maximum difference in group size can be specified. In Figure 3, the target size is three, but with ten items in the list, the groups will include three groups of three and one group of one. By specifying a maximum difference of one, the last groups will be dispersed into the three groups of three, resulting in one group of four and two groups of three.
83
+
84
+ #### :past_groups
85
+
86
+ ```ruby
87
+ list = [:a, :b, :c, :d]
88
+ past_groups = [[:a, :b],[:a, :c]]
89
+
90
+ groups = Garoupa.make_groups list, { target_size: 2, past_groups: past_groups }
91
+ => #<Garoupa:0x007f86c4273088
92
+ @groups=[[:a, :d], [:b, :c]],
93
+ @list=[:a, :b, :c, :d],
94
+ @past_groupmates={:a=>[:b, :c], :b=>[:a], :c=>[:a], :d=>[]}>
95
+ ```
96
+
97
+ *Figure 4*. Making groups based on past groups.
98
+
99
+ When we pass in the optional past groups, `.make_groups` will try to place items in groups with new groupmates. In the `past_groups` defined in Figure 4, Item `:a` has already been grouped with Items `:b` and `:c`. Item `:a` has not been grouped with Item `:d`; therefore, the ideal groups would be Items `:a` and `:d` together and Items `:b` and `:c` together. In these groups, no item would have a repear groupmate.
100
+
101
+ `Garoupa` attempts to make groups with no repeat pairs by calculating the past groupmates for each list item and then placing the items with the most past groupmates into groups first. Essentially, trying to place items with more constraints before items with less constraints.
102
+
103
+ Certainly, calculating all possible groupings and selecting one without any repeat pairs is possible, but it becomes impractical with larger group sizes or when repeat groupmates are inevitable.
104
+
105
+ ### `.past_groupmates`
106
+
107
+ ```ruby
108
+ list = [:a, :b, :c, :d]
109
+ past_groups = [[:a, :b],[:a, :c]]
110
+
111
+ Garoupa.past_groupmates list, past_groups
112
+ => {:a=>[:b, :c], :b=>[:a], :c=>[:a], :d=>[]}
113
+ ```
114
+
115
+ *Figure 5*. Finding the past groupmates for list items.
116
+
117
+ The second class method, `.past_groupmates`, takes a list and past groups and returns a map of the list items and their past_groupmates, as seen in Figure 5.
118
+
119
+ ### `Garoupa` instances
120
+
121
+ Instances of the `Garoupa` class are instantiated with groups, a list of items, and past groupmates. New instances are returned from `Garoupa.make_groups`, but they can also be made by providing all three required arguments. Each argument is saved as an instance variable and retrievable through getter methods.
122
+
123
+ Additionally, there are three public instance methods:
124
+
125
+ - `#repeat_pairs`
126
+ - `#to_json`
127
+ - `#to_s`
128
+
129
+ #### `#repeat_pairs`
130
+
131
+ ```ruby
132
+ list = [:a, :b, :c, :d]
133
+ past_groups = [[:a, :b],[:a, :c], [:a, :d]]
134
+
135
+ groups = Garoupa.make_groups list, target_size: 2, past_groups: past_groups
136
+ => #<Garoupa:0x007f86c414e4a0
137
+ @groups=[[:a, :d], [:c, :b]],
138
+ @list=[:a, :b, :c, :d],
139
+ @past_groupmates={:a=>[:b, :c, :d], :b=>[:a], :c=>[:a], :d=>[:a]}>
140
+
141
+ groups.repeat_pairs
142
+ => {:a=>[:d], :b=>[], :c=>[], :d=>[:a]}
143
+ ```
144
+
145
+ *Figure 6*. Repeat pairs reported for a groups.
146
+
147
+ An instance of the `Garoupa` class is able to report which list items are in groups with repeat pairs. `#repeat_pairs` returns a hash with each list item mapped to the repeat pairs in its group (see Figure 6).
148
+
149
+ #### `#to_json`
150
+
151
+ The `#to_json` method returns a JSON formatted string representing the `Garoupa` instance. It includes, the groups, list, past groupmates, and repeat pairs.
152
+
153
+ #### `#to_s`
154
+
155
+ ```ruby
156
+ list = [:a, :b, :c, :d]
157
+ past_groups = [[:a, :b],[:a, :c]]
158
+
159
+ groups = Garoupa.make_groups list, target_size: 2, past_groups: past_groups
160
+ => #<Garoupa:0x007f86c414e4a0
161
+ @groups=[[:a, :d], [:b, :c]],
162
+ @list=[:a, :b, :c, :d],
163
+ @past_groupmates={:a=>[:b, :c], :b=>[:a], :c=>[:a], :d=>[]}>
164
+
165
+ puts groups
166
+ 1. a, d
167
+ 2. b, c
168
+ => nil
169
+ ```
170
+
171
+ *Figure 7*. A `Garoupa` is printed as a numbered list.
172
+
173
+
174
+ The `#to_s` methods returns a numbered list of the groups (see Figure 7).
175
+
176
+
177
+ ## Contributing
178
+
179
+ If you'd like to help improve Garoupa by adding a new feature, please fork the repository and submit a pull request for your feature branch. Also, please report any bugs that you find.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/garoupa.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'garoupa/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "garoupa"
8
+ spec.version = Garoupa::VERSION
9
+ spec.authors = ["Torey Hickman"]
10
+ spec.email = ["torey@toreyhickman.com"]
11
+ spec.summary = %q{Make groups from a list}
12
+ spec.homepage = "https://github.com/toreyhickman/garoupa"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.6"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+
24
+ spec.add_dependency "json"
25
+ end
@@ -0,0 +1,3 @@
1
+ class Garoupa
2
+ VERSION = "1.0.0"
3
+ end
data/lib/garoupa.rb ADDED
@@ -0,0 +1,122 @@
1
+ require "garoupa/version"
2
+
3
+ class Garoupa
4
+
5
+ DEFAULT_GROUP_SIZE = 4
6
+
7
+ def self.make_groups(list, options = {})
8
+ list_items_past_groupmates = past_groupmates(list, options[:past_groups])
9
+ group_structure = make_empty_group_structure(list.size, options[:target_size])
10
+ corrected_group_structure = correct_for_group_size_difference(group_structure, options[:max_difference])
11
+ sorted_list = sort(list, list_items_past_groupmates)
12
+ groups = fill_group_structure(group_structure, sorted_list, list_items_past_groupmates)
13
+
14
+ self.new(groups, list, list_items_past_groupmates)
15
+ end
16
+
17
+ def self.past_groupmates(list, past_groups)
18
+ list.each_with_object( Hash.new ) do |list_item, previous_pairs|
19
+ previous_pairs[list_item] = past_groupmates_for(list_item, past_groups)
20
+ end
21
+ end
22
+
23
+
24
+ attr_reader :groups, :list, :past_groupmates
25
+
26
+ def initialize(groups, list, past_groupmates)
27
+ @groups = groups
28
+ @list = list
29
+ @past_groupmates = past_groupmates
30
+ end
31
+
32
+ def repeat_pairs
33
+ list.each_with_object( Hash.new ) do |list_item, repeat_pairs|
34
+ repeat_pairs[list_item] = group_for(list_item) & past_groupmates[list_item]
35
+ end
36
+ end
37
+
38
+ def to_json
39
+ { :groups => groups,
40
+ :list => list,
41
+ :past_groupmates => past_groupmates,
42
+ :repeat_pairs => repeat_pairs }.to_json
43
+ end
44
+
45
+ def to_s
46
+ groups.map.with_index(1) { |group, index| "#{index}. " + group.join(", ") }.join("\n")
47
+ end
48
+
49
+ private
50
+ def self.divide_list(list, group_size = nil)
51
+ list.each_slice(group_size || DEFAULT_GROUP_SIZE).to_a
52
+ end
53
+
54
+ def self.correct_for_group_size_difference(groups, max_difference = nil)
55
+ return groups unless max_difference
56
+
57
+ if difference_in_group_sizes(groups) > max_difference
58
+ groups = disperse_last_group(groups)
59
+ end
60
+ groups
61
+ end
62
+
63
+ def self.difference_in_group_sizes(groups)
64
+ sizes = groups.map(&:size)
65
+ sizes.max - sizes.min
66
+ end
67
+
68
+ def self.disperse_last_group(groups)
69
+ last_group = groups.pop
70
+
71
+ last_group.each_with_index do |element, index|
72
+ groups[index] << element
73
+ end
74
+
75
+ groups
76
+ end
77
+
78
+ def self.make_empty_group_structure(list_size, target_size = nil)
79
+ empty_list = Array.new(list_size) { nil }
80
+ empty_groups = divide_list(empty_list, target_size)
81
+ end
82
+
83
+ def self.past_groupmates_for(element, past_groups = nil)
84
+ return [] unless past_groups
85
+
86
+ past_groups = past_groups.select { |group| group.include? element }
87
+ past_groupmates = past_groups.flatten.uniq - [element]
88
+ end
89
+
90
+ def self.fill_group_structure(group_structure, list, previous_pairs = {})
91
+ list.each do |list_item|
92
+ place_in_best_group(list_item, group_structure, previous_pairs)
93
+ end
94
+
95
+ group_structure
96
+ end
97
+
98
+ def self.place_in_best_group(list_item, group_structure, previous_pairs)
99
+ available_groups = group_structure.select { |group| group.include? nil }
100
+ group_with_least_repeats = available_groups.min_by { |group| group & previous_pairs[list_item] }
101
+
102
+ index_of_nil = group_with_least_repeats.index nil
103
+ group_with_least_repeats[index_of_nil] = list_item
104
+
105
+ return nil
106
+ end
107
+
108
+ def self.sort(list, past_groupmates = nil)
109
+ return list.shuffle unless past_groupmates
110
+
111
+ list.shuffle.sort do |item_a, item_b|
112
+ item_a_number_of_past_groupmates = past_groupmates.fetch(item_a, []).size
113
+ item_b_number_of_past_groupmates = past_groupmates.fetch(item_b, []).size
114
+
115
+ item_b_number_of_past_groupmates <=> item_a_number_of_past_groupmates
116
+ end
117
+ end
118
+
119
+ def group_for(list_item)
120
+ groups.find { |group| group.include? list_item }
121
+ end
122
+ end
@@ -0,0 +1,181 @@
1
+ require 'spec_helper'
2
+
3
+ describe Garoupa do
4
+
5
+ let(:long_list) { [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l] }
6
+ let(:garoupa_no_options) { Garoupa.make_groups(long_list) }
7
+
8
+ let(:garoupa) { Garoupa.new(groups, list, past_groupmates) }
9
+ let(:groups) { [[:a, :b], [:c, :d]] }
10
+ let(:list) { [:a, :b, :c, :d] }
11
+ let(:past_groupmates) do
12
+ { :a => [:b, :c, :d],
13
+ :b => [:a],
14
+ :c => [],
15
+ :d => [] }
16
+ end
17
+
18
+
19
+ describe ".make_groups" do
20
+ it "returns a Groupa object" do
21
+ expect(garoupa_no_options).to be_instance_of Garoupa
22
+ end
23
+
24
+ it "places each list item into one group" do
25
+ list_items_in_groups = garoupa_no_options.groups.flatten
26
+
27
+ expect(list_items_in_groups - long_list).to be_empty
28
+ end
29
+
30
+ describe "group_sizes" do
31
+ context "no target size given" do
32
+ it "attemtps to make groups of the default group size" do
33
+
34
+ expect(garoupa_no_options.groups.first.size).to eq Garoupa::DEFAULT_GROUP_SIZE
35
+ end
36
+ end
37
+
38
+ context "target size given" do
39
+ context "list size evenly divisible by target size" do
40
+ it "makes groups of a specified size" do
41
+ options = { target_size: 3 }
42
+ groups = Garoupa.make_groups(long_list, options)
43
+ groups_sizes = groups.groups.map(&:size)
44
+
45
+ expect(groups_sizes.all? { |s| s == 3 }).to be true
46
+ end
47
+ end
48
+
49
+ context "list size not evenly divisible by target size" do
50
+ context "no max size difference specified" do
51
+ it "has one group with a different size" do
52
+ options = { target_size: 5 }
53
+ groups = Garoupa.make_groups(long_list, options)
54
+ groups_sizes = groups.groups.map(&:size)
55
+
56
+ expect(groups_sizes).to match_array [5, 5, 2]
57
+ end
58
+ end
59
+
60
+ context "max size difference specified" do
61
+ context "max size difference not exceeded" do
62
+ it "leaves the smaller group" do
63
+ options = { target_size: 5, max_difference: 3 }
64
+ groups = Garoupa.make_groups(long_list, options)
65
+ groups_sizes = groups.groups.map(&:size)
66
+
67
+ expect(groups_sizes).to match_array [5, 5, 2]
68
+ end
69
+ end
70
+ context "max size difference exceeded" do
71
+ it "disperses the smaller group" do
72
+ options = { target_size: 5, max_difference: 2 }
73
+ groups = Garoupa.make_groups(long_list, options)
74
+ groups_sizes = groups.groups.map(&:size)
75
+
76
+ expect(groups_sizes).to match_array [6, 6]
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "group make up" do
85
+ context "no past groups provided" do
86
+ it "divides shuffled list into groups" do
87
+ allow(long_list).to receive(:shuffle) do
88
+ [:a, :l, :c, :k, :e, :j, :g, :h, :i, :f, :d, :b]
89
+ end
90
+ expected_groups = [[:a, :l, :c, :k], [:e, :j, :g, :h], [:i, :f, :d, :b]]
91
+
92
+ expect(garoupa_no_options.groups).to match_array expected_groups
93
+ end
94
+ end
95
+
96
+ context "past groups provided" do
97
+ let(:past_groups) { [[:a, :b], [:a, :c], [:a, :d], [:a, :e], [:a, :f], [:a, :g], [:a, :h], [:a, :i]] }
98
+
99
+ it "attempts to make groups with minimal repeats" do
100
+ allow(long_list).to receive(:shuffle) do
101
+ [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l]
102
+ end
103
+
104
+ options = { past_groups: past_groups }
105
+ groups = Garoupa.make_groups(long_list, options).groups
106
+
107
+ a_group = groups.find { |group| group.include? :a }
108
+ expect(a_group).to match_array [:a, :j, :k, :l]
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe ".past_groupmates" do
115
+ let(:list) { [:a, :b, :c, :d] }
116
+ let(:past_groups) { [[:a, :b], [:a, :b], [:a, :c]] }
117
+
118
+ it "maps list items to their unique previous groupmates" do
119
+ past_group_map = Garoupa.past_groupmates(list, past_groups)
120
+
121
+ expect(past_group_map[:a]).to match_array [:b, :c]
122
+ expect(past_group_map[:b]).to match_array [:a]
123
+ expect(past_group_map[:c]).to match_array [:a]
124
+ expect(past_group_map[:d]).to be_empty
125
+ end
126
+ end
127
+
128
+ describe "accessor methods" do
129
+ let(:groups) { :groups_argument }
130
+ let(:list) { :list_argument }
131
+ let(:past_groupmates) { :past_groupmates_argument }
132
+
133
+ let(:garoupa) { Garoupa.new(groups, list, past_groupmates) }
134
+
135
+ it "returns the list" do
136
+ expect(garoupa.list).to eq list
137
+ end
138
+
139
+ it "returns the groups" do
140
+ expect(garoupa.groups).to eq groups
141
+ end
142
+
143
+ it "returns the past groupmates" do
144
+ expect(garoupa.past_groupmates).to eq past_groupmates
145
+ end
146
+ end
147
+
148
+ describe "#repeat_pairs" do
149
+ it "returns the repeat pairs for each list item" do
150
+ expected_repeat_pairs = { :a => [:b],
151
+ :b => [:a],
152
+ :c => [],
153
+ :d => [] }
154
+
155
+ expect(garoupa.repeat_pairs).to eq expected_repeat_pairs
156
+ end
157
+ end
158
+
159
+ describe "#to_json" do
160
+ it "returns a JSON formatted string" do
161
+ expect { JSON.parse(garoupa.to_json) }.to_not raise_error
162
+ end
163
+
164
+ it "includes groups, list, past groupmates, and repeat pairs" do
165
+ expected_json = { :groups => garoupa.groups,
166
+ :list => garoupa.list,
167
+ :past_groupmates => garoupa.past_groupmates,
168
+ :repeat_pairs => garoupa.repeat_pairs }.to_json
169
+
170
+ expect(garoupa.to_json).to eq expected_json
171
+ end
172
+ end
173
+
174
+ describe "#to_s" do
175
+ it "returns a numbered list of the groups" do
176
+ expected_string = "1. a, b\n2. c, d"
177
+
178
+ expect(garoupa.to_s).to eq expected_string
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,6 @@
1
+ require 'garoupa'
2
+ require 'json'
3
+
4
+ RSpec.configure do |c|
5
+ c.order = "random"
6
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: garoupa
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Torey Hickman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - torey@toreyhickman.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - garoupa.gemspec
83
+ - lib/garoupa.rb
84
+ - lib/garoupa/version.rb
85
+ - spec/garoupa_spec.rb
86
+ - spec/spec_helper.rb
87
+ homepage: https://github.com/toreyhickman/garoupa
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.2.2
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Make groups from a list
111
+ test_files:
112
+ - spec/garoupa_spec.rb
113
+ - spec/spec_helper.rb