answer-factory 0.0.15 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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