rasam 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/README.md +94 -6
- data/lib/rasam.rb +69 -34
- data/lib/rasam/version.rb +1 -1
- data/rasam.gemspec +4 -0
- data/scripts/prank.rb +69 -0
- data/todo.txt +11 -2
- metadata +35 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cefaa3715a0010c00504feb32a12fae7e5d4a538
|
4
|
+
data.tar.gz: 841cd1f623188c8eaf49a18e6ff540f1b703abbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bf0f4b37ca5b1b7ec31961723ffd48b4c7ddfd1ed82612da9b6b1ca161c181fd33c16e135e59507c20229527c6fab41468ffaa629c091c4a54e34ff19fb6c49
|
7
|
+
data.tar.gz: f5bbd8648953a8071926de7e7c5e012a1dfc6d8d266265d3cf48529c8d4932e0e0efafc1c7664f4d0961ed52416724b3fd0ce777d0e2644d50d1fe03e72a5f86
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rasam
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
data/README.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# Rasam
|
2
2
|
|
3
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rasam`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
-
|
5
3
|
Ranked pairs (RP) or the Tideman method is a voting system developed in 1987 by Nicolaus Tideman that selects a single winner using votes that express preferences. RP can also be used to create a sorted list of winners.
|
6
4
|
|
5
|
+
## Console
|
6
|
+
|
7
|
+
To experiment with the code, run `bin/console` for an interactive prompt.
|
8
|
+
|
7
9
|
## Installation
|
8
10
|
|
9
11
|
Add this line to your application's Gemfile:
|
@@ -22,7 +24,80 @@ Or install it yourself as:
|
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
|
-
|
27
|
+
Here is a simple script that uses the highline gem for command line interface to the gem. Just enter Salary <enter>, Stocks <enter>, Telecommuting <enter> and hit <enter><enter> when prompted for choices:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'highline/import'
|
31
|
+
require "pp"
|
32
|
+
require_relative '../lib/rasam'
|
33
|
+
|
34
|
+
include Rasam
|
35
|
+
|
36
|
+
def get_user_choice_for(pair)
|
37
|
+
choose do |menu|
|
38
|
+
menu.prompt = "Please choose your favorite: "
|
39
|
+
|
40
|
+
pair.each do |c|
|
41
|
+
menu.choice(c) do
|
42
|
+
say(c)
|
43
|
+
rationale = ask("Why? ")
|
44
|
+
say(rationale)
|
45
|
+
|
46
|
+
@pr.make_rational_choice(pair, c, rationale)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def display_score(options)
|
53
|
+
options.each do |option|
|
54
|
+
p "Score for #{option} : #{@pr.score_for(option)}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
options = ask("Enter your choices (or a blank line to quit):",
|
59
|
+
lambda { |ans| ans =~ /^-?\d+$/ ? Integer(ans) : ans} ) do |q|
|
60
|
+
q.gather = ""
|
61
|
+
end
|
62
|
+
|
63
|
+
@pr = PairRank.new(options)
|
64
|
+
|
65
|
+
def display_decisions
|
66
|
+
@pr.decisions.each do |d|
|
67
|
+
p d.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
pair = @pr.combination
|
72
|
+
|
73
|
+
loop do
|
74
|
+
p pair
|
75
|
+
break if pair.nil?
|
76
|
+
get_user_choice_for(pair)
|
77
|
+
pair = @pr.combination
|
78
|
+
end
|
79
|
+
|
80
|
+
display_decisions
|
81
|
+
display_score(options)
|
82
|
+
|
83
|
+
p 'Processing ties'
|
84
|
+
|
85
|
+
loop do
|
86
|
+
tie = @pr.tied_pair
|
87
|
+
if tie.empty?
|
88
|
+
break
|
89
|
+
else tie.empty?
|
90
|
+
p 'Handling a tie'
|
91
|
+
|
92
|
+
get_user_choice_for(tie)
|
93
|
+
|
94
|
+
display_decisions
|
95
|
+
display_score(options)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
You can find this script prank.rb in the scripts folder.
|
26
101
|
|
27
102
|
## Development
|
28
103
|
|
@@ -31,11 +106,25 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
31
106
|
Run the test with color:
|
32
107
|
|
33
108
|
```ruby
|
34
|
-
$ ruby -rminitest/pride test/pair_rank_test.rb
|
109
|
+
$ ruby -rminitest/pride test/pair_rank_test.rb --verbose
|
110
|
+
$ ruby -rminitest/pride test/pair_rank_simulator_test.rb --verbose
|
111
|
+
$ ruby -rminitest/pride test/combination_test.rb --verbose
|
35
112
|
```
|
36
113
|
|
114
|
+
To run all tests:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
$ rake
|
118
|
+
```
|
119
|
+
|
120
|
+
Default rake task will not run all the tests if you mix Test::Unit::TestCase and Minitest::Test. It will only run tests with Test::Unit::TestCase as it's parent. The coverage report gets clobbered if all the tests extend from Test::Unit::TestCase. So one of the test is extending from Minitest::Test to generate the coverage report.
|
121
|
+
|
37
122
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
38
123
|
|
124
|
+
## Articles
|
125
|
+
|
126
|
+
[TDD Beyond Basics : Outside In Perspective] (https://rubyplus.com/articles/2531 'TDD Beyond Basics : Outside In Perspective')
|
127
|
+
|
39
128
|
## Contributing
|
40
129
|
|
41
130
|
Bug reports and pull requests are welcome on GitHub at https://bitbucket.org/bparanj/rasam.
|
@@ -45,5 +134,4 @@ gem push rasam-0.1.0.gem
|
|
45
134
|
|
46
135
|
## License
|
47
136
|
|
48
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
49
|
-
|
137
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/rasam.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "rasam/version"
|
2
|
-
require 'forwardable'
|
3
2
|
|
4
3
|
module Rasam
|
5
4
|
# Value Object
|
@@ -20,61 +19,97 @@ module Rasam
|
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
22
|
+
class Combination
|
23
|
+
def initialize(options)
|
24
|
+
@list = options.combination(2).to_a
|
25
|
+
@index = -1
|
26
|
+
end
|
27
|
+
|
28
|
+
def pair
|
29
|
+
@index += 1
|
30
|
+
@list[@index]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
23
34
|
class PairRank
|
24
|
-
attr_reader :
|
35
|
+
attr_reader :decisions
|
25
36
|
|
26
37
|
def initialize(options)
|
38
|
+
@options = options
|
27
39
|
@decisions = []
|
28
40
|
@votes = Hash.new(0)
|
29
|
-
@
|
41
|
+
@combination = Combination.new(@options)
|
30
42
|
end
|
31
|
-
|
32
|
-
def
|
33
|
-
@
|
34
|
-
|
43
|
+
|
44
|
+
def combinations
|
45
|
+
@options.combination(2).to_a
|
46
|
+
end
|
47
|
+
|
48
|
+
def combination
|
49
|
+
@combination.pair
|
35
50
|
end
|
36
|
-
|
51
|
+
|
37
52
|
def score_for(choice)
|
38
53
|
@votes[choice]
|
39
54
|
end
|
55
|
+
|
56
|
+
def tied_pair
|
57
|
+
return [] if zeros?
|
58
|
+
|
59
|
+
find_tie
|
60
|
+
end
|
61
|
+
|
62
|
+
def break_tie(pair, choice, criteria)
|
63
|
+
make_rational_choice(pair, choice, criteria)
|
64
|
+
end
|
65
|
+
|
66
|
+
def make_rational_choice(pair, choice, criteria)
|
67
|
+
rc = RationalChoice.new(pair, choice, criteria)
|
68
|
+
make(rc)
|
69
|
+
end
|
70
|
+
|
71
|
+
# :nocov:
|
72
|
+
private
|
40
73
|
|
41
|
-
|
42
|
-
|
43
|
-
|
74
|
+
# All choices with 0 scores mean the Pair Ranking process has not begun
|
75
|
+
def zeros?
|
76
|
+
list = @options.collect{|c| score_for(c)}
|
77
|
+
list.uniq == [0]
|
44
78
|
end
|
45
79
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
80
|
+
def tie(combination)
|
81
|
+
first = score_for(combination[0])
|
82
|
+
second = score_for(combination[1])
|
83
|
+
first == second
|
49
84
|
end
|
50
85
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
first = score_for(combination[0])
|
55
|
-
second = score_for(combination[1])
|
56
|
-
|
57
|
-
if tie(first, second)
|
58
|
-
result = combination
|
59
|
-
break
|
60
|
-
end
|
61
|
-
end
|
62
|
-
result
|
86
|
+
def make(rational_choice)
|
87
|
+
store(rational_choice)
|
88
|
+
vote_for(rational_choice)
|
63
89
|
end
|
64
90
|
|
65
|
-
def
|
66
|
-
|
91
|
+
def has_tie?
|
92
|
+
!tied_pair.empty?
|
67
93
|
end
|
68
94
|
|
69
|
-
def
|
70
|
-
|
71
|
-
make(rc)
|
95
|
+
def vote_for(rational_choice)
|
96
|
+
@votes[rational_choice.choice] += 1
|
72
97
|
end
|
73
98
|
|
74
|
-
|
99
|
+
# For display at the end of the Pair Ranking process
|
100
|
+
def store(rational_choice)
|
101
|
+
@decisions << rational_choice
|
102
|
+
end
|
75
103
|
|
76
|
-
def
|
77
|
-
|
104
|
+
def find_tie
|
105
|
+
result = []
|
106
|
+
combinations.each do |combination|
|
107
|
+
if tie(combination)
|
108
|
+
result = combination
|
109
|
+
break
|
110
|
+
end
|
111
|
+
end
|
112
|
+
result
|
78
113
|
end
|
79
114
|
end
|
80
115
|
|
data/lib/rasam/version.rb
CHANGED
data/rasam.gemspec
CHANGED
@@ -19,7 +19,11 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
+
spec.required_ruby_version = '>= 2.2.2'
|
23
|
+
|
22
24
|
spec.add_development_dependency "bundler", "~> 1.10"
|
23
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
26
|
spec.add_development_dependency "minitest", "~> 5.4"
|
27
|
+
spec.add_development_dependency "simplecov", "~> 0.10.0"
|
28
|
+
spec.add_development_dependency "highline", "~> 1.7"
|
25
29
|
end
|
data/scripts/prank.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
require "pp"
|
3
|
+
require_relative '../lib/rasam'
|
4
|
+
|
5
|
+
include Rasam
|
6
|
+
|
7
|
+
def get_user_choice_for(pair)
|
8
|
+
choose do |menu|
|
9
|
+
menu.prompt = "Please choose your favorite: "
|
10
|
+
|
11
|
+
pair.each do |c|
|
12
|
+
menu.choice(c) do
|
13
|
+
say(c)
|
14
|
+
rationale = ask("Why? ")
|
15
|
+
say(rationale)
|
16
|
+
|
17
|
+
@pr.make_rational_choice(pair, c, rationale)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def display_score(options)
|
24
|
+
options.each do |option|
|
25
|
+
p "Score for #{option} : #{@pr.score_for(option)}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
options = ask("Enter your choices (or a blank line to quit):",
|
30
|
+
lambda { |ans| ans =~ /^-?\d+$/ ? Integer(ans) : ans} ) do |q|
|
31
|
+
q.gather = ""
|
32
|
+
end
|
33
|
+
|
34
|
+
@pr = PairRank.new(options)
|
35
|
+
|
36
|
+
def display_decisions
|
37
|
+
@pr.decisions.each do |d|
|
38
|
+
p d.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
pair = @pr.combination
|
43
|
+
|
44
|
+
loop do
|
45
|
+
p pair
|
46
|
+
break if pair.nil?
|
47
|
+
get_user_choice_for(pair)
|
48
|
+
pair = @pr.combination
|
49
|
+
end
|
50
|
+
|
51
|
+
display_decisions
|
52
|
+
display_score(options)
|
53
|
+
|
54
|
+
p 'Processing ties'
|
55
|
+
|
56
|
+
loop do
|
57
|
+
tie = @pr.tied_pair
|
58
|
+
if tie.empty?
|
59
|
+
break
|
60
|
+
else tie.empty?
|
61
|
+
p 'Handling a tie'
|
62
|
+
|
63
|
+
get_user_choice_for(tie)
|
64
|
+
|
65
|
+
display_decisions
|
66
|
+
display_score(options)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
data/todo.txt
CHANGED
@@ -1,2 +1,11 @@
|
|
1
|
-
1.
|
2
|
-
|
1
|
+
1. Demo using realistic example for job offer negotiation:
|
2
|
+
|
3
|
+
Salary
|
4
|
+
Stocks
|
5
|
+
Bonus
|
6
|
+
Signon Bonus
|
7
|
+
Vacation
|
8
|
+
Telecommuting
|
9
|
+
|
10
|
+
2. Buying a car.
|
11
|
+
3. Choosing a job.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rasam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bala Paranj
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.10.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.10.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: highline
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.7'
|
55
83
|
description: Select a single winner using votes that express preferences. This can
|
56
84
|
also be used to create a sorted list of winners
|
57
85
|
email:
|
@@ -61,6 +89,8 @@ extensions: []
|
|
61
89
|
extra_rdoc_files: []
|
62
90
|
files:
|
63
91
|
- ".gitignore"
|
92
|
+
- ".ruby-gemset"
|
93
|
+
- ".ruby-version"
|
64
94
|
- ".travis.yml"
|
65
95
|
- Gemfile
|
66
96
|
- LICENSE.txt
|
@@ -71,6 +101,7 @@ files:
|
|
71
101
|
- lib/rasam.rb
|
72
102
|
- lib/rasam/version.rb
|
73
103
|
- rasam.gemspec
|
104
|
+
- scripts/prank.rb
|
74
105
|
- todo.txt
|
75
106
|
homepage: https://bitbucket.org/bparanj/rasam
|
76
107
|
licenses:
|
@@ -84,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
115
|
requirements:
|
85
116
|
- - ">="
|
86
117
|
- !ruby/object:Gem::Version
|
87
|
-
version:
|
118
|
+
version: 2.2.2
|
88
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
120
|
requirements:
|
90
121
|
- - ">="
|
@@ -92,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
123
|
version: '0'
|
93
124
|
requirements: []
|
94
125
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
126
|
+
rubygems_version: 2.4.6
|
96
127
|
signing_key:
|
97
128
|
specification_version: 4
|
98
129
|
summary: Pair Rank a given list of items.
|