answer-factory 0.0.15 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.15
1
+ 0.1.1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{answer-factory}
8
- s.version = "0.0.15"
8
+ s.version = "0.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bill Tozier", "Trek Glowacki", "Jesse Sielaff"]
12
- s.date = %q{2010-05-10}
12
+ s.date = %q{2010-05-11}
13
13
  s.default_executable = %q{answer-factory}
14
14
  s.description = %q{The pragmaticgp gem provides a simple framework for building, running and managing genetic programming experiments which automatically discover algorithms and equations to solve user-defined problems.}
15
15
  s.email = %q{bill@vagueinnovation.com}
@@ -42,7 +42,7 @@ Gem::Specification.new do |s|
42
42
  "spec/batch_spec.rb",
43
43
  "spec/factories/factory_spec.rb",
44
44
  "spec/factories/workstation_spec.rb",
45
- "spec/integration_specs/couch_db_integration.rb",
45
+ "spec/integration_specs/couch_db_integration.rspec",
46
46
  "spec/machines/any_one_spec.rb",
47
47
  "spec/machines/build_random_spec.rb",
48
48
  "spec/machines/evaluate_simple_score_spec.rb",
@@ -65,7 +65,6 @@ Gem::Specification.new do |s|
65
65
  "spec/batch_spec.rb",
66
66
  "spec/factories/factory_spec.rb",
67
67
  "spec/factories/workstation_spec.rb",
68
- "spec/integration_specs/couch_db_integration.rb",
69
68
  "spec/machines/any_one_spec.rb",
70
69
  "spec/machines/build_random_spec.rb",
71
70
  "spec/machines/evaluate_simple_score_spec.rb",
@@ -2,7 +2,7 @@ require 'set'
2
2
 
3
3
  module AnswerFactory
4
4
  class Answer
5
- attr_accessor :scores, :tags
5
+ attr_accessor :scores, :tags, :location
6
6
  attr_reader :draft_blueprint, :program, :timestamp, :ancestors
7
7
  attr_reader :initialization_options, :progress
8
8
  attr_accessor :couch_id, :couch_rev
@@ -19,6 +19,7 @@ module AnswerFactory
19
19
  end
20
20
  @timestamp = Time.now
21
21
  @couch_id = options[:couch_id] || ""
22
+ @location = options[:location] || :NOWHERE
22
23
  @couch_rev = options[:couch_rev] || ""
23
24
  @progress = options[:progress] || 0
24
25
  @ancestors = options[:ancestors] || []
@@ -112,6 +113,12 @@ module AnswerFactory
112
113
  end
113
114
  end
114
115
 
116
+ def move_to(where)
117
+ raise ArgumentError, "#{where} is not a Symbol" unless where.kind_of?(Symbol)
118
+ @location = where.to_sym
119
+ self
120
+ end
121
+
115
122
 
116
123
  def add_tag(new_tag)
117
124
  raise ArgumentError, "#{new_tag} is not a Symbol" unless new_tag.kind_of?(Symbol)
@@ -130,6 +137,7 @@ module AnswerFactory
130
137
  basics["_rev"] = self.couch_rev unless self.couch_rev.empty?
131
138
 
