rachinations 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -25
- data/Rakefile +4 -4
- data/lib/rachinations/domain/diagrams/diagram.rb +12 -2
- data/lib/rachinations/domain/edges/edge.rb +9 -1
- data/lib/rachinations/domain/exceptions/bad_config.rb +4 -0
- data/lib/rachinations/domain/modules/common/hash_init.rb +1 -2
- data/lib/rachinations/domain/modules/common/refiners/number_modifiers.rb +1 -1
- data/lib/rachinations/domain/nodes/pool.rb +3 -1
- data/lib/rachinations/domain/nodes/source.rb +7 -3
- data/lib/rachinations/dsl/bootstrap.rb +0 -3
- data/lib/rachinations/dsl/helpers/parser.rb +50 -41
- data/lib/rachinations/version.rb +1 -1
- data/lib/rachinations.rb +6 -4
- data/testing/spec/non_deterministic_diagram_spec.rb +2 -2
- data/testing/spec/release1/dsl_spec.rb +36 -2
- data/testing/spec/xexeo_spec.rb +4 -4
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cdd3c499e1f1791ce742a6a2cc6485fce449c53
|
4
|
+
data.tar.gz: b39dd99ffa4514366b7047be022fb69323a953d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac6c02f660108180d6f7d48e048c7ec30ce90a5a1f3f476d19f21e0b0e390073433766bcf868f0a856f3018c2ee33f892e0bdccbed1fff5e1a656f26bfb26be2
|
7
|
+
data.tar.gz: 196440e524df7fa67b43fa13aac1726378a83d578c221769d0ad95ab4f73ecc60ea0c2ee9b74e51b60e3bc2ca50e3ed3c800b85b7e73071f7645ebda8fa8d2f0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -15,28 +15,4 @@ It provides a Ruby-based DSL to enable game designers to create and also test te
|
|
15
15
|
|
16
16
|
- Classes to model the domain
|
17
17
|
- Tests
|
18
|
-
- A simple DSL (Domain-specific language) whose objective is to enable anyone to write Machinations diagrams, run them, obtain metrics, compose subdiagrams and so on.
|
19
|
-
|
20
|
-
### DSL Usage
|
21
|
-
- Simplest possible usage:
|
22
|
-
- Install the `rachinations` [gem](http://rubygems.org/gems/rachinations)
|
23
|
-
|
24
|
-
```
|
25
|
-
$ gem install rachinations
|
26
|
-
```
|
27
|
-
- Require it into your code and start designing diagrams:
|
28
|
-
|
29
|
-
```ruby
|
30
|
-
require 'rachinations'
|
31
|
-
|
32
|
-
n=diagram 'my diagram' do
|
33
|
-
node 's1',Source
|
34
|
-
node 'p1', Pool
|
35
|
-
edge 'e1', Edge, 's1','p1'
|
36
|
-
end
|
37
|
-
|
38
|
-
n.run!(5)
|
39
|
-
|
40
|
-
p n.get_node("p1").resource_count
|
41
|
-
#prints 5
|
42
|
-
```
|
18
|
+
- A simple DSL (Domain-specific language) whose objective is to enable anyone to write Machinations diagrams, run them, obtain metrics, compose subdiagrams and so on.
|
data/Rakefile
CHANGED
@@ -5,12 +5,12 @@ require 'bundler/gem_tasks'
|
|
5
5
|
|
6
6
|
task :default => [:spec]
|
7
7
|
|
8
|
-
Rake::TestTask.new do |t|
|
9
|
-
t.pattern = 'testing/**/*_test.rb'
|
10
|
-
end
|
8
|
+
#Rake::TestTask.new do |t|
|
9
|
+
# t.pattern = 'testing/**/*_test.rb'
|
10
|
+
#end
|
11
11
|
|
12
12
|
RSpec::Core::RakeTask.new do |t|
|
13
|
-
t.rspec_opts= ['--default-path testing/spec','--color']
|
13
|
+
t.rspec_opts= ['--default-path testing/spec','--color','--pattern **/*_spec.rb']
|
14
14
|
end
|
15
15
|
|
16
16
|
|
@@ -41,12 +41,16 @@ class Diagram
|
|
41
41
|
|
42
42
|
params.store(:diagram, self)
|
43
43
|
|
44
|
-
#if there's a condition, return it, otherwise return default condition
|
44
|
+
# if there's a condition, return it, otherwise return default condition
|
45
45
|
condition = params.delete(:condition) { lambda { true } }
|
46
46
|
|
47
|
-
#similarly, if nodes are supposed to be triggered by another node
|
47
|
+
# similarly, if nodes are supposed to be triggered by another node
|
48
48
|
triggered_by = params.delete(:triggered_by) { nil }
|
49
49
|
|
50
|
+
# akin to :triggered_by, but it's defined in the triggerER
|
51
|
+
# rather than in the trigerrEE
|
52
|
+
triggers = params.delete(:triggers) { nil }
|
53
|
+
|
50
54
|
node = node_klass.new(params)
|
51
55
|
|
52
56
|
node.attach_condition &condition
|
@@ -57,6 +61,12 @@ class Diagram
|
|
57
61
|
triggerer.attach_trigger(node)
|
58
62
|
end
|
59
63
|
|
64
|
+
if !triggers.nil?
|
65
|
+
# ask the current class (diagram) to evaluate what node it is
|
66
|
+
triggeree = self.send(triggers.to_sym)
|
67
|
+
node.attach_trigger(triggeree)
|
68
|
+
end
|
69
|
+
|
60
70
|
nodes.push(node)
|
61
71
|
|
62
72
|
self
|
@@ -8,9 +8,17 @@ class Edge
|
|
8
8
|
using NumberModifiers
|
9
9
|
|
10
10
|
|
11
|
-
attr_reader :from, :to, :name, :
|
11
|
+
attr_reader :from, :to, :name, :types
|
12
12
|
|
13
13
|
|
14
|
+
def label
|
15
|
+
if @label.is_a?(Proc)
|
16
|
+
@label.call
|
17
|
+
else
|
18
|
+
@label
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
14
22
|
def initialize(hsh)
|
15
23
|
|
16
24
|
check_options!(hsh)
|
@@ -3,6 +3,7 @@ require_relative '../../domain/nodes/node'
|
|
3
3
|
require_relative '../../domain/resources/token'
|
4
4
|
require_relative '../resource_bag'
|
5
5
|
require_relative '../../domain/exceptions/no_elements_matching_condition_error'
|
6
|
+
require_relative '../../domain/exceptions/bad_config'
|
6
7
|
require_relative '../../domain/modules/common/refiners/proc_convenience_methods'
|
7
8
|
require_relative '../../../../lib/rachinations/helpers/edge_helper'
|
8
9
|
|
@@ -59,8 +60,9 @@ class Pool < ResourcefulNode
|
|
59
60
|
pull_all!
|
60
61
|
|
61
62
|
else
|
62
|
-
|
63
|
+
raise BadConfig, "Invalid config for this node's mode"
|
63
64
|
end
|
65
|
+
fire_triggers!
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
@@ -2,7 +2,6 @@ require_relative '../../domain/nodes/pool'
|
|
2
2
|
|
3
3
|
class Source < ResourcefulNode
|
4
4
|
|
5
|
-
|
6
5
|
def initialize(hsh={})
|
7
6
|
|
8
7
|
check_options!(hsh)
|
@@ -65,12 +64,17 @@ class Source < ResourcefulNode
|
|
65
64
|
|
66
65
|
push_any!
|
67
66
|
|
68
|
-
elsif
|
67
|
+
elsif push? && all?
|
68
|
+
|
69
|
+
push_all!
|
69
70
|
|
70
|
-
|
71
|
+
else
|
72
|
+
raise BadConfig, 'Invalid mode for Source'
|
71
73
|
|
72
74
|
end
|
73
75
|
|
76
|
+
fire_triggers!
|
77
|
+
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
@@ -9,20 +9,19 @@ module DSL
|
|
9
9
|
|
10
10
|
ConstantHash = ::Extras::ConstantHash
|
11
11
|
|
12
|
-
# these patterns
|
12
|
+
# these patterns define what each argument should look like
|
13
13
|
|
14
|
-
|
14
|
+
IDENTIFIER = proc { |arg| arg.is_a?(String) && valid_name?(arg) }
|
15
15
|
|
16
|
-
|
16
|
+
INITIAL_VALUE = proc { |arg| arg.is_a? Fixnum }
|
17
17
|
|
18
|
-
|
18
|
+
MODE = proc { |arg| [:pull_any, :pull_all, :push_any, :push_all].include? arg }
|
19
19
|
|
20
|
-
|
20
|
+
ACTIVATION= proc { |arg| [:automatic, :passive, :start].include? arg }
|
21
21
|
|
22
|
-
|
22
|
+
PROC = proc { |arg| arg.is_a? Proc }
|
23
23
|
|
24
|
-
|
25
|
-
LABEL_EXPR = proc { |arg| arg.is_a? Numeric }
|
24
|
+
LABEL = proc { |arg| arg.is_a?(Numeric) || arg.is_a?(Proc) }
|
26
25
|
|
27
26
|
# Parse an arbitrary list of arguments and returns a well-formed
|
28
27
|
# Hash which can then be used as argument to method add_node!
|
@@ -31,57 +30,66 @@ module DSL
|
|
31
30
|
def self.parse_arguments(arguments)
|
32
31
|
arguments.inject(ConstantHash.new) do |accumulator, arg|
|
33
32
|
|
34
|
-
# named parameters are expressed
|
33
|
+
# named parameters are expressed as hashes
|
35
34
|
# and all arguments can (also) be passed as named parameters
|
36
35
|
if arg.is_a? Hash
|
36
|
+
|
37
|
+
if arg.has_key? :activation
|
38
|
+
if ACTIVATION.match? arg[:activation]
|
39
|
+
accumulator[:activation] = arg[:activation]
|
40
|
+
else
|
41
|
+
raise BadDSL.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
37
45
|
if arg.has_key? :condition
|
38
|
-
if
|
46
|
+
if PROC.match? arg[:condition]
|
39
47
|
accumulator[:condition] = arg[:condition]
|
40
48
|
else
|
41
49
|
raise BadDSL.new
|
42
50
|
end
|
43
51
|
end
|
44
52
|
|
45
|
-
if arg.has_key? :
|
46
|
-
if
|
47
|
-
accumulator[:
|
53
|
+
if arg.has_key? :initial_value
|
54
|
+
if INITIAL_VALUE.match? arg[:initial_value]
|
55
|
+
accumulator[:initial_value] = arg[:initial_value]
|
48
56
|
else
|
49
57
|
raise BadDSL.new
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
|
-
if arg.has_key? :
|
54
|
-
if
|
55
|
-
accumulator[:
|
61
|
+
if arg.has_key? :mode
|
62
|
+
if MODE.match? arg[:mode]
|
63
|
+
accumulator[:mode] = arg[:mode]
|
56
64
|
else
|
57
65
|
raise BadDSL.new
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
61
|
-
if arg.has_key? :
|
62
|
-
if
|
63
|
-
accumulator[:
|
69
|
+
if arg.has_key? :triggered_by
|
70
|
+
if IDENTIFIER.match? arg[:triggered_by]
|
71
|
+
accumulator[:triggered_by] = arg[:triggered_by]
|
64
72
|
else
|
65
73
|
raise BadDSL.new
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
69
|
-
if arg.has_key? :
|
70
|
-
if
|
71
|
-
accumulator[:
|
77
|
+
if arg.has_key? :triggers
|
78
|
+
if IDENTIFIER.match? arg[:triggers]
|
79
|
+
accumulator[:triggers] = arg[:triggers]
|
72
80
|
else
|
73
81
|
raise BadDSL.new
|
74
82
|
end
|
75
83
|
end
|
76
84
|
|
77
85
|
else
|
78
|
-
if
|
86
|
+
if IDENTIFIER.match?(arg) # a node's name, if present, is always the first argument
|
79
87
|
accumulator[:name] = arg
|
80
|
-
elsif
|
88
|
+
elsif INITIAL_VALUE.match?(arg)
|
81
89
|
accumulator[:initial_value] = arg
|
82
|
-
elsif
|
90
|
+
elsif MODE.match?(arg)
|
83
91
|
accumulator[:mode] = arg
|
84
|
-
elsif
|
92
|
+
elsif ACTIVATION.match?(arg)
|
85
93
|
accumulator[:activation] = arg
|
86
94
|
else
|
87
95
|
raise BadDSL, "Argument #{arg} doesn't fit any known signature"
|
@@ -99,16 +107,16 @@ module DSL
|
|
99
107
|
arguments.inject(ConstantHash.new) do |accumulator, arg|
|
100
108
|
if arg.is_a? Hash
|
101
109
|
if arg.has_key? :condition
|
102
|
-
accumulator[:condition] = arg[:condition] if
|
110
|
+
accumulator[:condition] = arg[:condition] if PROC.match?(arg[:condition])
|
103
111
|
elsif arg.has_key? :triggered_by
|
104
|
-
accumulator[:triggered_by] = arg[:triggered_by] if
|
112
|
+
accumulator[:triggered_by] = arg[:triggered_by] if IDENTIFIER.match?(arg[:triggered_by])
|
105
113
|
else
|
106
|
-
|
114
|
+
raise BadDSL, "Named argument doesn't fit any known signature"
|
107
115
|
end
|
108
116
|
else
|
109
|
-
if
|
117
|
+
if IDENTIFIER.match?(arg)
|
110
118
|
accumulator[:name] = arg
|
111
|
-
elsif
|
119
|
+
elsif ACTIVATION.match?(arg)
|
112
120
|
accumulator[:activation] = arg
|
113
121
|
else
|
114
122
|
raise BadDSL, "Argument #{arg} doesn't fit any known signature"
|
@@ -122,23 +130,24 @@ module DSL
|
|
122
130
|
def self.parse_edge_arguments(arguments)
|
123
131
|
|
124
132
|
arguments.inject(ConstantHash.new) do |accumulator, arg|
|
125
|
-
if
|
126
|
-
accumulator[:name] = arg
|
127
|
-
elsif LABEL_EXPR.match?(arg)
|
128
|
-
accumulator[:label]=arg
|
129
|
-
elsif arg.is_a? Hash
|
130
|
-
|
133
|
+
if arg.is_a? Hash
|
131
134
|
if arg.has_key? :from
|
132
|
-
accumulator[:from] = arg[:from]
|
135
|
+
accumulator[:from] = arg[:from] if IDENTIFIER.match? arg[:from]
|
133
136
|
end
|
134
137
|
if arg.has_key? :to
|
135
|
-
accumulator[:to] = arg[:to]
|
138
|
+
accumulator[:to] = arg[:to] if IDENTIFIER.match? arg[:to]
|
136
139
|
end
|
137
140
|
if arg.has_key? :label
|
138
|
-
accumulator[:label] = arg[:label]
|
141
|
+
accumulator[:label] = arg[:label] if LABEL.match? arg[:label]
|
139
142
|
end
|
140
143
|
else
|
141
|
-
|
144
|
+
if IDENTIFIER.match?(arg)
|
145
|
+
accumulator[:name] = arg
|
146
|
+
elsif LABEL.match?(arg)
|
147
|
+
accumulator[:label]=arg
|
148
|
+
else
|
149
|
+
raise BadDSL, "Argument #{arg} doesn't fit any known signature."
|
150
|
+
end
|
142
151
|
end
|
143
152
|
accumulator
|
144
153
|
end
|
data/lib/rachinations/version.rb
CHANGED
data/lib/rachinations.rb
CHANGED
@@ -18,6 +18,7 @@ require 'rachinations/domain/edges/edge'
|
|
18
18
|
require 'rachinations/domain/exceptions/no_elements_of_given_type'
|
19
19
|
require 'rachinations/domain/exceptions/unsupported_type_error'
|
20
20
|
require 'rachinations/domain/exceptions/bad_options'
|
21
|
+
require 'rachinations/domain/exceptions/bad_config'
|
21
22
|
require 'rachinations/domain/exceptions/no_elements_matching_condition_error'
|
22
23
|
require 'rachinations/domain/exceptions/no_elements_found'
|
23
24
|
require 'rachinations/dsl/bad_dsl'
|
@@ -36,9 +37,10 @@ require 'rachinations/domain/node_collection'
|
|
36
37
|
require 'rachinations/domain/resource_bag'
|
37
38
|
|
38
39
|
|
39
|
-
# users can call .percent on integers
|
40
|
-
using NumberModifiers
|
41
|
-
|
42
40
|
# users can use the dsl to create diagrams
|
43
41
|
include DSL::Bootstrap
|
44
|
-
|
42
|
+
|
43
|
+
# users can call .percent on numbers
|
44
|
+
include NumberModifiers
|
45
|
+
|
46
|
+
|
@@ -11,13 +11,13 @@ describe NonDeterministicDiagram do
|
|
11
11
|
name: 'g1',
|
12
12
|
activation: :automatic,
|
13
13
|
initial_value: 5,
|
14
|
-
mode: :
|
14
|
+
mode: :push_any
|
15
15
|
}
|
16
16
|
|
17
17
|
generator.add_node! Pool, {
|
18
18
|
name: 'g2',
|
19
19
|
activation: :automatic,
|
20
|
-
mode: :
|
20
|
+
mode: :push_any
|
21
21
|
}
|
22
22
|
|
23
23
|
generator.add_node! Pool, {
|
@@ -2,8 +2,6 @@ require_relative '../spec_helper'
|
|
2
2
|
|
3
3
|
describe Diagram do
|
4
4
|
|
5
|
-
using NumberModifiers
|
6
|
-
|
7
5
|
context 'diagram tests using the dsl' do
|
8
6
|
|
9
7
|
it 'runs a simple example diagram' do
|
@@ -185,6 +183,42 @@ describe Diagram do
|
|
185
183
|
|
186
184
|
end
|
187
185
|
|
186
|
+
it "accepts procs for edge labels" do
|
187
|
+
|
188
|
+
d = diagram do
|
189
|
+
source 's'
|
190
|
+
pool 'p'
|
191
|
+
edge from: 's', to: 'p', label: expr { rand(10) }
|
192
|
+
end
|
193
|
+
|
194
|
+
d.run 2
|
195
|
+
|
196
|
+
# this is clearly not an exhaustive test but itll do for now
|
197
|
+
|
198
|
+
expect(d.p.resource_count).to be <= 20
|
199
|
+
expect(d.p.resource_count).to be >= 0
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'accepts :triggers' do
|
204
|
+
|
205
|
+
# see how it gets confusing when you to turn your logic
|
206
|
+
# around in your head and define stuff in the wrong order
|
207
|
+
|
208
|
+
d = diagram do
|
209
|
+
pool 'p2'
|
210
|
+
pool 'p1', :push_any, initial_value: 7
|
211
|
+
source 's', triggers: 'p1'
|
212
|
+
edge from: 'p1', to: 'p2'
|
213
|
+
end
|
214
|
+
|
215
|
+
d.run 10
|
216
|
+
|
217
|
+
expect(d.p2.resource_count).to eq 7
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
|
188
222
|
# it "forward-referencing of non existing nodes" do
|
189
223
|
#
|
190
224
|
# expect do
|
data/testing/spec/xexeo_spec.rb
CHANGED
@@ -26,13 +26,13 @@ describe Diagram do
|
|
26
26
|
:name => 'g1',
|
27
27
|
:activation => :automatic,
|
28
28
|
:initial_value => 5,
|
29
|
-
mode: :
|
29
|
+
mode: :push_any
|
30
30
|
}
|
31
31
|
|
32
32
|
generator.add_node! Pool, {
|
33
33
|
:name => 'g2',
|
34
34
|
:activation => :automatic,
|
35
|
-
mode: :
|
35
|
+
mode: :push_any
|
36
36
|
}
|
37
37
|
|
38
38
|
generator.add_node! Pool, {
|
@@ -68,13 +68,13 @@ describe Diagram do
|
|
68
68
|
name: 'g1',
|
69
69
|
activation: :automatic,
|
70
70
|
initial_value: 5,
|
71
|
-
mode: :
|
71
|
+
mode: :push_any
|
72
72
|
}
|
73
73
|
|
74
74
|
generator.add_node! Pool, {
|
75
75
|
name: 'g2',
|
76
76
|
activation: :automatic,
|
77
|
-
mode: :
|
77
|
+
mode: :push_any
|
78
78
|
}
|
79
79
|
|
80
80
|
generator.add_node! Pool, {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rachinations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felipe Almeida
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- lib/rachinations/domain/diagrams/verbose_diagram.rb
|
161
161
|
- lib/rachinations/domain/edge_collection.rb
|
162
162
|
- lib/rachinations/domain/edges/edge.rb
|
163
|
+
- lib/rachinations/domain/exceptions/bad_config.rb
|
163
164
|
- lib/rachinations/domain/exceptions/bad_options.rb
|
164
165
|
- lib/rachinations/domain/exceptions/no_elements_found.rb
|
165
166
|
- lib/rachinations/domain/exceptions/no_elements_matching_condition_error.rb
|