minigame 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YWY0MTkxZDc2ZTg1NWExMTgwODMyMDAwNjEwNmQ3YzZiODJmYTM1Zg==
4
+ OWQ1MjQwNjNjNGM5MTZiNWQ2ZDE3ZjQ4YWUxYmZmZjMyM2QxY2NmNA==
5
5
  data.tar.gz: !binary |-
6
- NGYzYTBiYTQ0ODFkNDg5OWVlYWRiZDJmYTJjNDIyNzZlY2VmNzk3Yw==
6
+ ZjMyNjg1N2ZjYjY0ODI1YmY5ZTdhMDA1NzkxM2Y5OWRhOGIxMThhMA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- OTM4MDgzZGY3MWNlNWUwOWY0ZGE0ZmM2ZDg4NWQ0NmQxNzU0YTc2Y2JiNWQy
10
- MWMzMTA3MmY5MDk1Mjk0ZjVjMGNkODNlYTU0OGU2ZjJlMGYzYTdjYTBmOWE3
11
- NTA2OWMzMDhhNGU2OGFmYjFhNzA5ZGJiNjVjZGMyODg2MThiYTg=
9
+ YzBlNDY5ODdkZTdlMTRjNzExYTNhMjVlZGViYzQxMDZlNzdkNDMyODQyNzhk
10
+ Y2RiMzA0NGU4OGM1M2IxMzY5YmM5ZGQ1MTJhNDQyMTYyMzJiNjUwYzYxYzVi
11
+ NzljNDg0NzQ1OTg5ZjAxNzhjZDc2MTg1NGRlZWYyODI1Y2E4MjQ=
12
12
  data.tar.gz: !binary |-