132
139
  basics.merge!({'blueprint' => self.blueprint,
140
+ 'location' => self.location.to_sym,
133
141
  'tags' => self.tags.to_a,
134
142
  'scores' => self.scores,
135
143
  'progress' => self.progress,
@@ -144,8 +152,9 @@ module AnswerFactory
144
152
  symbolized_scores = value_hash["scores"].inject({}) {|memo,(k,v)| memo[k.to_sym] = v; memo }
145
153
 
146
154
  Answer.new(value_hash["blueprint"],
147
- couch_id:value_hash['id'],
148
- couch_rev:value_hash['rev'],
155
+ couch_id:value_hash['_id'],
156
+ couch_rev:value_hash['_rev'],
157
+ location:(value_hash["location"] || "NOWHERE").to_sym,
149
158
  tags:tag_set,
150
159
  scores:symbolized_scores,
151
160
  progress:value_hash["progress"],
data/lib/answers/batch.rb CHANGED
@@ -54,6 +54,7 @@ module AnswerFactory
54
54
  end
55
55
  rescue JSON::ParserError => e
56
56
  puts "Batch not read due to JSON ParserError: '#{e.message}'"
57
+ # raise e
57
58
  end
58
59
  return batch
59
60
  end
@@ -63,6 +63,5 @@ module AnswerFactory
63
63
  rescue StandardError
64
64
  false
65
65
  end
66
-
67
66
  end
68
67
  end
@@ -58,10 +58,17 @@ module AnswerFactory
58
58
  end
59
59
 
60
60
 
61
- def ship_to(where, &filter)
61
+ def ship_to(where)
62
62
  raise ArgumentError, "Workstation#ship_to cannot ship to a #{where.class}" unless
63
63
  where.kind_of?(Symbol)
64
- (@answers.find_all &filter).each {|a| a.add_tag where; a.remove_tag @name}
64
+
65
+ @answers.each do |a|
66
+ next unless a.location.to_sym == @name.to_sym
67
+ if block_given?
68
+ next unless yield(a)
69
+ end
70
+ a.move_to(where)
71
+ end
65
72
  end
66
73
 
67
74
 
@@ -72,11 +79,12 @@ module AnswerFactory
72
79
 
73
80
 
74
81
  def scrap_if(why, &filter)
75
- (@answers.find_all &filter).each {|a| a.add_tag :SCRAP; a.remove_tag @name}
82
+ ship_to(:SCRAP, &filter)
83
+ # (@answers.find_all &filter).each {|a| a.add_tag :SCRAP; a.remove_tag @name}
76
84
  end
77
85
 
78
86
  def scrap_everything
79
- scrap_if("everything dies") {|x| true}
87
+ ship_to(:SCRAP)
80
88
  end
81
89
 
82
90
 
data/spec/answer_spec.rb CHANGED
@@ -57,6 +57,30 @@ describe "Answer" do
57
57
  Answer.new("foo").scores.should == {}
58
58
  end
59
59
 
60
+ it "should have a tags attribute" do
61
+ Answer.new("").should respond_to(:tags)
62
+ end
63
+
64
+ it "should be possible to set the :tags via initialization option" do
65
+ Answer.new("", tags:["hi"]).tags.to_a.should == ["hi"]
66
+ end
67
+
68
+ it "should not report duplicate entries" do
69
+ Answer.new("", tags:["hi", "hi"]).tags.to_a.should == ["hi"]
70
+ end
71
+
72
+ it "should have a :location attribute" do
73
+ Answer.new("").should respond_to(:location)
74
+ end
75
+
76
+ it "should have a default :location of :NOWHERE" do
77
+ Answer.new("").location.should == :NOWHERE
78
+ end
79
+
80
+ it "be possible to set :location via an initialization option" do
81
+ Answer.new("", location:"nearby").location.should == "nearby"
82
+ end
83
+
60
84
  it "should have a #timestamp, which is when (wall clock time) it was made" do
61
85
  tn = Time.now
62
86
  Time.should_receive(:now).and_return(tn)
@@ -78,7 +102,7 @@ describe "Answer" do
78
102
  describe "serialization" do
79
103
  describe "writing" do
80
104
  before(:each) do
81
- @a1 = Answer.new("block {do a}", progress:12)
105
+ @a1 = Answer.new("block {do a}", progress:12, location: :here)
82
106
  end
83
107
 
84
108
  it "should not contain the CouchDB _id, if none was set" do
@@ -99,11 +123,14 @@ describe "Answer" do
99
123
  @a1.data['_rev'].should == "88888"
100
124
  end
101
125
 
102
-
103
126
  it "should contain the blueprint" do
104
127
  @a1.data['blueprint'].should == @a1.blueprint
105
128
  end
106
129
 
130
+ it "should contain the location" do
131
+ @a1.data['location'].should == @a1.location
132
+ end
133
+
107
134
  it "should contain the tags" do
108
135
  @a1.data['tags'].should == @a1.tags.to_a
109
136
  end
@@ -125,7 +152,7 @@ describe "Answer" do
125
152
 
126
153
  describe "reading" do
127
154
  before(:each) do
128
- @couchified = {"id"=>"0f60c293ad736abfdb083d33f71ef9ab", "key"=>"ws1", "value"=>{"id"=>"0f60c293ad736abfdb083d33f71ef9ab", "rev"=>"1-473467b6dc1a4cba3498dd6eeb8e3206", "blueprint"=>"do bar", "tags"=>["quux", "whatevz"], "scores"=>{"badness" => 12.345}, "progress" => 12, "timestamp"=>"2010/04/14 17:09:14 +0000"}}
155
+ @couchified = {"id"=>"0f60c293ad736abfdb083d33f71ef9ab", "key"=>"ws1", "value"=>{"_id"=>"0f60c293ad736abfdb083d33f71ef9ab", "_rev"=>"1-473467b6dc1a4cba3498dd6eeb8e3206", "blueprint"=>"do bar", "location"=>"here","tags"=>["quux", "whatevz"], "scores"=>{"badness" => 12.345}, "progress" => 12, "timestamp"=>"2010/04/14 17:09:14 +0000"}}
129
156
  @my_a = Answer.from_serial_hash(@couchified)
130
157
  end
131
158
 
@@ -142,6 +169,10 @@ describe "Answer" do
142
169
  @my_a.blueprint.should == "do bar"
143
170
  end
144
171
 
172
+ it "should accumulate the :location" do
173
+ @my_a.location.should == :here
174
+ end
175
+
145
176
  it "should collect the tag Array into a Set of symbols" do
146
177
  @my_a.tags.should be_a_kind_of(Set)
147
178
  @my_a.tags.should include(:quux)
@@ -438,6 +469,20 @@ describe "Answer" do
438
469
  end
439
470
 
440
471
 
472
+ describe "locations" do
473
+ describe "move_to" do
474
+ it "should change the :location" do
475
+ a = Answer.new("do a", location: :dzz)
476
+ a.move_to(:zzd).location.should == :zzd
477
+ end
478
+
479
+ it "should raise an error if the argument isn't a Symbol" do
480
+ lambda{Answer.new("do a").move_to(99123)}.should raise_error(ArgumentError)
481
+ end
482
+ end
483
+ end
484
+
485
+
441
486
  describe "tags" do
442
487
  it "should have a tags array" do
443
488
  Answer.new("").tags.should be_a_kind_of(Set)
@@ -208,15 +208,20 @@ describe "Workstation" do
208
208
  describe "ship_to" do
209
209
  before(:each) do
210
210
  @w2 = Workstation.new(:lulu)
211
- @a1 = Answer.new("do fun_stuff", tags:[:lulu])
212
- @a2 = Answer.new("do sad_stuff", tags:[:lulu])
211
+ @a1 = Answer.new("do fun_stuff", location: :lulu)
212
+ @a2 = Answer.new("do sad_stuff", location: :lulu)
213
213
  @w2.answers = Batch[@a1,@a2]
214
214
  end
215
215
 
216
+
216
217
  it "should accept a single argument" do
217
218
  @w2.method(:ship_to).arity.should == 1
218
219
  end
219
220
 
221
+ it "should be comfortable without any block" do
222
+ @w2.ship_to(:here)
223
+ end
224
+
220
225
  it "should check the argument is a symbol" do
221
226
  lambda{@w2.ship_to(8)}.should raise_error(ArgumentError)
222
227
  lambda{@w2.ship_to(:heaven)}.should_not raise_error
@@ -227,25 +232,17 @@ describe "Workstation" do
227
232
  @w2.ship_to(:heaven) {|a| Math.sin(12.0)}
228
233
  end
229
234
 
230
- it "should add a new location tag to the answers in the filtered subset" do
231
- @a1.should_receive(:add_tag).with(:xyzzy)
232
- @a2.should_receive(:add_tag).with(:xyzzy)
233
- @w2.ship_to(:xyzzy) {|a| true}
234
- end
235
-
236
- it "should remove the old location tag to the answers in the filtered subset" do
237
- @a1.should_receive(:remove_tag).with(:lulu)
238
- @a2.should_receive(:remove_tag).with(:lulu)
235
+ it "should change the :location of the answers in the filtered subset" do
236
+ @a1.should_receive(:move_to).with(:xyzzy)
237
+ @a2.should_receive(:move_to).with(:xyzzy)
239
238
  @w2.ship_to(:xyzzy) {|a| true}
240
239
  end
241
240
 
242
- it "should not touch the tags of answers not in the filtered subset" do
243
- @a1.should_receive(:remove_tag).with(:lulu)
244
- @a2.should_not_receive(:remove_tag)
245
- @w2.ship_to(:xyzzy) {|a| a.blueprint.include? "fun"}
241
+ it "should only ship things that are still there" do
242
+ @a2.location = :far_away
243
+ @w2.ship_to(:other_place) {|a| true}
244
+ @a2.location.should == :far_away
246
245
  end
247
-
248
- it "should only ship things that are still there"
249
246
  end
250
247
  end
251
248
 
@@ -259,8 +256,8 @@ describe "Workstation" do
259
256
  describe "scrap_if" do
260
257
  before(:each) do
261
258
  @w3 = Workstation.new(:falafel)
262
- @a1 = Answer.new("do fun_stuff", progress:1, tags:[:falafel])
263
- @a2 = Answer.new("do sad_stuff", progress:99, tags:[:falafel])
259
+ @a1 = Answer.new("do fun_stuff", progress:1, location: :falafel)
260
+ @a2 = Answer.new("do sad_stuff", progress:99, location: :falafel)
264
261
  @w3.answers = Batch[@a1,@a2]
265
262
  end
266
263
 
@@ -273,32 +270,14 @@ describe "Workstation" do
273
270
  @w3.scrap_if("Math says so") {|a| Math.cos(12.0)}
274
271
  end
275
272
 
276
- it "should add a new location tag :SCRAP to the answers in the filtered subset" do
277
- @a1.should_receive(:add_tag).with(:SCRAP)
278
- @a2.should_receive(:add_tag).with(:SCRAP)
279
- @w3.scrap_if("everything dies") {|a| true}
280
- end
281
-
282
- it "should remove the old location tag to the answers in the filtered subset" do
283
- @a1.should_receive(:remove_tag).with(:falafel)
284
- @a2.should_receive(:remove_tag).with(:falafel)
285
- @w3.scrap_if("entropy") {|a| true}
286
- end
287
-
288
- it "should not touch the tags of answers not in the filtered subset" do
289
- @a1.should_receive(:remove_tag).with(:falafel)
290
- @a2.should_not_receive(:remove_tag)
291
- @w3.scrap_if("insufficient progress") {|a| a.progress < 10}
292
- end
293
-
294
273
  it "should not scrap things that aren't at that location"
295
274
  end
296
275
 
297
276
  describe "scrap_everything" do
298
277
  before(:each) do
299
278
  @w4 = Workstation.new(:ice_station_zebra)
300
- @a1 = Answer.new("do anything", tags:[:ice_station_zebra])
301
- @a2 = Answer.new("do whatevz", tags:[:ice_station_zebra])
279
+ @a1 = Answer.new("do anything", location: :ice_station_zebra)
280
+ @a2 = Answer.new("do whatevz", location: :ice_station_zebra)
302
281
  @w4.answers = Batch[@a1,@a2]
303
282
  end
304
283
 
@@ -307,20 +286,14 @@ describe "Workstation" do
307
286
  end
308
287
 
309
288
  it "should call scrap_if" do
310
- @w4.should_receive(:scrap_if)
289
+ @w4.should_receive(:ship_to)
311
290
  @w4.scrap_everything
312
291
  end
313
292
 
314
293
  it "should send every answer to :SCRAP" do
315
- @w4.answers.each {|a| a.tags.should_not include(:SCRAP)}
316
- @w4.scrap_everything
317
- @w4.answers.each {|a| a.tags.should include(:SCRAP)}
318
- end
319
-
320
- it "should remove the current location from every answer" do
321
- @w4.answers.each {|a| a.tags.should include(:ice_station_zebra)}
294
+ @w4.answers.each {|a| a.location.should_not == :SCRAP}
322
295
  @w4.scrap_everything
323
- @w4.answers.each {|a| a.tags.should_not include(:ice_station_zebra)}
296
+ @w4.answers.each {|a| a.location.should == :SCRAP}
324
297
  end
325
298
 
326
299
  it "should be safe to repeat the statement" do
@@ -0,0 +1,142 @@
1
+ require File.join(File.dirname(__FILE__), "./../spec_helper")
2
+
3
+ # CouchDB MUST BE RUNNING BEFORE YOU RUN THESE
4
+
5
+ class ShipperStation < Workstation
6
+ def receive!
7
+ gather_mine
8
+ end
9
+
10
+ def ship!
11
+ ship_to(:that_place) {|answer| true}
12
+ end
13
+ end
14
+
15
+
16
+ describe "CouchDB stuff" do
17
+ before(:each) do
18
+
19
+ configatron.factory.couchdb.server = "http://127.0.0.1:5984"
20
+ configatron.factory.couchdb.name = "integration_test_db"
21
+ break("CouchDB is offline") unless Factory.couch_available?
22
+ @db_uri = "#{configatron.factory.couchdb.server}/#{configatron.factory.couchdb.name}"
23
+ end
24
+
25
+ after(:all) do
26
+ CouchRest.database!(@db_uri).delete!
27
+ end
28
+
29
+
30
+ describe "Factory CouchDB interaction" do
31
+ it "should actually return 'true' if the db is reachable" do
32
+ Factory.couch_available?.should be true
33
+ end
34
+
35
+ it "should actually return 'false' if the db is unavailable" do
36
+ FakeWeb.allow_net_connect = false
37
+ Factory.couch_available?.should be false
38
+ FakeWeb.allow_net_connect = true
39
+ end
40
+
41
+ end
42
+
43
+ describe "Batch reading and writing" do
44
+ describe "updating a Batch" do
45
+ before(:each) do
46
+ @batch = Batch.[](Answer.new("do a"), Answer.new("do b"))
47
+ end
48
+
49
+ describe "Batch#bulk_save!" do
50
+ it "should capture the couch_id values in the Answers themselves" do
51
+ old_ids = @batch.collect {|a| a.couch_id}
52
+ @batch.bulk_save!(@db_uri)
53
+ new_ids = @batch.collect {|a| a.couch_id}
54
+ old_ids.should_not == new_ids
55
+ end
56
+
57
+ it "should capture the couch_rev values in the Answers themselves" do
58
+ @batch.bulk_save!(@db_uri)
59
+ new_revs = @batch.collect {|a| a.couch_rev}
60
+ new_revs.each {|r| r.should_not == ""}
61
+ end
62
+ end
63
+
64
+
65
+ it "should be possible to set the couchdb_id and have that be actually used" do
66
+ @batch[0].couch_id = "001"
67
+ @batch[1].couch_id = "002"
68
+ ids = @batch.bulk_save!(@db_uri).collect {|r| r["id"]}
69
+ ids.should == ["001", "002"]
70
+ end
71
+
72
+ it "should be possible to overwrite a document with new info" do
73
+ @batch.bulk_save!(@db_uri)
74
+
75
+ db = CouchRest.database!(@db_uri)
76
+ as_saved = db.get(@batch[0].couch_id)["_rev"]
77
+ @batch[0].scores[:wellness] = 0
78
+ @batch.bulk_save!(@db_uri)
79
+ and_now = db.get(@batch[0].couch_id)["_rev"]
80
+ as_saved[0].should == "1"
81
+ and_now[0].should == "2"
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+
88
+ describe "Workstations passing Batches around" do
89
+
90
+ describe "gathering" do
91
+ before(:each) do
92
+ @ws1 = ShipperStation.new(:this_place)
93
+ @batch = Batch.[](
94
+ Answer.new("do a", location: :this_place),
95
+ Answer.new("do b", location: :this_place),
96
+ Answer.new("do c", location: :elsewhere))
97
+ CouchRest.database!(@db_uri).
98
+ batch_save_doc({'_id' => "_design/this_place",
99
+ views: { current: { map:
100
+ "function(doc) { if(doc.location == 'this_place') { emit(doc._id, doc); } }"}}})
101
+ @batch.bulk_save!(@db_uri)
102
+ end
103
+
104
+ it "should gather the right ones" do
105
+ @ws1.receive!
106
+ @ws1.answers.length.should == 2
107
+ @ws1.answers.collect {|a| a.blueprint}.sort.should == ["do a", "do b"]
108
+ end
109
+
110
+ it "should capture the :_id and :_rev fields of the records" do
111
+ @ws1.receive!
112
+ @ws1.answers.each {|a| a.couch_id.should_not == ""}
113
+ @ws1.answers.each {|a| a.couch_rev.should_not == ""}
114
+ end
115
+ end
116
+
117
+
118
+ describe "shipping" do
119
+ before(:each) do
120
+ @ws1 = ShipperStation.new(:this_place)
121
+ @batch = Batch.[](
122
+ Answer.new("do a", location: :this_place),
123
+ Answer.new("do b", location: :this_place),
124
+ Answer.new("do c", location: :elsewhere))
125
+ CouchRest.database!(@db_uri).
126
+ batch_save_doc({'_id' => "_design/this_place",
127
+ views: { current: { map:
128
+ "function(doc) { if(doc.location == 'this_place') { emit(doc._id, doc); } }"}}})
129
+ @batch.bulk_save!(@db_uri)
130
+ end
131
+
132
+ it "should not be able to re-gather Answers it has shipped away" do
133
+ @ws1.cycle # load, ship, and save
134
+ @ws1.receive!
135
+ @ws1.answers.length.should == 0
136
+ end
137
+ end
138
+
139
+ end
140
+
141
+
142
+ end
@@ -23,6 +23,7 @@ class Setup_Factory < Thor::Group
23
23
  empty_directory("./lib/nudge/instructions")
24
24
  empty_directory("./lib/nudge/types")
25
25
  empty_directory("./lib/factory/machines")
26
+ empty_directory("./lib/factory/workstations")
26
27
  empty_directory("./spec")
27
28
  end
28
29
 
@@ -1,3 +1,4 @@
1
+ #encoding: utf-8
1
2
  require 'answer-factory'
2
3
  include Nudge
3
4
  include AnswerFactory
@@ -23,102 +24,102 @@ configatron.project.nudge.instructions.path = '/lib/nudge/instructions/*'
23
24
  configatron.project.nudge.types.path = '/lib/nudge/types/*'
24
25
 
25
26
 
26
-
27
27
  #### normally these should be in /lib/factory/workstations/**
28
28
 
29
- class GeneratorStation < Workstation
29
+ class GenerationStation < Workstation
30
30
  attr_reader :random_program_maker
31
31
 
32
32
  def initialize(name, options = {})
33
33
  super
34
34
  @random_program_maker = Machines::BuildRandom.new(
35
35
  how_many:10,
36
- target_size_in_points:7,
36
+ target_size_in_points:20,
37
37
  reference_names:["x1", "x2"])
38
38
  end
39
39
 
40
- def receive!
41
- gather_mine
42
- puts "#{self.name}: received and now have: #{@answers.length}"
43
- puts "\n\n#{self.name}: tags begin as #{(@answers.collect {|a| a.tags.to_a}).flatten}"
44
-
45
- end
46
-
47
40
  def build!
48
41
  @answers = process_with @random_program_maker
49
- puts "#{self.name}: built and now have: #{@answers.length}"
42
+ @answers.each {|a| a.location = :maker}
43
+ puts
44
+ puts "MAKER BUILD: made #{@answers.length}"
50
45
  end
51
46
 
52
47
  def ship!
53
- ship_to(:breeder) {|answer| true}
54
- puts "#{self.name}: shipping to #{@answers.collect {|a| a.tags.to_a}.inspect}"
48
+ ship_to(:polisher) {|answer| true}
49
+ puts "MAKER SHIP -> POLISHER"
55
50
  end
56
51
  end
57
52
 
58
53
 
59
- class EvaluatorStation1 < Workstation
54
+ class VariationStation < Workstation
60
55
  attr_reader :my_length_evaluator
61
56
 
62
57
  def initialize(name, options = {})
63
58
  super
64
- @my_length_evaluator = Machines::EvaluateSimpleScore.new(
65
- :name => :blueprint_length,
66
- scorer:Proc.new {|a| a.blueprint.length})
59
+ @mutator = Machines::MutateFootnotesUniform.new(
60
+ )
61
+ @score_1 = Machines::EvaluateSimpleScore.new(
62
+ :name => :number_of_footnotes,
63
+ scorer:Proc.new {|a| a.blueprint.scan(/^«/).length})
67
64
  end
68
65
 
69
66
  def receive!
70
67
  gather_mine
71
- puts "#{self.name}: received and now have: #{@answers.length}"
72
- puts "\n\n#{self.name}: tags begin as #{(@answers.collect {|a| a.tags.to_a}).flatten}"
68
+ puts "POLISHER RECEIVE: got #{@answers.length}"
73
69
  end
74
70
 
75
71
  def build!
76
- @answers = process_with @my_length_evaluator
77
- puts "#{self.name}: built and now have: #{@answers.length}"
72
+ @mutants = process_with @mutator
73
+ @mutants.each {|a| @answers << a}
74
+ @answers = process_with @score_1
75
+ puts "POLISHER BUILD: has #{@answers.length}"
78
76
  end
79
77
 
80
78
  def ship!
81
- ship_to(:marker) {|answer| rand < 0.5}
82
- puts "#{self.name}: shipping to #{@answers.collect {|a| a.tags.to_a}.inspect}"
79
+ ship_to(:picker) {|answer| true}
83
80
  end
84
81
 
85
82
  def scrap!
86
- puts "\n\n#{self.name}: tags begin as #{(@answers.collect {|a| a.tags.to_a}).flatten}"
87
- @best_score = (@answers.collect {|a| a.scores[:blueprint_length]}).min
88
- scrap_if("too_long") {|a| (a.scores[:blueprint_length] > @best_score)}
89
- puts "#{self.name}: tags ended as #{(@answers.collect {|a| a.tags.to_a})}"
90
- puts "#{self.name}: scores ended as #{(@answers.collect {|a| a.scores.values})}\n\n"
83
+ best_score = (@answers.collect {|a| a.scores[:number_of_footnotes]}).min
84
+ worst_score = (@answers.collect {|a| a.scores[:number_of_footnotes]}).max
85
+ puts "#{worst_score}..#{best_score}"
86
+ scrap_if("too many footnotes") {|a| a.scores[:number_of_footnotes] >
87
+ ((worst_score - best_score)/2.0 + best_score)}
88
+ puts "PICKER SCRAP: kept #{@answers.find_all {|a| a.location == :polisher}.length}"
91
89
  end
92
90
  end
93
91
 
94
92
 
95
- class EvaluatorStation2 < Workstation
96
- attr_reader :my_length_evaluator
93
+ class ScreeningStation < Workstation
94
+ attr_reader :letters
97
95
 
98
96
  def initialize(name, options = {})
99
97
  super
100
- @my_length_evaluator = Machines::EvaluateSimpleScore.new(
101
- :name => :points,
102
- scorer:Proc.new {|a| a.blueprint.points})
98
+ @letters = Machines::EvaluateSimpleScore.new(
99
+ :name => :letters,
100
+ scorer:Proc.new {|a| a.blueprint.length})
101
+ @so_far_so_good = Machines::SelectNondominated.new
103
102
  end
104
103
 
105
104
  def receive!
106
105
  gather_mine
107
- puts "#{self.name}: received and now have: #{@answers.length}"
108
- puts "\n\n#{self.name}: tags begin as #{(@answers.collect {|a| a.tags.to_a}).flatten}"
106
+ puts "PICKER RECEIVE: got #{@answers.length}"
109
107
  end
110
108
 
111
109
  def build!
112
- @answers = process_with @my_length_evaluator
113
- puts "#{self.name}: built and now have: #{@answers.length}"
110
+ @answers = process_with @letters
111
+ @best = process_with @so_far_so_good
112
+ puts "PICKER EVERYTHING: #{@answers.length}"
113
+ @answers.each {|a| puts a.scores}
114
+ puts "----------"
115
+ puts "PICKER NONDOMINATED SET: #{@best.length}"
116
+ @best.each {|a| puts a.scores}
117
+
114
118
  end
115
119
 
116
120
  def scrap!
117
- puts "\n\n#{self.name}: tags begin as #{(@answers.collect {|a| a.tags.to_a}).flatten}"
118
- @best_score = (@answers.collect {|a| a.scores[:points]}).min
119
- scrap_if("too_long") {|a| (a.scores[:points] > @best_score)}
120
- puts "#{self.name}: tags ended as #{(@answers.collect {|a| a.tags.to_a}).flatten}"
121
- puts "#{self.name}: scores ended as #{(@answers.collect {|a| a.scores.values}).flatten}\n\n"
121
+ scrap_if("dominated") {|a| !@best.include?(a)}
122
+ puts "PICKER SCRAP: kept #{@answers.find_all {|a| a.location == :picker}.length}"
122
123
  end
123
124
  end
124
125
 
@@ -141,30 +142,43 @@ raise "CouchDB not available at #{configatron.factory.couchdb.server}" unless
141
142
  # extend Workstation
142
143
  Dir.glob(File.dirname(__FILE__) + configatron.project.workstations.path) {|file| require file}
143
144
 
145
+
146
+ ### these should get tucked away elsewhere:
147
+
144
148
  project = Factory.new()
145
- workstations = [GeneratorStation.new(:maker),EvaluatorStation1.new(:breeder)]
146
- # GeneratorStation.new(:maker)],
147
- # EvaluatorStation1.new(:breeder),
148
- # EvaluatorStation2.new(:marker)]
149
+ workstations =[
150
+ GenerationStation.new(:maker),
151
+ VariationStation.new(:polisher),
152
+ ScreeningStation.new(:picker)]
149
153
 
150
- # write view document(s)
154
+ # reset database
151
155
  db = CouchRest.database!("#{configatron.factory.couchdb.server}/#{configatron.factory.name}")
152
156
  db.delete!
153
157
  db.create!
154
158
 
155
- db.batch_save_doc({'_id' => "_design/marker", views: { current: { map: "function(doc) { if(doc.tags.length > 0) { for(var idx in doc.tags) { if(doc.tags[idx] == 'marker') {emit(doc._id, doc) }}}}"}}})
156
159
 
157
- db.batch_save_doc({'_id' => "_design/breeder", views: { current: { map: "function(doc) { if(doc.tags.length > 0) { for(var idx in doc.tags) { if(doc.tags[idx] == 'breeder') {emit(doc._id, doc) }}}}"}}})
160
+ # create required view document(s) [should be part of generating each workstation]
161
+ db.batch_save_doc({'_id' => "_design/maker", views: { current: { map: "function(doc) {
162
+ if(doc.location == 'maker') {
163
+ emit(doc._id, doc);
164
+ }
165
+ }"}}})
158
166
 
159
- db.batch_save_doc({'_id' => "_design/maker", views: { current: { map: "function(doc) { if(doc.tags.length > 0) { for(var idx in doc.tags) { if(doc.tags[idx] == 'maker') {emit(doc._id, doc) }}}}"}}})
167
+ db.batch_save_doc({'_id' => "_design/polisher", views: { current: { map: "function(doc) {
168
+ if(doc.location == 'polisher') {
169
+ emit(doc._id, doc);
170
+ }
171
+ }"}}})
160
172
 
173
+ db.batch_save_doc({'_id' => "_design/picker", views: { current: { map: "function(doc) {
174
+ if(doc.location == 'picker') {
175
+ emit(doc._id, doc);
176
+ }
177
+ }"}}})
161
178
 
162
- test = {"_id" => "test_doc", "wild" => "and random"}
163
- db.save_doc(test)
164
- test["foo" => "bar"]
165
- db.save_doc(test)
166
179
 
167
- 5.times do
180
+ # final workcycle behavior
181
+ 100.times do
168
182
  workstations.each do |ws|
169
183
  ws.cycle
170
184
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
- - 15
9
- version: 0.0.15
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bill Tozier
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-05-10 00:00:00 -04:00
19
+ date: 2010-05-11 00:00:00 -04:00
20
20
  default_executable: answer-factory
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -146,7 +146,7 @@ files:
146
146
  - spec/batch_spec.rb
147
147
  - spec/factories/factory_spec.rb
148
148
  - spec/factories/workstation_spec.rb
149
- - spec/integration_specs/couch_db_integration.rb
149
+ - spec/integration_specs/couch_db_integration.rspec
150
150
  - spec/machines/any_one_spec.rb
151
151
  - spec/machines/build_random_spec.rb
152
152
  - spec/machines/evaluate_simple_score_spec.rb
@@ -194,7 +194,6 @@ test_files:
194
194
  - spec/batch_spec.rb
195
195
  - spec/factories/factory_spec.rb
196
196
  - spec/factories/workstation_spec.rb
197
- - spec/integration_specs/couch_db_integration.rb
198
197
  - spec/machines/any_one_spec.rb
199
198
  - spec/machines/build_random_spec.rb
200
199
  - spec/machines/evaluate_simple_score_spec.rb
@@ -1,60 +0,0 @@
1
- require File.join(File.dirname(__FILE__), "./../spec_helper")
2
-
3
- # CouchDB MUST BE RUNNING BEFORE YOU RUN THESE
4
-
5
-
6
- describe "CouchDB stuff" do
7
- before(:each) do
8
- configatron.factory.couchdb.server = "http://127.0.0.1:5984"
9
- configatron.factory.couchdb.name = "integration_test_db"
10
- break("CouchDB is offline") unless Factory.couch_available?
11
- @db_uri = "#{configatron.factory.couchdb.server}/#{configatron.factory.couchdb.name}"
12
- end
13
-
14
- after(:all) do
15
- CouchRest.database!(@db_uri).delete!
16
- end
17
-
18
- describe "updating a Batch" do
19
- before(:each) do
20
- @batch = Batch.[](Answer.new("do a"), Answer.new("do b"))
21
- end
22
-
23
- describe "Batch#bulk_save!" do
24
- it "should capture the couch_id values in the Answers themselves" do
25
- old_ids = @batch.collect {|a| a.couch_id}
26
- @batch.bulk_save!(@db_uri)
27
- new_ids = @batch.collect {|a| a.couch_id}
28
- old_ids.should_not == new_ids
29
- end
30
-
31
- it "should capture the couch_rev values in the Answers themselves" do
32
- @batch.bulk_save!(@db_uri)
33
- new_revs = @batch.collect {|a| a.couch_rev}
34
- new_revs.each {|r| r.should_not == ""}
35
- end
36
- end
37
-
38
-
39
- it "should be possible to set the couchdb_id and have that be actually used" do
40
- @batch[0].couch_id = "001"
41
- @batch[1].couch_id = "002"
42
- ids = @batch.bulk_save!(@db_uri).collect {|r| r["id"]}
43
- ids.should == ["001", "002"]
44
- end
45
-
46
- it "should be possible to overwrite a document with new info" do
47
- @batch.bulk_save!(@db_uri)
48
-
49
- db = CouchRest.database!(@db_uri)
50
- as_saved = db.get(@batch[0].couch_id)["_rev"]
51
- @batch[0].scores[:wellness] = 0
52
- @batch.bulk_save!(@db_uri)
53
- and_now = db.get(@batch[0].couch_id)["_rev"]
54
- as_saved[0].should == "1"
55
- and_now[0].should == "2"
56
- end
57
-
58
- end
59
-
60
- end