rachinations 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +6 -0
  4. data/.travis.yml +8 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +19 -0
  7. data/Gemfile.lock +93 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +18 -0
  10. data/Rakefile +16 -0
  11. data/lib/rachinations.rb +49 -0
  12. data/lib/rachinations/domain/diagrams/diagram.rb +167 -0
  13. data/lib/rachinations/domain/diagrams/non_deterministic_diagram.rb +16 -0
  14. data/lib/rachinations/domain/diagrams/verbose_diagram.rb +9 -0
  15. data/lib/rachinations/domain/edge_collection.rb +12 -0
  16. data/lib/rachinations/domain/edges/edge.rb +159 -0
  17. data/lib/rachinations/domain/edges/random_edge.rb +4 -0
  18. data/lib/rachinations/domain/exceptions/bad_options.rb +3 -0
  19. data/lib/rachinations/domain/exceptions/no_elements_found.rb +2 -0
  20. data/lib/rachinations/domain/exceptions/no_elements_matching_condition_error.rb +2 -0
  21. data/lib/rachinations/domain/exceptions/no_elements_of_given_type.rb +3 -0
  22. data/lib/rachinations/domain/exceptions/unsupported_type_error.rb +2 -0
  23. data/lib/rachinations/domain/modules/common/hash_init.rb +88 -0
  24. data/lib/rachinations/domain/modules/common/invariant.rb +17 -0
  25. data/lib/rachinations/domain/modules/diagrams/verbose.rb +30 -0
  26. data/lib/rachinations/domain/node_collection.rb +30 -0
  27. data/lib/rachinations/domain/nodes/converter.rb +276 -0
  28. data/lib/rachinations/domain/nodes/gate.rb +6 -0
  29. data/lib/rachinations/domain/nodes/node.rb +166 -0
  30. data/lib/rachinations/domain/nodes/pool.rb +267 -0
  31. data/lib/rachinations/domain/nodes/resourceful_node.rb +96 -0
  32. data/lib/rachinations/domain/nodes/resourceless_node.rb +11 -0
  33. data/lib/rachinations/domain/nodes/sink.rb +17 -0
  34. data/lib/rachinations/domain/nodes/source.rb +161 -0
  35. data/lib/rachinations/domain/nodes/trader.rb +6 -0
  36. data/lib/rachinations/domain/resource_bag.rb +131 -0
  37. data/lib/rachinations/domain/resources/token.rb +51 -0
  38. data/lib/rachinations/domain/strategies/strategy.rb +5 -0
  39. data/lib/rachinations/domain/strategies/valid_types.rb +69 -0
  40. data/lib/rachinations/dsl/dsl.rb +63 -0
  41. data/lib/rachinations/extras/fifo.rb +27 -0
  42. data/lib/rachinations/version.rb +3 -0
  43. data/machinations_diagrams/apenas_bonito.xml +22 -0
  44. data/machinations_diagrams/behavior_converter.xml +53 -0
  45. data/machinations_diagrams/behavior_converter_fim.xml +10 -0
  46. data/machinations_diagrams/canon/README.md +8 -0
  47. data/machinations_diagrams/canon/converters_differences.xml +27 -0
  48. data/machinations_diagrams/canon/converters_differences2.xml +34 -0
  49. data/machinations_diagrams/canon/converters_similarities.xml +63 -0
  50. data/machinations_diagrams/canon/converters_similarities2.xml +21 -0
  51. data/machinations_diagrams/canon/nodes_and_edges_differences.xml +15 -0
  52. data/machinations_diagrams/canon/nodes_and_edges_similarities.xml +20 -0
  53. data/machinations_diagrams/deterministic_example.xml +46 -0
  54. data/machinations_diagrams/economies_of_scale.xml +32 -0
  55. data/machinations_diagrams/feature_ou_bug.xml +5 -0
  56. data/machinations_diagrams/loop_in_trigger.xml +21 -0
  57. data/machinations_diagrams/naficadevendo.xml +12 -0
  58. data/machinations_diagrams/noreporting_equivalent.xml +22 -0
  59. data/machinations_diagrams/pull_all_example.xml +7 -0
  60. data/machinations_diagrams/sketch_of_memory.xml +41 -0
  61. data/machinations_diagrams/software_engineering_process 2.xml +130 -0
  62. data/machinations_diagrams/software_engineering_process v3.xml +168 -0
  63. data/machinations_diagrams/software_engineering_process v4.xml +192 -0
  64. data/machinations_diagrams/software_engineering_process.xml +65 -0
  65. data/machinations_diagrams/software_engineering_process_with_rework_after_test.xml +195 -0
  66. data/machinations_diagrams/startup_marketing.xml +35 -0
  67. data/machinations_diagrams/triggers_allow_multiple_stages_at_same_round.xml +19 -0
  68. data/machinations_diagrams/um_de_cada_vez_vs_todos_de_uma_vez.xml +20 -0
  69. data/rachinations.gemspec +35 -0
  70. data/testing/features/step_definitions/step_definitions.rb +11 -0
  71. data/testing/simulations/modelo1.rb +20 -0
  72. data/testing/simulations/modelo2.rb +49 -0
  73. data/testing/simulations/noreporting.rb +51 -0
  74. data/testing/simulations/sequencial.rb +19 -0
  75. data/testing/simulations/sobonito.rb +28 -0
  76. data/testing/simulations/sobonitowhile.rb +28 -0
  77. data/testing/simulations/whatIwish1.rb +20 -0
  78. data/testing/spec/canon/converter_spec.rb +33 -0
  79. data/testing/spec/canon/pool_spec.rb +68 -0
  80. data/testing/spec/conditions_spec.rb +10 -0
  81. data/testing/spec/converter_spec.rb +223 -0
  82. data/testing/spec/diagram_spec.rb +671 -0
  83. data/testing/spec/edge_spec.rb +256 -0
  84. data/testing/spec/hash_init_spec.rb +59 -0
  85. data/testing/spec/node_spec.rb +31 -0
  86. data/testing/spec/non_deterministic_diagram_spec.rb +112 -0
  87. data/testing/spec/pool_spec.rb +233 -0
  88. data/testing/spec/source_spec.rb +132 -0
  89. data/testing/spec/spec_helper.rb +34 -0
  90. data/testing/spec/xexeo_spec.rb +193 -0
  91. metadata +283 -0
