vispan 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/generate +13 -0
- data/lib/process_visualisation.rb +73 -0
- data/lib/process_visualisation/config.rb +13 -0
- data/lib/process_visualisation/graphwriter.rb +34 -0
- data/lib/process_visualisation/node.rb +16 -0
- data/lib/process_visualisation/output_console.rb +33 -0
- data/lib/process_visualisation/output_graphic.rb +38 -0
- data/lib/process_visualisation/relation.rb +49 -0
- data/lib/process_visualisation/szenario.rb +42 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dbe9fe566ea5f0e162c6a7cafcef542cdcef52a7
|
4
|
+
data.tar.gz: 8da510a7bcaab07ae848f650a2d19ce57c909c56
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2485a48fee6b3a87b3f026845c0bafcfa25df604ac4cb3b416b530454d770b950fc039fca349cb935b4c77a4e0aa6fc53acbac729a8e7991edba014db4b306e0
|
7
|
+
data.tar.gz: 063433caa99ad5ed07caef983b4f2ae5773609e3dac851fc625c97ae1465a1d4711d96b1373c5a508b85f35f5a3cb4ae3e5ec69026a8ca56a734a52f16ab1823
|
data/bin/generate
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# require "./input.rb"
|
3
|
+
require "./lib/process_visualisation.rb"
|
4
|
+
|
5
|
+
if ARGV.length == 2
|
6
|
+
input_file = ARGV[0]
|
7
|
+
output_file = ARGV[1]
|
8
|
+
process = ProcessVisualisation.new(input_file)
|
9
|
+
process.display_text
|
10
|
+
process.visualize(output_file)
|
11
|
+
else
|
12
|
+
puts 'wrong number of arguments!'
|
13
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# require "process_visualisation/version.rb"
|
2
|
+
require 'rack'
|
3
|
+
require "szenario.rb"
|
4
|
+
require "relation.rb"
|
5
|
+
require "node.rb"
|
6
|
+
require "output_console.rb"
|
7
|
+
require "output_graphic.rb"
|
8
|
+
|
9
|
+
module ProcessVisualisation
|
10
|
+
attr_reader :processed_string, :nodes, :text, :szenarios
|
11
|
+
|
12
|
+
class WebPreview < Rack::Static
|
13
|
+
def call(env)
|
14
|
+
# initialize()
|
15
|
+
self.visualize(Rails.root.join('app/assets/images/process.png'))
|
16
|
+
#generate process.png
|
17
|
+
# [200, {"Content-Type" => "text/plain"}, env]
|
18
|
+
[200, {"Content-Type" => "image/png"}, [IO.read(Rails.root.join('app/assets/images/process.png'))]]
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(input_file)
|
22
|
+
@szenarios = []
|
23
|
+
separate_szenarios(input_file)
|
24
|
+
end
|
25
|
+
|
26
|
+
def separate_szenarios(input_file)
|
27
|
+
@single_szenario = Szenario.new()
|
28
|
+
@relation_lines = []
|
29
|
+
@lines = File.readlines(input_file)
|
30
|
+
@lines.each do |line|
|
31
|
+
|
32
|
+
if line[0] == "-"
|
33
|
+
create_new_szenario(line)
|
34
|
+
elsif (line == "\n" && !@relation_lines.empty?) || (line == @lines.last)
|
35
|
+
create_new_relation(line)
|
36
|
+
elsif line != "\n"
|
37
|
+
@relation_lines << line
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
@szenarios << @single_szenario
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_new_szenario(line)
|
46
|
+
if @single_szenario.title == ""
|
47
|
+
@single_szenario.set_title(line)
|
48
|
+
else
|
49
|
+
@szenarios << @single_szenario
|
50
|
+
@single_szenario = Szenario.new(line)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_new_relation(line)
|
55
|
+
@relation_lines << line if line != "\n"
|
56
|
+
relation = Relation.new(@relation_lines, @szenarios.length)
|
57
|
+
@single_szenario.add_relation(relation)
|
58
|
+
@relation_lines = []
|
59
|
+
end
|
60
|
+
|
61
|
+
def display_text
|
62
|
+
text = OutputConsole.new(@szenarios)
|
63
|
+
text.generate
|
64
|
+
end
|
65
|
+
|
66
|
+
def visualize(output_file)
|
67
|
+
png = OutputGraphic.new(@szenarios, output_file)
|
68
|
+
png.generate
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
NODE_WIDTH = 3.3
|
2
|
+
NODE_MARGIN = 0.2
|
3
|
+
|
4
|
+
SZENARIO = {szenario:{bgcolor:"mintcream:lightcyan", margin:60, fontsize:18}}
|
5
|
+
|
6
|
+
NODE = {screen:{color:"none", shape:"rect", style:"rounded, filled", fillcolor:"yellowgreen:lemonchiffon", width:"#{NODE_WIDTH}", margin:"#{NODE_MARGIN}"},
|
7
|
+
email:{color:"none", shape:"rect",style:"rounded, filled", fillcolor:"grey:ghostwhite", width:"#{NODE_WIDTH}", margin:"#{NODE_MARGIN}"},
|
8
|
+
pdf:{color:"none", shape:"rect", style:"rounded, filled", fillcolor:"gold:orange", width:"#{NODE_WIDTH}", margin:"#{NODE_MARGIN}"},
|
9
|
+
command:{color:"none", shape:"rect",style:"rounded, filled", fillcolor:"lightblue:steelblue", width:"#{NODE_WIDTH}", margin:"#{NODE_MARGIN}"}
|
10
|
+
}
|
11
|
+
RELATION = {event:{color:"red"},
|
12
|
+
link:{arrowhead:"none", arrowsize:"30"}
|
13
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "config.rb"
|
2
|
+
|
3
|
+
class GraphWriter
|
4
|
+
|
5
|
+
def build_string(szenarios)
|
6
|
+
"Digraph G{ rankdir=LR; splines=ortho;labeljust=l#{szenarios.map.with_index {|szenario, index| build_szenario(szenario, index)}.join("")}}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_szenario(szenario, index)
|
10
|
+
node_definitions = szenario.nodes.map{|node| write_node(node)}.join("")
|
11
|
+
relation_definitions = szenario.relations.map{|relation| write_relations(relation)}.join("")
|
12
|
+
effect_definitions = szenario.relations.map {|relation| write_effects(relation)}.join("")
|
13
|
+
|
14
|
+
"\n\nsubgraph cluster#{index.to_s} {label=\"#{szenario.title}\"#{find_attributes(szenario)};\n#{node_definitions}\n#{relation_definitions}#{effect_definitions}}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_node(node)
|
18
|
+
"#{node.name} [label=\"#{node.label}\" #{find_attributes(node)}]\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
def write_relations(relation)
|
22
|
+
"#{relation.start.name} -> #{relation.stop.name} [label=\"#{relation.label}\" #{find_attributes(relation)}]\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_effects(relation)
|
26
|
+
"{rank = same; #{relation.stop.name}; #{relation.effects.map(&:name).join('; ')};}" unless relation.effects.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_attributes(element)
|
30
|
+
type = element.class.to_s.upcase
|
31
|
+
GraphWriter.const_get(type)[element.type.to_sym].map{|attribute| "; #{attribute[0]}=\"#{attribute[1]}\""}.join("")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Node
|
2
|
+
|
3
|
+
attr_accessor :name, :type, :label
|
4
|
+
NODE_TYPES = ["screen", "email", "pdf", "command"]
|
5
|
+
|
6
|
+
def initialize(type, label, index)
|
7
|
+
@name = transform_to_name(label, index)
|
8
|
+
@type = NODE_TYPES.include?(type)? type : ""
|
9
|
+
@label = label
|
10
|
+
end
|
11
|
+
|
12
|
+
def transform_to_name(label, index)
|
13
|
+
label.gsub(/[-\s.]/, "") + index.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class OutputConsole
|
2
|
+
|
3
|
+
def initialize(szenarios)
|
4
|
+
@text = ""
|
5
|
+
@szenarios = szenarios
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate
|
9
|
+
build_text
|
10
|
+
puts @text
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_text
|
14
|
+
@szenarios.each do |szenario|
|
15
|
+
@text += "\nProzess Ablauf in '#{szenario.title}'\n"
|
16
|
+
done = []
|
17
|
+
szenario.relations.each do |rel|
|
18
|
+
|
19
|
+
if !done.include? rel.start
|
20
|
+
@text += "\n"
|
21
|
+
@text += "'#{rel.start.label}' führt zu '#{rel.stop.label}'"
|
22
|
+
done << rel.start
|
23
|
+
|
24
|
+
else
|
25
|
+
@text += " und zu '#{rel.stop.label}'"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
@text += "\n"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class OutputGraphic
|
2
|
+
|
3
|
+
def initialize(szenarios, output_file)
|
4
|
+
@szenarios = szenarios
|
5
|
+
@processed_string = ""
|
6
|
+
@output_file = output_file
|
7
|
+
end
|
8
|
+
|
9
|
+
def generate
|
10
|
+
build_graph
|
11
|
+
generate_processed_file(@processed_string)
|
12
|
+
generate_graph(@output_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_graph
|
16
|
+
graph = GraphWriter.new()
|
17
|
+
@processed_string = graph.build_string(@szenarios)
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate_processed_file(processed_string)
|
21
|
+
ready = File.open("lib/process_visualisation/input_processed.dot", "w") {
|
22
|
+
|file| file.write(processed_string)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_graph(output_file)
|
27
|
+
|
28
|
+
file_ending = check_output(output_file)
|
29
|
+
cmd = "dot -T#{file_ending} lib/process_visualisation/input_processed.dot -o #{output_file}"
|
30
|
+
system(cmd)
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_output(output_file)
|
34
|
+
output_file = output_file.to_s
|
35
|
+
output_file.split(".")[1]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Relation
|
2
|
+
attr_accessor :start, :stop, :type, :effects, :label
|
3
|
+
|
4
|
+
def initialize(relation_array, index)
|
5
|
+
@effects = []
|
6
|
+
@label = ""
|
7
|
+
|
8
|
+
extract(relation_array, index)
|
9
|
+
end
|
10
|
+
|
11
|
+
def extract(relation_array, index)
|
12
|
+
@start = set_node(relation_array.shift, index)
|
13
|
+
set_connection(relation_array.shift)
|
14
|
+
@stop = set_node(relation_array.shift, index)
|
15
|
+
@effects = relation_array.map{|effect| set_node(effect, index)}
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_connection(label_string)
|
19
|
+
label = label_string.split(":")
|
20
|
+
@label = label[1].strip if label[0].include? "Event"
|
21
|
+
adjust_length(@label)
|
22
|
+
@type = label[0].strip.downcase
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_node(node_string, index)
|
26
|
+
node_array = node_string.split(":")
|
27
|
+
type = node_array[0].strip.downcase
|
28
|
+
label = node_array[1].strip
|
29
|
+
# puts label
|
30
|
+
adjust_length(label)
|
31
|
+
Node.new(type, label, index)
|
32
|
+
end
|
33
|
+
|
34
|
+
def adjust_length(string)
|
35
|
+
|
36
|
+
if string.length > 30
|
37
|
+
(20..string.length).step(20){ |limit|
|
38
|
+
|
39
|
+
if string[limit, string.length-limit].include?(" ")
|
40
|
+
empty = string[limit, string.length-limit].index(" ")
|
41
|
+
string[limit+empty] = "\n"
|
42
|
+
end
|
43
|
+
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "graphwriter.rb"
|
2
|
+
|
3
|
+
class Szenario
|
4
|
+
attr_accessor :title, :relations, :nodes, :type
|
5
|
+
|
6
|
+
def initialize(line = "")
|
7
|
+
@title = line.gsub(/--/, "").strip
|
8
|
+
@relations = []
|
9
|
+
@nodes = []
|
10
|
+
@type = "szenario"
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_szenario(index)
|
14
|
+
graph = GraphWriter.new()
|
15
|
+
node_definitions = @nodes.map{|node| graph.write_node(node)}.join("")
|
16
|
+
relation_definitions = @relations.map{|relation| graph.write_relations(relation)}.join("")
|
17
|
+
effect_definitions = @relations.map {|relation| graph.write_effects(relation)}.join("")
|
18
|
+
|
19
|
+
"\n\nsubgraph cluster#{index.to_s} {bgcolor=aliceblue; label=\"#{title}\";\n#{node_definitions}\n#{relation_definitions}#{effect_definitions}}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_title(line)
|
23
|
+
@title = line.gsub(/--/, "").strip
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_relation(relation)
|
27
|
+
@relations << relation
|
28
|
+
add_nodes([relation.start, relation.stop, relation.effects])
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_nodes(nodes_array)
|
32
|
+
nodes_array = nodes_array.flatten
|
33
|
+
nodes_array.map{|node| @nodes << node if is_not_saved(node, @nodes)}
|
34
|
+
end
|
35
|
+
|
36
|
+
def is_not_saved(node, szenario_nodes)
|
37
|
+
szenario_nodes.each do |szenario_node|
|
38
|
+
return false if szenario_node.name == node.name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vispan
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Witek
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.12'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.12'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: minitest
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 5.11.3
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 5.11.3
|
75
|
+
description:
|
76
|
+
email: daniel.witek@edgycircle.com
|
77
|
+
executables:
|
78
|
+
- generate
|
79
|
+
extensions: []
|
80
|
+
extra_rdoc_files: []
|
81
|
+
files:
|
82
|
+
- bin/generate
|
83
|
+
- lib/process_visualisation.rb
|
84
|
+
- lib/process_visualisation/config.rb
|
85
|
+
- lib/process_visualisation/graphwriter.rb
|
86
|
+
- lib/process_visualisation/node.rb
|
87
|
+
- lib/process_visualisation/output_console.rb
|
88
|
+
- lib/process_visualisation/output_graphic.rb
|
89
|
+
- lib/process_visualisation/relation.rb
|
90
|
+
- lib/process_visualisation/szenario.rb
|
91
|
+
homepage: ''
|
92
|
+
licenses:
|
93
|
+
- BSD-3-Clause
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib/process_visualisation
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.5.2.3
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Visualize processes with simple syntax and multiple output formats
|
115
|
+
test_files: []
|