13
- YjhlN2JiMzQzMjRmZDBmOGFjODQyMjA5Nzk5ZjRkZDAwZGYyN2Y4NGM3YjQ4
14
- ZjZhM2NjMWI4YmNlNWQwZjc3OTVkMDk3ZDQwODhiNGJjNmVhMzc4YWUxNjI1
15
- ZWJhZjk5YTNmMzUyMWMyMzUwYWNkY2ZiYTNjMzgzNzk1Y2RjNzA=
13
+ YjcyMmE3MjUyYzg0MDM5NGQyZWNmYmY4NDdjNjllYzdmZmI4YTYwNWYxZmM0
14
+ ODE4Mjk2Y2YwMTg5MmRiNzEzM2YzMjgyNGUzZjM1NzdlMDFhZjRmMWMzZjNm
15
+ YmYyMDM4NDY1MjZjNjRhNjYxMDJiY2ZjNWJlMGE4MDk0ZmFiMjM=
data/.gitignore CHANGED
@@ -91,6 +91,8 @@ capybara-*.html
91
91
  /log/*
92
92
  /tmp/*
93
93
  /db/*.sqlite3
94
+ /pkg
95
+ /pkg/*
94
96
  /public/system/*
95
97
  /coverage/
96
98
  /spec/tmp/*
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ # uncomment this line if your project needs to run something other than `rake`:
5
+ # script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -2,4 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in minigame.gemspec
4
4
  gemspec
5
- gem 'debugger'
5
+ #gem 'debugger'
data/Gemfile.lock CHANGED
@@ -1,27 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- minigame (0.0.1)
4
+ minigame (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- columnize (0.3.6)
10
- debugger (1.6.1)
11
- columnize (>= 0.3.1)
12
- debugger-linecache (~> 1.2.0)
13
- debugger-ruby_core_source (~> 1.2.3)
14
- debugger-linecache (1.2.0)
15
- debugger-ruby_core_source (1.2.3)
9
+ diff-lcs (1.2.4)
16
10
  minitest (5.0.6)
17
11
  rake (10.1.0)
12
+ rspec (2.13.0)
13
+ rspec-core (~> 2.13.0)
14
+ rspec-expectations (~> 2.13.0)
15
+ rspec-mocks (~> 2.13.0)
16
+ rspec-core (2.13.1)
17
+ rspec-expectations (2.13.0)
18
+ diff-lcs (>= 1.1.3, < 2.0)
19
+ rspec-mocks (2.13.1)
18
20
 
19
21
  PLATFORMS
20
22
  ruby
21
23
 
22
24
  DEPENDENCIES
23
25
  bundler (~> 1.3)
24
- debugger
25
26
  minigame!
26
27
  minitest
27
28
  rake
29
+ rspec
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
+ [![Build Status](https://travis-ci.org/wavell/minigame.png)](https://travis-ci.org/wavell/minigame)
1
2
  # MiniGame
2
3
  ## Simplistic Game Theory Library in Ruby
3
4
 
5
+ Installation
6
+ ```
7
+ gem install minigame
8
+ ```
9
+
4
10
  Usage:
5
11
 
6
12
  To create new players:
@@ -70,7 +76,7 @@ To get the list a weakly dominated strategies:
70
76
  # ------------------------|---------------------|------------------
71
77
  gs.weakly_dominated_list
72
78
 
73
- [{:name=>"Generic Training"}, {:name=>"Deny Training"}]
79
+ [{:name=>"Generic Training"}]
74
80
 
75
81
  ```
76
82
 
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require "bundler/gem_tasks"
2
2
  require 'rake/testtask'
3
3
  Rake::TestTask.new do |t|
4
4
  t.libs << 'test'
5
+ system("bundle exec rspec spec/")
5
6
  end
6
7
 
7
8
  desc "Run tests"
@@ -79,7 +79,10 @@ module Gameable
79
79
  end
80
80
  end
81
81
  end
82
- dominated_list.flatten.uniq
82
+ dom = dominated_list.flatten.uniq
83
+ strict = strictly_dominated_list
84
+ weakly_dominated_list = dom.take_while{|i| strict.include?(i)==false}
85
+ weakly_dominated_list
83
86
  end
84
87
 
85
88
  def strategies_by_player(player)
@@ -1,3 +1,3 @@
1
1
  module Minigame
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/minigame.gemspec CHANGED
@@ -6,11 +6,11 @@ require 'minigame/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "minigame"
8
8
  spec.version = Minigame::VERSION
9
- spec.authors = ["Wavell Watson"]
10
- spec.email = ["wavell.watson@gmail.com"]
9
+ spec.authors = ["W Watson"]
10
+ spec.email = ["me@wwatson.me"]
11
11
  spec.description = %q{A game theory library}
12
12
  spec.summary = %q{A minimalistic game theory library that computes nash equilibrium}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/wavell/minigame"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -21,5 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "minitest"
24
+ spec.add_development_dependency "rspec"
24
25
 
25
26
  end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe ArrayOfHashes do
4
+ before(:each) do
5
+ class TestAOfH
6
+ include ArrayOfHashes
7
+ end
8
+ end
9
+
10
+ it "should instantiate with an array of hashes" do
11
+ aoh = TestAOfH.new [{keyname1: "test1", keyname2: "test2"},{keyname3: "test3", keyname4: "test4"}]
12
+ aoh.count.should == 2
13
+ end
14
+
15
+ it "should have enumerable functions" do
16
+ aoh = TestAOfH.new [{keyname1: "test1", keyname2: "test2"},{keyname3: "test3", keyname4: "test4"}]
17
+ @test2 = aoh.select{|x| x[:keyname2] == "test2"}
18
+ @test2.count.should == 1
19
+ end
20
+
21
+ it ".required_keys should reject non-symbols" do
22
+ aoh=TestAOfH.new
23
+ expect {
24
+ aoh.required_keys ["name", "description"]
25
+ }.to raise_error(RuntimeError,/Not a symbol/)
26
+ end
27
+
28
+ it ".required_keys should work as assignment" do
29
+ aoh=TestAOfH.new
30
+ expect {
31
+ aoh.required_keys = [:name, :description]
32
+ }.to_not raise_error
33
+ end
34
+
35
+ it ".required_keys should also work with a single symbol (not an array)" do
36
+ aoh=TestAOfH.new
37
+ expect {
38
+ aoh.required_keys = :name
39
+ }.to_not raise_error
40
+ end
41
+
42
+ it ".required_keys should accept a list of symbols" do
43
+ aoh=TestAOfH.new
44
+ expect {
45
+ aoh.required_keys([:name, :description])
46
+ }.to_not raise_error
47
+ end
48
+
49
+ it ".check_keys should allow a name" do
50
+ aoh=TestAOfH.new
51
+ expect {
52
+ aoh.check_keys({name: "Deny Training"})
53
+ }.to_not raise_error
54
+ end
55
+
56
+ it ".check_keys should raise an error if not passed a hash" do
57
+ aoh=TestAOfH.new
58
+ expect {
59
+ aoh.check_keys('notahash')
60
+ }.to raise_error(RuntimeError,/Not a Hash/)
61
+ end
62
+
63
+ it ".check_keys should check for name" do
64
+ aoh=TestAOfH.new
65
+ aoh.required_keys :name
66
+ expect {
67
+ aoh.check_keys({hmm: 'notahash'})
68
+ }.to raise_error(RuntimeError,/Name required/)
69
+ end
70
+
71
+ it "should allow addition of hashes with <<" do
72
+ aoh = TestAOfH.new
73
+ aoh << {keyname1: "test1", keyname2: "test2"}
74
+ aoh << {keyname3: "test3", keyname4: "test4"}
75
+ aoh.count.should == 2
76
+ end
77
+
78
+ it "should check for an required keys when initializing" do
79
+ aoh = TestAOfH.new
80
+ aoh.required_keys = [:name, :description]
81
+ expect {
82
+ aoh << {notname: "test1", description: "test2"}
83
+ }.to raise_error(RuntimeError,/Name required/)
84
+ end
85
+
86
+ it "should allow inserts when required keys are present" do
87
+ aoh = TestAOfH.new
88
+ aoh.required_keys = [:name, :description]
89
+ expect {
90
+ aoh << {name: "test1", description: "test2"}
91
+ aoh << {name: "test3", description: "test4"}
92
+ }.to_not raise_error
93
+ end
94
+ end
@@ -0,0 +1,4 @@
1
+ describe Gameable do
2
+ it "should create a game on another entity" do
3
+ end
4
+ end
@@ -0,0 +1,280 @@
1
+ require 'spec_helper'
2
+
3
+ describe Game do
4
+
5
+ # training game -- generic weakly dominated (not realistic)
6
+ #
7
+ # Employer: | Task Specific | Generic
8
+ # You: -----------------|---------------------|------------------
9
+ # | |
10
+ # Deny Training | (-2, -1) | (-2, -1)
11
+ # ------------------------|---------------------|------------------
12
+ # Accept Training | (1, 4) | (5, -2)
13
+ # ------------------------|---------------------|------------------
14
+ def game_with_weakly_dominated_strategies
15
+ strategies = Strategy.new [{name: "Accept Training"}, {name: "Generic Training"},{name: "Task Specific Training"},{name: "Deny Training"}]
16
+ accept = strategies.find{|x| x[:name] == "Accept Training"}
17
+ generic = strategies.find{|x| x[:name] == "Generic Training"}
18
+ task = strategies.find{|x| x[:name] == "Task Specific Training"}
19
+ deny = strategies.find{|x| x[:name] == "Deny Training"}
20
+ employer = Player.new name: "IBM"
21
+ employee = Player.new name: "John Smith"
22
+
23
+ strategy_profile = StrategyProfile.new
24
+ strategy_profile << {id: 1, strategy: generic, payoff: -2, player: employer}
25
+ strategy_profile << {id: 1, strategy: accept, payoff: 5, player: employee}
26
+
27
+ strategy_profile << {id: 2, strategy: generic, payoff: -1, player: employer}
28
+ strategy_profile << {id: 2, strategy: deny, payoff: -2, player: employee}
29
+
30
+ # not realistic
31
+ strategy_profile << {id: 3, strategy: task, payoff: -1, player: employer}
32
+ strategy_profile << {id: 3, strategy: deny, payoff: -2, player: employee}
33
+
34
+ strategy_profile << {id: 4, strategy: task, payoff: 4, player: employer}
35
+ strategy_profile << {id: 4, strategy: accept, payoff: 1, player: employee}
36
+ gs = Game.new
37
+ gs.strategy_profiles = strategy_profile
38
+ gs
39
+ end
40
+
41
+ # Regular training game -- generic strictly dominated
42
+ #
43
+ # Employer: | Task Specific | Generic
44
+ # You: -----------------|---------------------|------------------
45
+ # | |
46
+ # Deny Training | (-2, 0) | (-2, -1)
47
+ # ------------------------|---------------------|------------------
48
+ # Accept Training | (1, 4) | (5, -2)
49
+ # ------------------------|---------------------|------------------
50
+ before(:each) do
51
+ @strategies = Strategy.new [{name: "Accept Training"}, {name: "Generic Training"},{name: "Task Specific Training"},{name: "Deny Training"}]
52
+ @accept = @strategies.find{|x| x[:name] == "Accept Training"}
53
+ @generic = @strategies.find{|x| x[:name] == "Generic Training"}
54
+ @task = @strategies.find{|x| x[:name] == "Task Specific Training"}
55
+ @deny = @strategies.find{|x| x[:name] == "Deny Training"}
56
+ @employer = Player.new name: "IBM"
57
+ @employee = Player.new name: "John Smith"
58
+
59
+ @strategy_profile = StrategyProfile.new
60
+ @strategy_profile << {id: 1, strategy: @generic, payoff: -2, player: @employer}
61
+ @strategy_profile << {id: 1, strategy: @accept, payoff: 5, player: @employee}
62
+
63
+ @strategy_profile << {id: 2, strategy: @generic, payoff: -1, player: @employer}
64
+ @strategy_profile << {id: 2, strategy: @deny, payoff: -2, player: @employee}
65
+
66
+ @strategy_profile << {id: 3, strategy: @task, payoff: 0, player: @employer}
67
+ @strategy_profile << {id: 3, strategy: @deny, payoff: -2, player: @employee}
68
+
69
+ @strategy_profile << {id: 4, strategy: @task, payoff: 4, player: @employer}
70
+ @strategy_profile << {id: 4, strategy: @accept, payoff: 1, player: @employee}
71
+ @gs = Game.new
72
+ @gs.strategy_profiles = @strategy_profile
73
+ end
74
+
75
+ it ".strategies should allow assignment of strategies" do
76
+ @gs.strategy_profiles.count.should == 8
77
+ end
78
+
79
+ it ".payoff should return the payoff for a strategy and player" do
80
+ @gs.payoff(@generic, @employer).should == -2
81
+ end
82
+
83
+
84
+ it '.players should return a list of players' do
85
+ @gs.players.count.should == 2
86
+ end
87
+
88
+ it '.player_names should return a list of player names' do
89
+ @gs.player_names.count.should == 2
90
+ end
91
+
92
+ it '.opposing_players should return a list of players who receive payouts for the passed in strategy profile' do
93
+ gen_strat_profile = @gs.strategy_profiles.select{|x| x[:strategy][:name] == "Generic Training"}.first
94
+ @gs.opposing_players(gen_strat_profile).count.should == 1
95
+ end
96
+
97
+ it '.player_strategy_profiles should return a list of strategy profiles for the players' do
98
+ @gs.player_strategy_profiles(@employer).count.should == 4
99
+ end
100
+
101
+ it '.complementary_moves? should return a list of strategy profiles for a player other than the passed in profile' do
102
+ gen_strat_profile = @gs.strategy_profiles.select{|x| x[:strategy][:name] == @generic[:name]}.first
103
+ @gs.complementary_moves(gen_strat_profile).count.should == 1
104
+ @gs.complementary_moves(gen_strat_profile).first[:strategy][:name].should == @task[:name]
105
+ end
106
+
107
+ it '.opposing_player_strategy_profile should return the name of the opposing players strategy for the passed in profile' do
108
+ gen_strat_profile = @gs.strategy_profiles.select{|x| x[:strategy][:name] == @generic[:name]}.first
109
+ @gs.opposing_player_strategy_profile(gen_strat_profile)[:strategy][:name].should == @accept[:name]
110
+ end
111
+
112
+ it '.better_payoffs? should return a list of strategy profiles that are better than the passed in profile for the passed in player' do
113
+ gen_strat_profile = @gs.strategy_profiles.select{|x| x[:strategy][:name] == @generic[:name]}.first
114
+ #@gs.better_moves?(gen_strat_profile).first[:strategy][:name].should == @task[:name]
115
+ @gs.better_payoffs?(gen_strat_profile).first[:strategy][:name].should == @task[:name]
116
+ end
117
+
118
+ # should return this
119
+ # Employer: | Task Specific | Generic
120
+ # You: -----------------|---------------------|------------------
121
+ # | get all alternates | Pass in this
122
+ # Deny Training | ( , 0) | (-2, )
123
+ # ------------------------|---------------------|------------------
124
+ # Accept Training | | (5, )
125
+ # ------------------------|---------------------|------------------
126
+ it '.worse_payoffs? should return a list of strategy profiles that are worse than the passed in profile for the passed in player'do
127
+ gen_strat_profile = @gs.strategy_profiles.select{|x| x[:strategy][:name] == @accept[:name]}.first
128
+ @gs.worse_payoffs?(gen_strat_profile).should_not be_nil
129
+ @gs.worse_payoffs?(gen_strat_profile).should_not be_empty
130
+ @gs.worse_payoffs?(gen_strat_profile)[0][:payoff].should == -2
131
+ end
132
+
133
+ # Employer: | Task Specific | Generic
134
+ # You: -----------------|---------------------|------------------
135
+ # | |
136
+ # Deny Training | (-2, -1) | (-2, -1)
137
+ # ------------------------|---------------------|------------------
138
+ # Accept Training | (1, 4) | (5, -2)
139
+ # ------------------------|---------------------|------------------
140
+ it '.better_or_equal_moves? should return a list of strategy profiles that are better than the passed in profile for the passed in player' do
141
+ gs = game_with_weakly_dominated_strategies
142
+ # gets the generic strategy vs the deny training profile
143
+ gen_strat_profile = gs.strategy_profiles.select{|x| x[:strategy][:name] == @generic[:name]}[1]
144
+ gs.better_payoffs?(gen_strat_profile).count.should == 0
145
+ gs.better_or_equal_payoffs?(gen_strat_profile).count.should == 1
146
+ gs.better_or_equal_payoffs?(gen_strat_profile).first[:strategy][:name].should == @task[:name]
147
+ end
148
+
149
+ it ".strictly_dominated_list should return a list of strictly dominated strategies" do
150
+ # generic training and deny training are strictly dominated
151
+ @gs.strictly_dominated_list.count.should == 2
152
+ @gs.strictly_dominated_list.select{|x| x[:name] == @generic[:name]}.count.should > 0
153
+ @gs.strictly_dominated_list.select{|x| x[:name] == @deny[:name]}.count.should > 0
154
+ end
155
+
156
+ # Employer: | Task Specific | Generic
157
+ # You: -----------------|---------------------|------------------
158
+ # | |
159
+ # Deny Training | (-2, -1) | (-2, -1)
160
+ # ------------------------|---------------------|------------------
161
+ # Accept Training | (1, 4) | (5, -2)
162
+ # ------------------------|---------------------|------------------
163
+ it ".equal_moves should return a list of moves for a matchup that are equal in payoffs" do
164
+ # in the above game generic training is weakly dominated
165
+ gs = game_with_weakly_dominated_strategies
166
+ gen_strat_profiles = gs.strategy_profiles.select do |x|
167
+ x[:strategy][:name] == @generic[:name] &&
168
+ x[:payoff] == -1
169
+ end
170
+ gen_strat_profile = gen_strat_profiles.first
171
+ gs.equal_moves(gen_strat_profile).count.should == 1
172
+ gs.equal_moves(gen_strat_profile).first[:payoff].should == -1
173
+ end
174
+
175
+ # Employer: | Task Specific | Generic
176
+ # You: -----------------|---------------------|------------------
177
+ # | |
178
+ # Deny Training | (-2, -1) | (-2, -1)
179
+ # ------------------------|---------------------|------------------
180
+ # Accept Training | (1, 4) | (5, -2)
181
+ # ------------------------|---------------------|------------------
182
+ it ".all_other_moves should return a list of moves for a matchup that are equal in payoffs" do
183
+ # in the above game generic training is weakly dominated
184
+ gs = game_with_weakly_dominated_strategies
185
+ gen_strat_profiles = gs.strategy_profiles.select do |x|
186
+ x[:strategy][:name] == @generic[:name] &&
187
+ x[:payoff] == -1
188
+ end
189
+ gen_strat_profile = gen_strat_profiles.first
190
+ gs.equal_moves(gen_strat_profile).count.should == 1
191
+ gs.equal_moves(gen_strat_profile).first[:payoff].should == -1
192
+ end
193
+
194
+ # Employer: | Task Specific | Generic
195
+ # You: -----------------|---------------------|------------------
196
+ # | |
197
+ # Deny Training | (-2, -1) | (-2, -1)
198
+ # ------------------------|---------------------|------------------
199
+ # Accept Training | (1, 4) | (5, -2)
200
+ # ------------------------|---------------------|------------------
201
+ it ".weakly_dominated_list should return a list of weakly dominated strategies" do
202
+ # in the above game generic training is weakly dominated
203
+ gs = game_with_weakly_dominated_strategies
204
+ # generic should not be strictly but rather weakly dominated
205
+ gs.strictly_dominated_list.count.should == 1
206
+ gs.weakly_dominated_list.count.should == 1
207
+ gs.weakly_dominated_list.select{|x| x[:name] == @generic[:name]}.count.should > 0
208
+ end
209
+ it ".weakly_dominated_list should not return ant strictly dominated strategies" do
210
+ # in the above game generic training is weakly dominated
211
+ gs = game_with_weakly_dominated_strategies
212
+ # generic should not be strictly but rather weakly dominated
213
+ gs.strictly_dominated_list.count.should == 1
214
+ gs.weakly_dominated_list.count.should == 1
215
+ gs.weakly_dominated_list.select{|x| x[:name] == @generic[:name]}.count.should > 0
216
+ gs.weakly_dominated_list.select{|x| x[:name] == @deny[:name]}.count.should == 0
217
+ end
218
+
219
+ # Employer: | Task Specific | Generic
220
+ # You: -----------------|---------------------|------------------
221
+ # | |
222
+ # Deny Training | (-2, -1) | (-2, -1)
223
+ # ------------------------|---------------------|------------------
224
+ # Accept Training | (1, 4) | (5, -2)
225
+ # ------------------------|---------------------|------------------
226
+ it ".valid_deviation? should not be nil if the strategy and the deviation belongs to the same player" do
227
+ gs = game_with_weakly_dominated_strategies
228
+ gs.valid_deviation?(@deny, @accept).should_not be_nil
229
+ end
230
+
231
+ it ".valid_deviation? should not be nil if the strategy and the deviation belongs to the same player" do
232
+ gs = game_with_weakly_dominated_strategies
233
+ gs.valid_deviation?(@deny, @generic).should == nil
234
+ end
235
+
236
+ # Employer: | Task Specific | Generic
237
+ # You: -----------------|---------------------|------------------
238
+ # | |
239
+ # Deny Training | (-2, -1) | (-2, -1)
240
+ # ------------------------|---------------------|------------------
241
+ # Accept Training | (1, 4) | (5, -2)
242
+ # ------------------------|---------------------|------------------
243
+ it ".compare_deviating_strategy should return a list of weakly dominated strategies" do
244
+ # in the above game generic training is weakly dominated
245
+ gs = game_with_weakly_dominated_strategies
246
+ gs.compare_deviating_strategy(@deny, @accept).should == :strictly_dominated
247
+ end
248
+
249
+ it ".deviating_strategies should return a list of deviations" do
250
+ gen_strat_payoff = @gs.strategy_profiles.detect{|x| x[:strategy][:name] == @generic[:name]}
251
+ task_strat_payoff = @gs.strategy_profiles.detect{|x| x[:strategy][:name] == @task[:name]}
252
+ @gs.deviating_strategies(gen_strat_payoff).include?(gen_strat_payoff[:strategy]).should == false
253
+ @gs.deviating_strategies(gen_strat_payoff).include?(task_strat_payoff[:strategy]).should == true
254
+ end
255
+
256
+ it ".player_from_strategy should get the player for a particular strategy" do
257
+ @gs.player_from_strategy(@accept).should eq @employee
258
+ end
259
+
260
+ it ".best_response should be the action of a player that is best for him given his beliefs about the other's action" do
261
+ task_strat_payoff = @gs.strategy_profiles.detect{|x| x[:strategy][:name] == @task[:name]}
262
+ accept_strat_payoff = @gs.strategy_profiles.detect{|x| x[:strategy][:name] == @accept[:name]}
263
+ @gs.best_response_against(task_strat_payoff)[:strategy][:name].should == accept_strat_payoff[:strategy][:name]
264
+
265
+ end
266
+
267
+ it ".player_enum should get a list of player enumerators" do
268
+ @gs.player_enum.include?(@employer).should == true
269
+ end
270
+
271
+ it ".strategies_by_player should get a list of strategies by player" do
272
+ @gs.strategies_by_player(@employee).include?(@accept).should == true
273
+ end
274
+
275
+ it ".nash should return a list of strategy profiles that are nash equilibriums" do
276
+ @gs.nash.include?([@accept[:name],@task[:name]]).should == true
277
+ end
278
+
279
+
280
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Player do
4
+ it "should check for an required keys when initializing" do
5
+ players=Player.new
6
+ expect {
7
+ players << {notname: "test1", description: "test2"}
8
+ }.to raise_error(RuntimeError,/Name required/)
9
+ end
10
+
11
+ it "should allow and insert when name and description are present" do
12
+ players=Player.new
13
+ expect {
14
+ players << {name: "test1", description: "test2"}
15
+ players << {name: "test3", description: "test4"}
16
+ }.to_not raise_error
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe StrategyProfile do
4
+ #
5
+ # Employer: | Task Specific | Generic
6
+ # You: -----------------|---------------------|------------------
7
+ # | |
8
+ # Deny Training | (-2, 0) | (-2, -1)
9
+ # ------------------------|---------------------|------------------
10
+ # Accept Training | (1, 4) | (5, -2)
11
+ # ------------------------|---------------------|------------------
12
+ before (:each) do
13
+ @strategies = Strategy.new [{name: "Accept Training"}, {name: "Generic Training"},{name: "Task Specific Training"},{name: "Deny Training"}]
14
+ @accept = @strategies.find{|x| x[:name] == "Accept Training"}
15
+ @generic = @strategies.find{|x| x[:name] == "Generic Training"}
16
+ @task_specific = @strategies.find{|x| x[:name] == "Task Specific Training"}
17
+ @deny = @strategies.find{|x| x[:name] == "Deny Training"}
18
+ @employer = Player.new name: "John Smith"
19
+ @employee = Player.new name: "John Smith"
20
+ end
21
+ # hash of stategy, matchup, player, payoff
22
+ it "should collect matchups" do
23
+ @strategy_profile = StrategyProfile.new
24
+ @strategy_profile << {id: 1, strategy: @accept, payoff: -2, player: @employer}
25
+ @strategy_profile << {id: 1, strategy: @generic, payoff: 5, player: @employee}
26
+ @strategy_profile.count.should == 2
27
+
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Strategy do
4
+
5
+ it "should check for an required keys when initializing" do
6
+ strategies=Strategy.new
7
+ expect {
8
+ strategies << {notname: "test1", description: "test2"}
9
+ }.to raise_error(RuntimeError,/Name required/)
10
+ end
11
+
12
+ it "should allow and insert when name and description are present" do
13
+ strategies=Strategy.new
14
+ expect {
15
+ strategies << {name: "test1", description: "test2"}
16
+ strategies << {name: "test3", description: "test4"}
17
+ }.to_not raise_error
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ #this file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ #require File.expand_path("../../config/environment", __FILE__)
4
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/minigame/array_of_hashes.rb')
5
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/minigame/strategy.rb')
6
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/minigame/strategy_profile.rb')
7
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/minigame/player.rb')
8
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/minigame/gameable.rb')
9
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/minigame/game.rb')
10
+ require 'rspec/autorun'
11
+
12
+ # Requires supporting ruby files with custom matchers and macros, etc,
13
+ # in spec/support/ and its subdirectories.
14
+ #Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
15
+
16
+ Dir["../app/models/*.rb"].each {|f| require_relative f}
17
+ RSpec.configure do |config|
18
+ # == Mock Framework
19
+ #
20
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
21
+ #
22
+ # config.mock_with :mocha
23
+ # config.mock_with :flexmock
24
+ # config.mock_with :rr
25
+ config.mock_with :rspec
26
+
27
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
28
+ #config.fixture_path = "#{::Rails.root}/spec/fixtures"
29
+
30
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
31
+ # examples within a transaction, remove the following line or assign false
32
+ # instead of true.
33
+ # next line doesn't work with database cleaner
34
+ #config.use_transactional_fixtures = true
35
+
36
+ # If true, the base class of anonymous controllers will be inferred
37
+ # automatically. This will be the default behavior in future versions of
38
+ # rspec-rails.
39
+ #config.infer_base_class_for_anonymous_controllers = false
40
+ #config.include FactoryGirl::Syntax::Methods
41
+
42
+ #config.before(:suite) do
43
+ # DatabaseCleaner.strategy = :transaction
44
+ # DatabaseCleaner.clean_with(:truncation)
45
+ #end
46
+ #config.before(:each) do
47
+ # DatabaseCleaner.start
48
+ #end
49
+
50
+ #config.after(:each) do
51
+ # DatabaseCleaner.clean
52
+ #end
53
+
54
+ end
55
+
@@ -1,8 +1,8 @@
1
1
  require 'minigame'
2
2
  require 'minigame/player'
3
- require 'debugger'
4
3
  require 'minitest/autorun'
5
4
  require 'minitest/unit'
5
+ #require 'debugger'
6
6
 
7
7
  class MiniGameTest < Minitest::Test
8
8
  class Game
@@ -94,8 +94,8 @@ class MiniGameTest < Minitest::Test
94
94
 
95
95
  def test_weakly_dominated_list
96
96
  game = Game.new
97
- game.strategy_profiles = new_profiles
98
- assert_equal [{:name=>"Generic Training"}, {:name=>"Deny Training"}], game.weakly_dominated_list
97
+ game.strategy_profiles = new_weak_profiles
98
+ assert_equal [{:name=>"Generic Training"}], game.weakly_dominated_list
99
99
  end
100
100
 
101
101
  def test_nash
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minigame
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
- - Wavell Watson
7
+ - W Watson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-13 00:00:00.000000000 Z
11
+ date: 2013-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,15 +52,30 @@ dependencies:
52
52
  - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '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'
55
69
  description: A game theory library
56
70
  email:
57
- - wavell.watson@gmail.com
71
+ - me@wwatson.me
58
72
  executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - .gitignore
63
77
  - .rvmrc
78
+ - .travis.yml
64
79
  - Gemfile
65
80
  - Gemfile.lock
66
81
  - LICENSE.txt
@@ -70,14 +85,20 @@ files:
70
85
  - lib/minigame/array_of_hashes.rb
71
86
  - lib/minigame/game.rb
72
87
  - lib/minigame/gameable.rb
73
- - lib/minigame/payoff.rb
74
88
  - lib/minigame/player.rb
75
89
  - lib/minigame/strategy.rb
76
90
  - lib/minigame/strategy_profile.rb
77
91
  - lib/minigame/version.rb
78
92
  - minigame.gemspec
93
+ - spec/models/array_of_hashes_spec.rb
94
+ - spec/models/gameable_spec.rb
95
+ - spec/models/games_spec.rb
96
+ - spec/models/player_spec.rb
97
+ - spec/models/strategy_profile_spec.rb
98
+ - spec/models/strategy_spec.rb
99
+ - spec/spec_helper.rb
79
100
  - test/test_minigame.rb
80
- homepage: ''
101
+ homepage: https://github.com/wavell/minigame
81
102
  licenses:
82
103
  - MIT
83
104
  metadata: {}
@@ -102,4 +123,11 @@ signing_key:
102
123
  specification_version: 4
103
124
  summary: A minimalistic game theory library that computes nash equilibrium
104
125
  test_files:
126
+ - spec/models/array_of_hashes_spec.rb
127
+ - spec/models/gameable_spec.rb
128
+ - spec/models/games_spec.rb
129
+ - spec/models/player_spec.rb
130
+ - spec/models/strategy_profile_spec.rb
131
+ - spec/models/strategy_spec.rb
132
+ - spec/spec_helper.rb
105
133
  - test/test_minigame.rb
@@ -1,12 +0,0 @@
1
- require 'data_mapper'
2
- #class Payoff < ActiveRecord::Base
3
- # belongs_to :player
4
- # belongs_to :matchup
5
- # attr_accessible :payoff
6
- #end
7
- class Payoff
8
- include DataMapper::Resource
9
- belongs_to :player
10
- belongs_to :matchup
11
- #attr_accessible :payoff
12
- end