@@ -0,0 +1,233 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Pool do
4
+
5
+ it 'is created with just a name attribute and has the expected default attributes' do
6
+ obj = Pool.new name: 'some name'
7
+
8
+ expect(obj.passive?).to eq true
9
+ expect(obj.pull?).to eq true
10
+ expect(obj.resource_count).to eq 0
11
+
12
+ end
13
+
14
+ it 'knows its name' do
15
+
16
+ obj = Pool.new name: 'foo'
17
+
18
+ expect(obj).to respond_to :name
19
+ expect(obj.name).to eq 'foo'
20
+ end
21
+
22
+ it 'cannot have its name set after creation' do
23
+
24
+ obj = Pool.new name: 'bar'
25
+ expect(obj).not_to respond_to :name=
26
+
27
+ end
28
+
29
+ it 'supports simple integers as resources' do
30
+
31
+ p=Pool.new name: 'baz', initial_value: 10
32
+
33
+ expect(p.resource_count).to eq 10
34
+
35
+ end
36
+
37
+ it 'supports types during instantiation' do
38
+
39
+ #note that there is no check whether this class is suited to play the role of a Token...
40
+
41
+ expect { Pool.new name: 'qux', types: [Peach] }.not_to raise_error
42
+
43
+ end
44
+
45
+ it "knows that having initial values for some types implies having those types even if the user didn't explicitly added them" do
46
+
47
+ p = Pool.new name: 'foo', initial_values: {Peach => 6, Mango => 7}
48
+
49
+ expect(p.support?(Peach)).to eq true
50
+ expect(p.support?(Mango)).to eq true
51
+
52
+ end
53
+
54
+ it 'can be set to automatic upon instantiation' do
55
+ Pool.new name: 'bar', activation: :automatic
56
+ end
57
+
58
+ it 'knows how many resources were added' do
59
+
60
+ p1 = Pool.new name: 'typed pool'
61
+ 5.times { p1.put_resource! Token.new }
62
+ p1.unlock_resources!
63
+ 2.times { p1.take_resource! }
64
+
65
+
66
+ expect(p1.resources_added).to eq 5
67
+ expect(p1.resources_removed).to eq 2
68
+ expect(p1.resource_count).to eq 3
69
+
70
+ end
71
+
72
+
73
+ it 'is enabled by default' do
74
+
75
+ p2 = Pool.new name: 'simpler yet'
76
+
77
+ expect(p2.enabled?).to eq true
78
+
79
+ end
80
+
81
+ describe '#resource_count' do
82
+
83
+ before(:each) do
84
+ @untyped = Pool.new name: 'p', initial_value: 10
85
+ @typed = Pool.new name: 'p', initial_value: {Peach => 10, Lemon => 5}
86
+ end
87
+
88
+ it 'works with no params' do
89
+ expect(@typed.resource_count).to eq 15
90
+ expect(@untyped.resource_count).to eq 10
91
+ end
92
+
93
+ it 'raises an error when it is asked about an unsupported type and it is typed' do
94
+ expect { @typed.resource_count(Mango) }.to raise_error UnsupportedTypeError
95
+ end
96
+
97
+ it 'just returns zero if it is untyped and it is asked about a type' do
98
+ expect(@untyped.resource_count(Mango)).to eq 0
99
+ end
100
+
101
+ it 'otherwise works with one type param' do
102
+ expect(@typed.resource_count(Peach)).to eq 10
103
+ end
104
+
105
+ it 'accepts a single block' do
106
+ expect(@typed.resource_count { |r| r.is_type? Peach }).to eq 10
107
+ expect(@untyped.resource_count { true }).to eq 10
108
+
109
+ # if user sent a block. he prolly knows what he's doing so no errors.
110
+ expect(@typed.resource_count { |r| r.is_type? Football }).to eq 0
111
+ end
112
+
113
+ it 'errors if given both a type and a block' do
114
+ expect { @typed.resource_count(Peach) { |r| r.is_type? Mango } }.to raise_error ArgumentError
115
+ end
116
+
117
+ it 'also errors if some other nonsense is passed' do
118
+ expect { @typed.resource_count(Hash.new) }.to raise_error ArgumentError
119
+ expect { @untyped.resource_count('Foo') }.to raise_error ArgumentError
120
+ end
121
+
122
+ end
123
+
124
+ describe '#take_resource!' do
125
+
126
+
127
+ end
128
+
129
+ describe '#put_resource!' do
130
+ before(:each) do
131
+ @p = Pool.new name: 'p'
132
+ @res = instance_double(Token, lock!: @res, :unlocked? => true)
133
+ end
134
+ it 'blocks the resource upon receiving it' do
135
+
136
+ expect(@res).to receive(:lock!)
137
+
138
+ @p.put_resource!(@res)
139
+
140
+ end
141
+
142
+ it 'adds the resource to the store' do
143
+ bag_dbl = instance_double(ResourceBag)
144
+ expect(@p).to receive(:resources).and_return(bag_dbl)
145
+ expect(bag_dbl).to receive(:add!)
146
+
147
+ @p.put_resource!(Token.new)
148
+ end
149
+
150
+ it 'fires triggers' do
151
+ expect(@p).to receive(:fire_triggers!)
152
+ @p.put_resource!(Token.new)
153
+ end
154
+
155
+ end
156
+
157
+ describe '#trigger!' do
158
+
159
+
160
+ context 'when :push_any' do
161
+
162
+ before(:each) do
163
+
164
+ @p = Pool.new name: 'p', mode: :push_any
165
+
166
+ @e = instance_double(Edge, from: @p, to: double(), label: 1)
167
+ allow(@e).to receive_messages([:push!])
168
+
169
+ @p.attach_edge!(@e)
170
+
171
+ end
172
+
173
+ it 'asks outgoing edges for blocks' do
174
+
175
+ expect(@e).to receive(:push_expression).and_return(proc { |r| true == true })
176
+
177
+ @p.trigger!
178
+
179
+ end
180
+
181
+ it 'removes resources from self if given a suitable block' do
182
+ expect(@e).to receive(:push_expression).and_return(proc { |r| true })
183
+
184
+ expect(@p).to receive(:remove_resource!)
185
+
186
+ @p.trigger!
187
+
188
+ end
189
+
190
+ it 'calls push! on edge if it succeeded in removing from self the needed resource for that edge' do
191
+
192
+ expect(@e).to receive(:push_expression).and_return( proc{ true==true } )
193
+
194
+ res = instance_double(Token)
195
+
196
+ expect(@p).to receive(:remove_resource!).and_return(res)
197
+
198
+ expect(@e).to receive(:push!).with(res)
199
+
200
+ @p.trigger!
201
+
202
+ end
203
+
204
+ it 'does not call push! on edge if it cannot provide the needed resource' do
205
+ expect(@e).to receive(:push_expression).and_return( proc{ true })
206
+
207
+ expect(@p).to receive(:remove_resource!).and_raise(RuntimeError)
208
+
209
+ expect(@e).not_to receive(:push!)
210
+
211
+ @p.trigger!
212
+
213
+ end
214
+
215
+ end
216
+
217
+ context 'when :pull_any' do
218
+
219
+
220
+ end
221
+
222
+ context 'when :push_all' do
223
+
224
+ end
225
+
226
+ context 'when :pull_all' do
227
+
228
+ end
229
+
230
+
231
+ end
232
+
233
+ end
@@ -0,0 +1,132 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe 'Source' do
4
+
5
+ describe '#initialize' do
6
+
7
+ it 'is push_any automatic with no types by default' do
8
+
9
+ s = Source.new name: 'source'
10
+
11
+ expect(s.typed?).to eq false
12
+ expect(s.automatic?).to eq true
13
+ expect(s.push?).to eq true
14
+ expect(s.any?).to eq true
15
+
16
+ end
17
+
18
+ it 'raises an error if user tries to give it an initial_value' do
19
+ #sources have no initial value
20
+ expect { Source.new name: 'mysource', initial_value: 10 }.to raise_error BadOptions
21
+ end
22
+
23
+
24
+ end
25
+
26
+
27
+ describe '#support?' do
28
+
29
+ it "supports anything if it's untyped" do
30
+ s = Source.new name: 'foo'
31
+
32
+ expect(s.support?(Peach)).to eq true
33
+
34
+ end
35
+
36
+ it "supports only the given type and no other types if it's been given a specific type" do
37
+
38
+ s = Source.new name: 'foo', type: Peach
39
+
40
+ expect(s.support?(Mango)).to eq false
41
+ expect(s.support?(Peach)).to eq true
42
+
43
+ end
44
+
45
+
46
+ end
47
+
48
+
49
+ describe '#take_resource!' do
50
+
51
+ it "provides a typeless resource (Token) if it it's untyped" do
52
+
53
+ s = Source.new name: 'foo'
54
+
55
+ expect(s.take_resource!).to be_a(Token)
56
+
57
+ end
58
+
59
+ it "provides a typed resource if it supports that type" do
60
+
61
+ s = Source.new name: 'foo', type: Green
62
+
63
+ expect(s.take_resource!(Green)).to be_a(Green)
64
+
65
+ end
66
+
67
+ it "keeps giving out resources forever, and each resource is a different object" do
68
+
69
+ s = Source.new name: 'foo', type: Blue
70
+
71
+ obj_ids = []
72
+
73
+ #i've tested this with up to 10000 loops.
74
+ # but i keep this 100 just to make the whole
75
+ # test suite run faster.
76
+ 100.times do
77
+
78
+ res = s.take_resource!(Blue)
79
+
80
+ expect(res).to be_a(Blue)
81
+
82
+ expect(obj_ids).not_to include(res.object_id)
83
+
84
+ obj_ids.push(res.object_id)
85
+
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ describe '#trigger!' do
94
+
95
+ context 'when :push_any' do
96
+
97
+ before(:each) do
98
+
99
+ @s = Source.new name: 's'
100
+
101
+ @e1 = instance_double(Edge, from: @s, to: double(), label: 1)
102
+
103
+ @e2 = instance_double(Edge, from: @s, to: double(), label: 1)
104
+
105
+ @s.attach_edge!(@e1)
106
+ @s.attach_edge!(@e2)
107
+
108
+
109
+ end
110
+
111
+ it 'sends a push to outgoing edges(in random order)' do
112
+
113
+ expect(@e1).to receive(:push_expression).and_return( proc{true==true} )
114
+ expect(@e2).to receive(:push_expression).and_return( proc{true==true} )
115
+
116
+ expect(@e1).to receive(:push!)
117
+ expect(@e2).to receive(:push!)
118
+
119
+ @s.trigger!
120
+
121
+ end
122
+
123
+ end
124
+
125
+ context 'when :push_all' do
126
+
127
+ end
128
+
129
+ end
130
+
131
+
132
+ end
@@ -0,0 +1,34 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ # so that i can require stuff as if these dirctories were in ruby's default PATH
5
+ #$: << File.expand_path(File.dirname(__FILE__))+"/../../domain"
6
+ #$: << File.expand_path(File.dirname(__FILE__))+"/../../dsl"
7
+
8
+ require 'rspec'
9
+
10
+ # RSpec.configure do |config|
11
+ # config.color_enabled = true
12
+ # config.default_path = 'testing/spec'
13
+ # end
14
+
15
+ require 'rachinations'
16
+
17
+ #resource classes to be used in tests
18
+ Blue=Class.new(Token)
19
+ Black=Class.new(Token)
20
+ Green=Class.new(Token)
21
+ Red=Class.new(Token)
22
+ Yellow=Class.new(Token)
23
+
24
+
25
+ Football=Class.new(Token)
26
+ Baseball=Class.new(Token)
27
+ Basketball=Class.new(Token)
28
+
29
+ Mango=Class.new(Token)
30
+ Peach=Class.new(Token)
31
+ Banana=Class.new(Token)
32
+ Lemon=Class.new(Token)
33
+
34
+
@@ -0,0 +1,193 @@
1
+ require_relative 'spec_helper'
2
+
3
+ #models in testing/simulations, rewritten as specs
4
+
5
+ describe Diagram do
6
+
7
+ it "runs modelo1" do
8
+
9
+ n=diagram 'test_diagram' do
10
+ node 'source', Source
11
+ node 'pool1', Pool
12
+ edge 'edge1', Edge, 'source', 'pool1'
13
+ end
14
+
15
+ d = Diagram.new('one source one pool')
16
+
17
+ n.run!(5)
18
+
19
+ end
20
+
21
+ it "runs modelo2" do
22
+
23
+ generator = Diagram.new('1to2')
24
+
25
+ generator.add_node! Pool, {
26
+ :name => 'g1',
27
+ :activation => :automatic,
28
+ :initial_value => 5,
29
+ mode: :push
30
+ }
31
+
32
+ generator.add_node! Pool, {
33
+ :name => 'g2',
34
+ :activation => :automatic,
35
+ mode: :push
36
+ }
37
+
38
+ generator.add_node! Pool, {
39
+ :name => 'g3'
40
+ }
41
+
42
+ generator.add_edge! Edge, {
43
+ :name => 'c1',
44
+ :from => 'g1',
45
+ :to => 'g2'
46
+ }
47
+
48
+ generator.add_edge! Edge, {
49
+ :name => 'c2',
50
+ :from => 'g1',
51
+ :to => 'g3'
52
+ }
53
+
54
+
55
+ generator.add_edge! Edge, {
56
+ :name => 'c3',
57
+ :from => 'g2',
58
+ :to => 'g1'
59
+ }
60
+
61
+ generator.run!(5)
62
+ end
63
+
64
+ it "runs noreporting" do
65
+ generator = Diagram.new('1to2')
66
+
67
+ generator.add_node! Pool, {
68
+ name: 'g1',
69
+ activation: :automatic,
70
+ initial_value: 5,
71
+ mode: :push
72
+ }
73
+
74
+ generator.add_node! Pool, {
75
+ name: 'g2',
76
+ activation: :automatic,
77
+ mode: :push
78
+ }
79
+
80
+ generator.add_node! Pool, {
81
+ name: 'g3'
82
+ }
83
+
84
+ generator.add_edge! Edge, {
85
+ name: 'c1',
86
+ from: 'g1',
87
+ to: 'g2'
88
+ }
89
+
90
+ generator.add_edge! Edge, {
91
+ name: 'c2',
92
+ from: 'g1',
93
+ to: 'g3',
94
+ }
95
+
96
+
97
+ generator.add_edge! Edge, {
98
+ name: 'c3',
99
+ from: 'g2',
100
+ to: 'g1',
101
+ }
102
+
103
+ # I want to check the initial state
104
+ #puts "#### Estado inicial ####"
105
+ #puts generator
106
+
107
+ # run and get the end
108
+ generator.run!(10)
109
+
110
+ #puts "#### Estado final ####"
111
+ #puts generator
112
+ end
113
+
114
+ it "runs sequencial" do
115
+ n=diagram 'test_diagram' do
116
+ node 'p1', Pool, mode: :push, activation: :automatic, initial_value: 8
117
+ node 'p2', Pool, mode: :push, activation: :automatic
118
+ node 'p3', Pool, mode: :push, activation: :automatic
119
+ node 'p4', Pool, mode: :push, activation: :automatic
120
+ edge 'e1', Edge, 'p1', 'p2'
121
+ edge 'e2', Edge, 'p2', 'p3'
122
+ edge 'e3', Edge, 'p3', 'p4'
123
+ end
124
+
125
+ n.run!(5)
126
+
127
+ #puts n
128
+ end
129
+
130
+ it "runs sobonito" do
131
+ n=diagram 'test_diagram' do
132
+ node 'p1', Pool, mode: :push, activation: :automatic, initial_value: 8
133
+ node 'p2', Pool, mode: :push, activation: :automatic
134
+ node 'p3', Pool, mode: :push, activation: :automatic
135
+ node 'p4', Pool, mode: :push, activation: :automatic
136
+ edge 'e1', Edge, 'p1', 'p2'
137
+ edge 'e2', Edge, 'p2', 'p1'
138
+ edge 'e3', Edge, 'p1', 'p3'
139
+ edge 'e4', Edge, 'p3', 'p1'
140
+ edge 'e5', Edge, 'p4', 'p2'
141
+ edge 'e6', Edge, 'p2', 'p4'
142
+ edge 'e7', Edge, 'p4', 'p3'
143
+ edge 'e8', Edge, 'p3', 'p4'
144
+ end
145
+
146
+ d = Diagram.new('bonitinho')
147
+
148
+ n.run!(20)
149
+ end
150
+
151
+ it "runs sobonitowhile" do
152
+ n=diagram 'test_diagram' do
153
+ node 'p1', Pool, mode: :push, activation: :automatic, initial_value: 8
154
+ node 'p2', Pool, mode: :push, activation: :automatic
155
+ node 'p3', Pool, mode: :push, activation: :automatic
156
+ node 'p4', Pool, mode: :push, activation: :automatic
157
+ edge 'e1', Edge, 'p1', 'p2'
158
+ edge 'e2', Edge, 'p2', 'p1'
159
+ edge 'e3', Edge, 'p1', 'p3'
160
+ edge 'e4', Edge, 'p3', 'p1'
161
+ edge 'e5', Edge, 'p4', 'p2'
162
+ edge 'e6', Edge, 'p2', 'p4'
163
+ edge 'e7', Edge, 'p4', 'p3'
164
+ edge 'e8', Edge, 'p3', 'p4'
165
+ end
166
+
167
+ d = Diagram.new('bonitinho')
168
+
169
+ n.run_while! do
170
+ not (n.get_node("p1").resource_count == 2 and n.get_node("p4").resource_count == 2)
171
+ end
172
+ end
173
+
174
+
175
+ it "runs whatIwish1" do
176
+
177
+ skip "needed features are missing"
178
+
179
+ # n=diagram 'test_diagram' do
180
+ # node 'source', Source
181
+ # node 'pool1', Pool
182
+ # edge 'edge1', Edge, 'source', 'pool1'
183
+ # node 'pool2', Pool,
184
+ # converter 'c1' , Converter
185
+ # node 'e3' , Edge , 'pool2' , 'c1'
186
+ # trigger 't1' , Trigger , 'pool1' , 'pool2' , { |ExtendedNode p| p.resouces>0 }
187
+ # end
188
+ #
189
+ # n.run!(5,report=true)
190
+
191
+ end
192
+
193
+ end