lucidMachines 0.1.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e45b69e99c6fa792a59c07f778c2650116e627698dd6c7f59e19ea18d3999bdd
4
+ data.tar.gz: 75161768c35466c9b18479d4e29b89a689394f64a232779892abf1c158f1cf26
5
+ SHA512:
6
+ metadata.gz: 26e5d9dc07e9a3ab1f62da9c9b0a69e6944d700051c900ab4874db4b88b20790833021afcaef0156d9d6a1e7778d5814ea1d2994f6bad4edabcac6277b1c2b0c
7
+ data.tar.gz: d759259eb5c5c22f4795392efdfbacac30d140c5183f1268b79b51aebc6685da6b125ac5caebeb9e01456f0a7dbb14448fb38ed95ae496cf3b8999884f39ed5a
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /export/
@@ -0,0 +1 @@
1
+ ,jiii,jiii-mi,25.01.2019 22:33,file:///home/jiii/.config/libreoffice/4;
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at poqudrof@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in lucid-machines.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lucidMachines (0.1.2)
5
+ aasm
6
+ aasm-diagram
7
+ ruby-graphviz
8
+ thor
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ aasm (5.0.6)
14
+ concurrent-ruby (~> 1.0)
15
+ aasm-diagram (0.1.2)
16
+ aasm (~> 5.0, >= 4.12)
17
+ ruby-graphviz (~> 1.2)
18
+ concurrent-ruby (1.1.5)
19
+ rake (10.5.0)
20
+ ruby-graphviz (1.2.4)
21
+ thor (0.20.3)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 2.0)
28
+ lucidMachines!
29
+ rake (~> 10.0)
30
+
31
+ BUNDLED WITH
32
+ 2.0.1
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Lucid::Machines
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lucid/machines`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'lucid-machines'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install lucid-machines
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/lucid-machines. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## Code of Conduct
38
+
39
+ Everyone interacting in the Lucid::Machines project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/lucid-machines/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/aasm_export.rb ADDED
@@ -0,0 +1,380 @@
1
+ # coding: utf-8
2
+
3
+ module ChartReader
4
+
5
+ class AASMExport
6
+
7
+ EventCallbacks = ["before", "guards", "guard",
8
+ "before_enter", "enter",
9
+ "before_success",
10
+ "success", "after",
11
+ "error", "ensure"]
12
+
13
+ GlobalEventCallbacks = ["before_all_events", "after_all_events",
14
+ "error_on_all_events", "ensure_on_all_events"]
15
+
16
+ StateCallbacks = ["before_exit", "exit",
17
+ "before_enter", "enter",
18
+ "after_exit", "after_enter"]
19
+
20
+ TransitionCallbacks = ["guard", "guards", "after", "success"]
21
+ GlobalTransitionCallbacks = ["after_all_transitions"]
22
+
23
+ attr_reader :method_names
24
+
25
+ def initialize(chart)
26
+ @chart = chart
27
+ init_method_names
28
+ create
29
+ end
30
+
31
+ def init_method_names
32
+ @method_names = []
33
+ end
34
+
35
+ def method_names
36
+ # @method_names = @method_names.uniq
37
+ # return @method_names
38
+
39
+ # unique, no trailing spaces, inside spaces are underscores
40
+ @method_names.uniq.map{|t| sanitize(t)}
41
+ end
42
+
43
+ def sanitize(name)
44
+ name.strip.tr " ", "_"
45
+ end
46
+
47
+ def create
48
+ @states = @chart.get_blocks_of_type "state"
49
+ @states = @states + @chart.get_blocks_of_type("Process")
50
+ # puts "States count: " + @states.size.to_s
51
+
52
+ @events = @chart.get_blocks_of_type "event"
53
+ @events = @events + @chart.get_blocks_of_type("Decision")
54
+ # puts "Events count: " + @events.size.to_s
55
+
56
+ ## Arrows between states are also events
57
+ ## handled in generate_events_code
58
+
59
+ create_multi_events
60
+ end
61
+
62
+ attr_reader :transitions
63
+
64
+ def create_multi_events
65
+ transitions = @chart.get_blocks_of_type("transition") +
66
+ @chart.get_blocks_of_type("Summing Junction")
67
+
68
+ # puts transitions.size.to_s + " found"
69
+
70
+ @transitions = {}
71
+ # Hash with events as keys
72
+ ## Values: Array of [from_state, to_state]
73
+ ## ex: { event1 => [[[state1], state2], [[state1, state4], state3]] }
74
+
75
+ # puts "raw transitions found " + transitions.size.to_s
76
+
77
+ ## select the valid one
78
+ transitions.each do |t|
79
+ # Link from a block.
80
+ # and link to a block.
81
+ # and link from or to an event.
82
+
83
+ from_states = t.links_from_type("state") + t.links_from_type("Process")
84
+ to_state = t.links_to_type("state") + t.links_to_type("Process")
85
+
86
+ event = t.links_to_type("event") + t.links_from_type("event")
87
+ event = event + t.links_to_type("Decision") + t.links_from_type("Decision")
88
+
89
+ priority = 0
90
+ t.links_from.each do |l, e|
91
+ if(l.text.to_i != 0)
92
+ priority = l.text.to_i
93
+ end
94
+ end
95
+
96
+ ## Remove possible duplicate links...
97
+ from_states.uniq!
98
+ to_state.uniq!
99
+ event.uniq!
100
+
101
+ if from_states.size < 1 or to_state.size != 1 or event.size != 1
102
+ print_warning(event, from_states, to_state)
103
+ next
104
+ end
105
+
106
+ event = event.first
107
+ to_state = to_state.first
108
+
109
+ # puts "Adding, from " + from_states.first.text + " to " + to_state.text + " through " + event.text
110
+ ## get the ID from the link.
111
+
112
+ # Find the priority
113
+ all_links = t.links_to.merge(t.links_from)
114
+ prio = 0
115
+ from_states.each do |s|
116
+ link = all_links.key(to_state)
117
+ next if link.nil? or link.text.nil?
118
+ link_prio = link.to_i
119
+ prio = link_prio if link_prio > prio
120
+ end
121
+ # puts "Priority found " + prio.to_s if prio != 0
122
+
123
+ @transitions[event] = [] if @transitions[event].nil?
124
+ @transitions[event] << [from_states, to_state, priority, t]
125
+ end
126
+
127
+ # puts "Transitions found " + @transitions.size.to_s
128
+
129
+ end
130
+
131
+ def print_warning(event, from_states, to_state)
132
+
133
+ if(event.size != 1)
134
+ puts "Warning: Transition without any event !" if event.size == 0
135
+
136
+ if event.size > 1
137
+ puts "Warning: Transition with multiple events !"
138
+ event.each do |e|
139
+ puts " - Event: " + e.to_s
140
+ end
141
+ end
142
+ end
143
+
144
+ if(to_state != 1)
145
+ puts "Warning: Transition without output !" if to_state.size == 0
146
+ puts "Warning: Transition with multiple outputs !" if to_state.size > 1
147
+ end
148
+
149
+ if(from_states.size < 1)
150
+ puts "Warning: Transition without input !" if from_states.size == 0
151
+ end
152
+ end
153
+
154
+
155
+ def generate_state_code
156
+ states_code = ""
157
+ @states.each do |state|
158
+
159
+ code = " state :" + sanitize(state.text)
160
+ code = code + ", :initial => true" if state.initial
161
+
162
+ callback_code = generate_callback(state, "method", StateCallbacks)
163
+
164
+ states_code = states_code + code + callback_code + "\n"
165
+ end
166
+ states_code + "\n"
167
+ end
168
+
169
+
170
+
171
+ def generate_events_code
172
+
173
+ events_code = ""
174
+
175
+ ## Arrows between two blocks are events.
176
+ @chart.links.each_value do |link|
177
+ if (@chart.blocks[link.source].type == "state" or
178
+ @chart.blocks[link.source].type == "process") and
179
+ (@chart.blocks[link.destination].type == "state" or
180
+ @chart.blocks[link.destination].type == "process") and
181
+ not link.text.nil?
182
+
183
+ name = sanitize(link.text)
184
+
185
+ code = <<-SMALL_EVENT
186
+ event :#{name} do
187
+ transitions :from => :#{@chart.blocks[link.source].text}, :to => :#{@chart.blocks[link.destination].text}
188
+ end
189
+
190
+ SMALL_EVENT
191
+
192
+ events_code = events_code + code
193
+ end
194
+ end
195
+
196
+ @events.each do |event|
197
+ code = " event :" + sanitize(event.text)
198
+
199
+ ## Add event :before :after...
200
+ callback_code = generate_callback(event, "method", EventCallbacks)
201
+
202
+ code = code + callback_code + " do \n"
203
+
204
+ ## Add the code if it is defined.
205
+ code = code + generate_code_callback(event, EventCallbacks)
206
+
207
+ ## Simple case: This event links from and to a state
208
+ inputs = event.links_from_type "state"
209
+ outputs = event.links_to_type "state"
210
+
211
+ inputs = inputs + event.links_from_type("Process")
212
+ outputs = outputs + event.links_to_type("Process")
213
+
214
+
215
+ if inputs.size > 0 and outputs.size == 1
216
+ transition = transition_code(event,
217
+ inputs,
218
+ outputs.first)
219
+ code = code + transition + "\n"
220
+
221
+ end
222
+
223
+ unless @transitions[event].nil?
224
+ ## Sort by ID if present
225
+
226
+ @sorted = @transitions[event].each.sort do |tr|
227
+ input, output, priority = tr
228
+ priority
229
+ end
230
+
231
+ @sorted.each do |t|
232
+ inputs, output, priority, t_element = t
233
+ transition = transition_code(event, inputs, output)
234
+ transition_callback = generate_callback(t_element,
235
+ "method",
236
+ TransitionCallbacks)
237
+ code = code + transition + transition_callback + "\n"
238
+ end
239
+ end
240
+
241
+ code = code + " end\n\n"
242
+ events_code = events_code + code
243
+ end
244
+
245
+ events_code
246
+ end
247
+
248
+ def transition_code(event, inputs, output)
249
+
250
+ code = " transitions :from => "
251
+ if inputs.size == 1
252
+ code = code + ":" + sanitize(inputs[0].text)
253
+ else
254
+ code = code + "["
255
+ inputs.each do |input|
256
+ code = code + ":" + sanitize(input.text) + ","
257
+ end
258
+ ## remove last ","
259
+ code = code.chop + "]"
260
+ end
261
+
262
+ code = code + ", :to => :" + sanitize(output.text)
263
+ ## TODO: add options
264
+
265
+ # TransitionCallbacks
266
+ ## Add event :before :after... METHOD out of this
267
+ ## Not yet testable
268
+ # callback_code = generate_callback(event, "method", TransitionCallbacks)
269
+ callback_code = ""
270
+
271
+ return code + callback_code
272
+ end
273
+
274
+ def generate_callback(event, element_type, callbacks)
275
+
276
+ ## TODO: Handle the Guards -> create an array
277
+ l1 = event.links_to.each.select{|link, e| e.type.eql? element_type }
278
+ l2 = event.links_from.each.select{|link, e| e.type.eql? element_type }
279
+ links = l1 + l2
280
+ code = ""
281
+ unless links.empty?
282
+ links.each do |l|
283
+
284
+ link = l[0]
285
+ element = l[1]
286
+ if(callbacks.any? link.text)
287
+ code = code + ", :" + sanitize(link.text) +
288
+ " => :" + sanitize(element.text)
289
+
290
+ @method_names << element.text
291
+ end
292
+ end
293
+ end
294
+ return code
295
+ end
296
+
297
+ def generate_code_callback(event, callbacks)
298
+ l1 = event.links_to.each.select{|link, e| e.type.eql? "code" }
299
+ l2 = event.links_from.each.select{|link, e| e.type.eql? "code" }
300
+ links = l1 + l2
301
+ code = ""
302
+
303
+ unless links.empty?
304
+ links.each do |l|
305
+ link = l[0]
306
+ element = l[1]
307
+
308
+ if(callbacks.any? link.text)
309
+ code = code + " " + link.text + " do"
310
+
311
+ if link.text == "error"
312
+ code = code + " |e|\n"
313
+ else
314
+ code = code + "\n"
315
+ end
316
+ indent = " "
317
+ element.text.split("\n").each do |t|
318
+ code = code + indent + t
319
+ end
320
+
321
+ code = code + "\n end\n"
322
+ end
323
+ end
324
+ end
325
+ return code
326
+ end
327
+
328
+ # Generate code that creates methods for each
329
+ # method declared in the graph.
330
+ def generate_methods_placeholder
331
+ code = "\n"
332
+ method_names().each do |method_name|
333
+
334
+ code = code + <<-METH
335
+ def #{method_name}
336
+ puts "Please implement the method #{method_name}"
337
+ true
338
+ end
339
+
340
+ METH
341
+ end
342
+ return code
343
+ end
344
+
345
+ # Generate methods that are not already
346
+ # Defined in the class.
347
+ def generate_methods_placeholder_for(klass, debug: true)
348
+ method_names().each do |method_name|
349
+ if klass.method_defined? method_name.to_sym
350
+ puts "Found: #{method_name}. " if debug
351
+ next
352
+ end
353
+
354
+ puts "To implement: #{method_name}. " if debug
355
+ klass.define_method method_name.to_sym do
356
+ puts "Please implement the method #{method_name}"
357
+ true
358
+ end
359
+
360
+ end
361
+ end
362
+
363
+ # Export the document to code (String)
364
+ # It exports only the aasm code, not the
365
+ # methods called by it.
366
+ def export
367
+ start = <<-START
368
+ aasm do
369
+ START
370
+
371
+ finish = <<-END
372
+ end
373
+ END
374
+ return start + generate_state_code +
375
+ generate_events_code + finish
376
+ # generate_methods_placeholder
377
+ end
378
+ end
379
+
380
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "lucid/machines"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here