rachinations 0.0.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +6 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +93 -0
- data/LICENSE.txt +21 -0
- data/README.md +18 -0
- data/Rakefile +16 -0
- data/lib/rachinations.rb +49 -0
- data/lib/rachinations/domain/diagrams/diagram.rb +167 -0
- data/lib/rachinations/domain/diagrams/non_deterministic_diagram.rb +16 -0
- data/lib/rachinations/domain/diagrams/verbose_diagram.rb +9 -0
- data/lib/rachinations/domain/edge_collection.rb +12 -0
- data/lib/rachinations/domain/edges/edge.rb +159 -0
- data/lib/rachinations/domain/edges/random_edge.rb +4 -0
- data/lib/rachinations/domain/exceptions/bad_options.rb +3 -0
- data/lib/rachinations/domain/exceptions/no_elements_found.rb +2 -0
- data/lib/rachinations/domain/exceptions/no_elements_matching_condition_error.rb +2 -0
- data/lib/rachinations/domain/exceptions/no_elements_of_given_type.rb +3 -0
- data/lib/rachinations/domain/exceptions/unsupported_type_error.rb +2 -0
- data/lib/rachinations/domain/modules/common/hash_init.rb +88 -0
- data/lib/rachinations/domain/modules/common/invariant.rb +17 -0
- data/lib/rachinations/domain/modules/diagrams/verbose.rb +30 -0
- data/lib/rachinations/domain/node_collection.rb +30 -0
- data/lib/rachinations/domain/nodes/converter.rb +276 -0
- data/lib/rachinations/domain/nodes/gate.rb +6 -0
- data/lib/rachinations/domain/nodes/node.rb +166 -0
- data/lib/rachinations/domain/nodes/pool.rb +267 -0
- data/lib/rachinations/domain/nodes/resourceful_node.rb +96 -0
- data/lib/rachinations/domain/nodes/resourceless_node.rb +11 -0
- data/lib/rachinations/domain/nodes/sink.rb +17 -0
- data/lib/rachinations/domain/nodes/source.rb +161 -0
- data/lib/rachinations/domain/nodes/trader.rb +6 -0
- data/lib/rachinations/domain/resource_bag.rb +131 -0
- data/lib/rachinations/domain/resources/token.rb +51 -0
- data/lib/rachinations/domain/strategies/strategy.rb +5 -0
- data/lib/rachinations/domain/strategies/valid_types.rb +69 -0
- data/lib/rachinations/dsl/dsl.rb +63 -0
- data/lib/rachinations/extras/fifo.rb +27 -0
- data/lib/rachinations/version.rb +3 -0
- data/machinations_diagrams/apenas_bonito.xml +22 -0
- data/machinations_diagrams/behavior_converter.xml +53 -0
- data/machinations_diagrams/behavior_converter_fim.xml +10 -0
- data/machinations_diagrams/canon/README.md +8 -0
- data/machinations_diagrams/canon/converters_differences.xml +27 -0
- data/machinations_diagrams/canon/converters_differences2.xml +34 -0
- data/machinations_diagrams/canon/converters_similarities.xml +63 -0
- data/machinations_diagrams/canon/converters_similarities2.xml +21 -0
- data/machinations_diagrams/canon/nodes_and_edges_differences.xml +15 -0
- data/machinations_diagrams/canon/nodes_and_edges_similarities.xml +20 -0
- data/machinations_diagrams/deterministic_example.xml +46 -0
- data/machinations_diagrams/economies_of_scale.xml +32 -0
- data/machinations_diagrams/feature_ou_bug.xml +5 -0
- data/machinations_diagrams/loop_in_trigger.xml +21 -0
- data/machinations_diagrams/naficadevendo.xml +12 -0
- data/machinations_diagrams/noreporting_equivalent.xml +22 -0
- data/machinations_diagrams/pull_all_example.xml +7 -0
- data/machinations_diagrams/sketch_of_memory.xml +41 -0
- data/machinations_diagrams/software_engineering_process 2.xml +130 -0
- data/machinations_diagrams/software_engineering_process v3.xml +168 -0
- data/machinations_diagrams/software_engineering_process v4.xml +192 -0
- data/machinations_diagrams/software_engineering_process.xml +65 -0
- data/machinations_diagrams/software_engineering_process_with_rework_after_test.xml +195 -0
- data/machinations_diagrams/startup_marketing.xml +35 -0
- data/machinations_diagrams/triggers_allow_multiple_stages_at_same_round.xml +19 -0
- data/machinations_diagrams/um_de_cada_vez_vs_todos_de_uma_vez.xml +20 -0
- data/rachinations.gemspec +35 -0
- data/testing/features/step_definitions/step_definitions.rb +11 -0
- data/testing/simulations/modelo1.rb +20 -0
- data/testing/simulations/modelo2.rb +49 -0
- data/testing/simulations/noreporting.rb +51 -0
- data/testing/simulations/sequencial.rb +19 -0
- data/testing/simulations/sobonito.rb +28 -0
- data/testing/simulations/sobonitowhile.rb +28 -0
- data/testing/simulations/whatIwish1.rb +20 -0
- data/testing/spec/canon/converter_spec.rb +33 -0
- data/testing/spec/canon/pool_spec.rb +68 -0
- data/testing/spec/conditions_spec.rb +10 -0
- data/testing/spec/converter_spec.rb +223 -0
- data/testing/spec/diagram_spec.rb +671 -0
- data/testing/spec/edge_spec.rb +256 -0
- data/testing/spec/hash_init_spec.rb +59 -0
- data/testing/spec/node_spec.rb +31 -0
- data/testing/spec/non_deterministic_diagram_spec.rb +112 -0
- data/testing/spec/pool_spec.rb +233 -0
- data/testing/spec/source_spec.rb +132 -0
- data/testing/spec/spec_helper.rb +34 -0
- data/testing/spec/xexeo_spec.rb +193 -0
- metadata +283 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../../domain/nodes/pool'
|
2
|
+
# You can send anything to a Sink.
|
3
|
+
# Think of it like a Blackhole for resources.
|
4
|
+
|
5
|
+
class Sink < Pool
|
6
|
+
|
7
|
+
|
8
|
+
def take_resource!(type=nil, &expression)
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
def put_resource!(obj)
|
13
|
+
inv{obj.unlocked?}
|
14
|
+
# do nothing
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require_relative '../../domain/nodes/pool'
|
2
|
+
|
3
|
+
class Source < ResourcefulNode
|
4
|
+
|
5
|
+
|
6
|
+
def initialize(hsh={})
|
7
|
+
|
8
|
+
check_options!(hsh)
|
9
|
+
params = set_defaults(hsh)
|
10
|
+
|
11
|
+
@type = params[:type]
|
12
|
+
@mode = params[:mode]
|
13
|
+
@activation = params[:activation]
|
14
|
+
@name = params[:name]
|
15
|
+
|
16
|
+
super
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :support?, :supports?
|
21
|
+
|
22
|
+
def typed?
|
23
|
+
!@type.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def untyped?
|
27
|
+
!typed?
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"Source '#{@name}': #{@resources.to_s}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def put_resource!;
|
35
|
+
end
|
36
|
+
|
37
|
+
def take_resource!(type=nil)
|
38
|
+
|
39
|
+
if type.nil? && untyped?
|
40
|
+
res = Token.new
|
41
|
+
type_taken = nil
|
42
|
+
elsif !type.nil? && supports?(type)
|
43
|
+
res = type.new
|
44
|
+
type_taken = type
|
45
|
+
else
|
46
|
+
res = self.type.new
|
47
|
+
type_taken = self.type
|
48
|
+
end
|
49
|
+
|
50
|
+
@resources_removed[type_taken] += 1
|
51
|
+
|
52
|
+
fire_triggers!
|
53
|
+
|
54
|
+
res
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
def types
|
59
|
+
[@type]
|
60
|
+
end
|
61
|
+
|
62
|
+
def trigger!
|
63
|
+
if enabled?
|
64
|
+
if push? && any?
|
65
|
+
|
66
|
+
push_any!
|
67
|
+
|
68
|
+
elsif pull?
|
69
|
+
|
70
|
+
raise NotImplementedError('A pulling Source?')
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def resources_added
|
78
|
+
0
|
79
|
+
end
|
80
|
+
|
81
|
+
def resources_removed(type=nil)
|
82
|
+
|
83
|
+
if type.nil?
|
84
|
+
@resources_removed[Token]
|
85
|
+
else
|
86
|
+
@resources_removed[type]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def resource_count(type=nil)
|
92
|
+
return 0
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def remove_resource!(&expression)
|
98
|
+
|
99
|
+
#we'll need to change this if source starts accepting
|
100
|
+
# more than a single type
|
101
|
+
inv { types.size === 1 }
|
102
|
+
|
103
|
+
if type.nil?
|
104
|
+
res = Token.new
|
105
|
+
else
|
106
|
+
res = type.new
|
107
|
+
end
|
108
|
+
|
109
|
+
if (expression.call(res))
|
110
|
+
@resources_removed[res.type] += 1
|
111
|
+
res
|
112
|
+
else
|
113
|
+
raise RuntimeError.new("This Source cannot provide a resource matching given expression.")
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
attr_reader :type
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def push_any!
|
124
|
+
outgoing_edges
|
125
|
+
.shuffle
|
126
|
+
.each do |edge|
|
127
|
+
begin
|
128
|
+
blk = edge.push_expression
|
129
|
+
rescue => ex
|
130
|
+
# Could not get a block for one Edge, but this is push_any so I'll go ahead.
|
131
|
+
next
|
132
|
+
end
|
133
|
+
|
134
|
+
edge.label.times do
|
135
|
+
begin
|
136
|
+
res = remove_resource!(&blk)
|
137
|
+
rescue => ex
|
138
|
+
# Failed to remove this resource. Let's try another Edge, perhaps?
|
139
|
+
break
|
140
|
+
end
|
141
|
+
|
142
|
+
edge.push!(res)
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def options
|
150
|
+
[:type, :mode, :activation, :diagram, :conditions, name: :required]
|
151
|
+
end
|
152
|
+
|
153
|
+
def defaults
|
154
|
+
{
|
155
|
+
type: nil,
|
156
|
+
mode: :push_any,
|
157
|
+
activation: :automatic
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require_relative '../domain/modules/common/invariant'
|
3
|
+
|
4
|
+
|
5
|
+
class ResourceBag
|
6
|
+
include Invariant
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@store = Array.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize_copy(orig)
|
13
|
+
super
|
14
|
+
@store=@store.map { |el| el.clone }
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def add!(obj)
|
19
|
+
@store.push(obj)
|
20
|
+
end
|
21
|
+
|
22
|
+
#retrieve
|
23
|
+
def get(klass)
|
24
|
+
|
25
|
+
if count(klass) === 0
|
26
|
+
raise NoElementsOfGivenTypeError, "No elements of class #{klass} found."
|
27
|
+
end
|
28
|
+
|
29
|
+
obj = store.select { |el| el.is_a?(klass) }.sample
|
30
|
+
|
31
|
+
remove_element!(obj)
|
32
|
+
obj
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def count(klass)
|
37
|
+
|
38
|
+
inv { klass.is_a?(Class) }
|
39
|
+
|
40
|
+
store.select { |el| el.is_a?(klass) }.length
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def count_where(&blk)
|
45
|
+
|
46
|
+
raise ArgumentError, 'Please supply a block containing the condition.' unless block_given?
|
47
|
+
|
48
|
+
amount = 0
|
49
|
+
|
50
|
+
store.each { |e|
|
51
|
+
amount += 1 if yield e
|
52
|
+
}
|
53
|
+
|
54
|
+
amount
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
def each_where
|
59
|
+
raise ArgumentError, 'Please supply a block containing the condition to apply for each resource.' unless block_given?
|
60
|
+
|
61
|
+
store.each { |r| yield r }
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_where &condition
|
66
|
+
raise ArgumentError, 'Please supply a block containing the condition to apply..' unless block_given?
|
67
|
+
raise NoElementsMatchingConditionError, "No elements found matching given condition." unless theres_at_least_one_where &condition
|
68
|
+
|
69
|
+
obj = store.select{|r| r.unlocked? }.select { |r| (yield r) }.sample
|
70
|
+
|
71
|
+
remove_element!(obj)
|
72
|
+
obj
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# created so that I don't have to call count everytime just to see whether there's at least one element matching said condition
|
77
|
+
def theres_at_least_one_where
|
78
|
+
|
79
|
+
raise ArgumentError, 'Please supply a block containing the condition.' unless block_given?
|
80
|
+
|
81
|
+
store.each do |e|
|
82
|
+
if e.unlocked? && (yield e)
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
false
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
out = ''
|
93
|
+
|
94
|
+
classes = store.map { |el| el.class }.uniq
|
95
|
+
|
96
|
+
classes.each do |klass|
|
97
|
+
|
98
|
+
name = if klass.name.nil?
|
99
|
+
'Anonymous Klass'
|
100
|
+
else
|
101
|
+
klass.name
|
102
|
+
end
|
103
|
+
|
104
|
+
out += "\n"+' '+ name + ' -> '+ count(klass).to_s+"\n\n"
|
105
|
+
end
|
106
|
+
|
107
|
+
if classes.empty?
|
108
|
+
"\n Empty\n\n"
|
109
|
+
else
|
110
|
+
out
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
|
119
|
+
def store
|
120
|
+
@store
|
121
|
+
end
|
122
|
+
|
123
|
+
def remove_element!(obj)
|
124
|
+
|
125
|
+
if @store.delete(obj).nil?
|
126
|
+
raise NoElementsOfGivenTypeError
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Token
|
2
|
+
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@lock= false
|
6
|
+
end
|
7
|
+
|
8
|
+
def lock!
|
9
|
+
if locked?
|
10
|
+
raise RuntimeError, 'Tried to lock a locked Token.'
|
11
|
+
else
|
12
|
+
@lock = true
|
13
|
+
end
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def type
|
18
|
+
self.class
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_type?(type)
|
22
|
+
self.type.eql? type
|
23
|
+
end
|
24
|
+
|
25
|
+
def unlock!
|
26
|
+
if unlocked?
|
27
|
+
raise RuntimeError, 'Tried to unlock an unlocked Token.'
|
28
|
+
else
|
29
|
+
@lock = false
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def locked?
|
35
|
+
@lock == true
|
36
|
+
end
|
37
|
+
|
38
|
+
def unlocked?
|
39
|
+
@lock == false
|
40
|
+
end
|
41
|
+
|
42
|
+
#hooks which can be overridden in child classes
|
43
|
+
def reached_node(node); end
|
44
|
+
|
45
|
+
def left_node(node); end
|
46
|
+
|
47
|
+
def reached_edge(edge); end
|
48
|
+
|
49
|
+
def left_edge(edge); end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'strategy'
|
2
|
+
|
3
|
+
class ValidTypes < Strategy
|
4
|
+
|
5
|
+
# @note from_node is only included in the constructor's argument
|
6
|
+
# list to check whether it is enabled, but it isn't used anywhere lese.
|
7
|
+
def initialize(from_node, edge, to_node)
|
8
|
+
@from_node = from_node
|
9
|
+
@edge = edge
|
10
|
+
@to_node = to_node
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the expression block which can used by from_node in order
|
14
|
+
# to select a resource that is supported by both the edge and the node
|
15
|
+
# to which the resource will be transferred.
|
16
|
+
#
|
17
|
+
# @return [Proc] the expression block.
|
18
|
+
def condition
|
19
|
+
|
20
|
+
return match_none_expression if [@from_node, @edge, @to_node].any? {|el| el.disabled? }
|
21
|
+
|
22
|
+
edge_types = @edge.types
|
23
|
+
to_node_types = @to_node.types
|
24
|
+
|
25
|
+
if edge_types.empty? && to_node_types.empty?
|
26
|
+
match_all_expression
|
27
|
+
else
|
28
|
+
if edge_types.empty? && (not to_node_types.empty?)
|
29
|
+
Proc.new { |res| to_node_types.include?(res.type) }
|
30
|
+
elsif to_node_types.empty? && (not edge_types.empty?)
|
31
|
+
Proc.new { |res| edge_types.include?(res.type) }
|
32
|
+
else
|
33
|
+
Proc.new { |res| edge_types.include?(res.type) && node_types.include?(res.type) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns an expression block which can be used to decide whether a given
|
40
|
+
# resource is supported both by the edge and by to_node.
|
41
|
+
#
|
42
|
+
# @return [Proc] the expression block
|
43
|
+
def push_condition
|
44
|
+
condition
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns an expression block which can be used to decide whether a given
|
48
|
+
# resource is supported both by the edge and by from_node.
|
49
|
+
#
|
50
|
+
# @return [Proc] the expression block
|
51
|
+
def pull_condition
|
52
|
+
condition
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def unsatisfiable_expression
|
58
|
+
Proc.new { true == false }
|
59
|
+
end
|
60
|
+
|
61
|
+
def any_satisfiable_expression
|
62
|
+
Proc.new { true == true }
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method :match_all_expression, :any_satisfiable_expression
|
66
|
+
alias_method :match_none_expression, :unsatisfiable_expression
|
67
|
+
|
68
|
+
|
69
|
+
end
|