diaspora-cluster-creator 0.2.0 → 0.3.0

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.
Files changed (42) hide show
  1. data/.gitignore +1 -2
  2. data/Guardfile +1 -2
  3. data/README.md +2 -0
  4. data/TODO.todo +2 -0
  5. data/bin/diaspora-cluster +11 -8
  6. data/diaspora-cluster-creator.gemspec +2 -0
  7. data/features/cluster.feature +1 -1
  8. data/features/command_line.feature +165 -0
  9. data/features/node.feature +13 -0
  10. data/features/step_definitions/cluster_steps.rb +3 -3
  11. data/features/step_definitions/command_line_steps.rb +7 -0
  12. data/features/step_definitions/node_steps.rb +16 -0
  13. data/features/support/aruba.rb +1 -0
  14. data/features/support/world.rb +4 -8
  15. data/lib/diaspora-cluster-creator.rb +12 -9
  16. data/lib/diaspora-cluster-creator/attribute.rb +29 -0
  17. data/lib/diaspora-cluster-creator/attribute_collection_factory.rb +29 -0
  18. data/lib/diaspora-cluster-creator/cluster.rb +31 -18
  19. data/lib/diaspora-cluster-creator/edge_drawer.rb +41 -0
  20. data/lib/diaspora-cluster-creator/guarantor.rb +21 -0
  21. data/lib/diaspora-cluster-creator/node.rb +71 -0
  22. data/lib/diaspora-cluster-creator/node_attribute.rb +41 -0
  23. data/lib/diaspora-cluster-creator/node_collection_factory.rb +30 -0
  24. data/lib/diaspora-cluster-creator/template.rb +23 -16
  25. data/lib/diaspora-cluster-creator/version.rb +1 -1
  26. data/spec/diaspora-cluster-creator/attribute_collection_factory_spec.rb +31 -0
  27. data/spec/diaspora-cluster-creator/attribute_spec.rb +69 -0
  28. data/spec/diaspora-cluster-creator/cluster_spec.rb +66 -15
  29. data/spec/diaspora-cluster-creator/edge_drawer_spec.rb +21 -0
  30. data/spec/diaspora-cluster-creator/guarantor_spec.rb +54 -0
  31. data/spec/diaspora-cluster-creator/node_attribute_spec.rb +36 -0
  32. data/spec/diaspora-cluster-creator/node_collection_factory_spec.rb +27 -0
  33. data/spec/diaspora-cluster-creator/node_spec.rb +65 -0
  34. data/spec/diaspora-cluster-creator/template_integration_spec.rb +9 -10
  35. data/spec/diaspora-cluster-creator/template_spec.rb +9 -2
  36. metadata +78 -34
  37. data/features/star_system.feature +0 -13
  38. data/features/step_definitions/star_system_steps.rb +0 -16
  39. data/lib/diaspora-cluster-creator/graph.rb +0 -58
  40. data/lib/diaspora-cluster-creator/star_system.rb +0 -80
  41. data/spec/diaspora-cluster-creator/graph_spec.rb +0 -34
  42. data/spec/diaspora-cluster-creator/star_system_spec.rb +0 -103
data/.gitignore CHANGED
@@ -15,5 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- cluster.png
19
- cluster.dot
18
+ cluster.*
data/Guardfile CHANGED
@@ -33,7 +33,7 @@ end
33
33
 
34
34
  guard 'bundler' do
35
35
  watch('Gemfile')
36
- watch('*.gemspec')
36
+ watch(%r{.*\.gemspec})
37
37
  # Uncomment next line if Gemfile contain `gemspec' command
38
38
  # watch(/^.+\.gemspec/)
39
39
  end
@@ -42,5 +42,4 @@ guard 'cucumber' do
42
42
  watch(%r{^features/.+\.feature$})
43
43
  watch(%r{^features/support/.+$}) { 'features' }
44
44
  watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
45
- watch(%r{^lib/diaspora-cluster-creator/(.+)\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
46
45
  end
data/README.md CHANGED
@@ -38,6 +38,8 @@ Or you can specify names
38
38
  Or perhaps you prefer a PNG
39
39
 
40
40
  $ diaspora-cluster filename=output.png names="Sparta [T2 E1 R3], Athens [T-2], Corinth [R3 T2 E1], Ephesus, Rhodes [T4]"
41
+
42
+ Take a look at /features/command_line.feature for better definitions.
41
43
 
42
44
  ## Contributing
43
45
 
@@ -0,0 +1,2 @@
1
+ – Allow different attributes to be passed.
2
+ – The above implies an NodeAttribute class; And a Config class as well.
@@ -5,25 +5,28 @@ require_relative '../lib/diaspora-cluster-creator'
5
5
 
6
6
  Main do
7
7
  description 'Generate a diaspora cluster'
8
- keyword('names', 'n') {
8
+ keyword('names') {
9
9
  arity(-1)
10
10
  cast :list_of_string
11
11
  description "List of cluster names, comma separated."
12
12
  }
13
- keyword('count', 'c') {
13
+ keyword('count') {
14
14
  arity 1
15
15
  cast :integer
16
16
  description "Instead of a list of names, provide a cluster count."
17
17
  }
18
- keyword('filename', 'f') {
19
- required
18
+ keyword('filename') {
20
19
  arity 1
21
- validate {|output| output =~ /\w\.(png|dot)$/i}
22
- description "filename.DOT or filename.PNG"
23
- default "cluster.dot"
20
+ validate {|output| output =~ /\w\.(png|svg|dot)$/i}
21
+ description ".png, .svg, .dot formats"
22
+ }
23
+ keyword('attributes') {
24
+ arity(-1)
25
+ cast :list_of_string
26
+ description "Instead of the default attributes, specify a different set"
24
27
  }
25
28
  def run
26
- options = {:names => params[:names].value, :count => params[:count].value, :filename => params[:filename].value}
29
+ options = {:names => params[:names].value, :count => params[:count].value, :filename => params[:filename].value, :attributes => params[:attributes].value}
27
30
  Diaspora::Cluster::Creator.run(options)
28
31
  end
29
32
  end
@@ -22,6 +22,8 @@ Gem::Specification.new do |gem|
22
22
  gem.add_development_dependency 'guard-bundler'
23
23
  gem.add_development_dependency 'guard-cucumber'
24
24
  gem.add_development_dependency 'growl'
25
+ gem.add_development_dependency 'debugger'
26
+ gem.add_development_dependency 'aruba'
25
27
 
26
28
  gem.add_runtime_dependency "ruby-graphviz"
27
29
  gem.add_runtime_dependency "main"
@@ -1,6 +1,6 @@
1
1
  Feature: Cluster creation
2
2
 
3
3
  Scenario: Cluster creation
4
- When I request a new cluster with 5 star systems
4
+ When I request a new cluster with 5 node systems
5
5
  Then the output should have 5 nodes
6
6
  And the output should have at least 4 edges
@@ -0,0 +1,165 @@
1
+ @announce
2
+ Feature: Provide tested examples of the command-line interface
3
+
4
+ Scenario: Specify without parameters
5
+ When I run `diaspora-cluster`
6
+ Then it should pass with output like:
7
+ """
8
+ graph Cluster {
9
+ A \[label = "A
10
+ T-?\d R-?\d E-?\d"\];
11
+ B \[label = "B
12
+ T-?\d R-?\d E-?\d"\];
13
+ A -- B
14
+ }
15
+ """
16
+
17
+ Scenario: Specify with names
18
+ When I run `diaspora-cluster names="Sparta{T2 E-1 R0},Athens{T1 E1 R0}"`
19
+ Then it should pass with:
20
+ """
21
+ graph Cluster {
22
+ Sparta [label = "Sparta
23
+ T2 R0 E-1"];
24
+ Athens [label = "Athens
25
+ T1 R0 E1"];
26
+ Sparta -- Athens
27
+ }
28
+ """
29
+
30
+ Scenario: Specify with technology guarantee
31
+ When I run `diaspora-cluster names="Sparta{T0 E-1 R0},Athens{T1 E1 R0},Corinth{T1 E0 R0}"`
32
+ Then it should pass with output like:
33
+ """
34
+ graph Cluster {
35
+ Sparta \[label = "Sparta
36
+ T2 R0 E-1"\];
37
+ Athens \[label = "Athens
38
+ T2 R0 E1"\];
39
+ Corinth \[label = "Corinth
40
+ T1 R0 E0"\];
41
+ Sparta -- Athens
42
+ Athens -- Corinth
43
+ }
44
+ """
45
+
46
+ Scenario: With -h
47
+ When I run `diaspora-cluster -h`
48
+ Then it should fail with output like:
49
+ """
50
+ NAME
51
+ diaspora-cluster
52
+
53
+ SYNOPSIS
54
+ diaspora-cluster \[names=names\] \[count=count\] \[filename=filename\]
55
+
56
+ DESCRIPTION
57
+ Generate a diaspora cluster
58
+
59
+ PARAMETERS
60
+ names
61
+ count
62
+ filename
63
+ --help, -h
64
+ """
65
+
66
+ Scenario Outline: I want files of different formats
67
+ When I run `diaspora-cluster filename=cluster.<FORMAT>`
68
+ Then the following files should exist:
69
+ | cluster.<FORMAT> |
70
+
71
+ Examples:
72
+ | FORMAT |
73
+ | png |
74
+ | dot |
75
+ | svg |
76
+
77
+ Scenario: Specify different attributes
78
+ When I run `diaspora-cluster attributes="Magic, Religion, Science"`
79
+ Then it should pass with output like:
80
+ """
81
+ graph Cluster {
82
+ A \[label = "A
83
+ M-?\d R-?\d S-?\d"\];
84
+ B \[label = "B
85
+ M-?\d R-?\d S-?\d"\];
86
+ C \[label = "C
87
+ M-?\d R-?\d S-?\d"\];
88
+ D \[label = "D
89
+ M-?\d R-?\d S-?\d"\];
90
+ E \[label = "E
91
+ M-?\d R-?\d S-?\d"\];
92
+ A -- B
93
+ B -- C
94
+ C -- D
95
+ D -- E
96
+ """
97
+
98
+ Scenario: Specify different attributes with prefix override
99
+ When I run `diaspora-cluster attributes="M(a)gic, Religion, Science"`
100
+ Then it should pass with output like:
101
+ """
102
+ graph Cluster {
103
+ A \[label = "A
104
+ A-?\d R-?\d S-?\d"\];
105
+ B \[label = "B
106
+ A-?\d R-?\d S-?\d"\];
107
+ C \[label = "C
108
+ A-?\d R-?\d S-?\d"\];
109
+ D \[label = "D
110
+ A-?\d R-?\d S-?\d"\];
111
+ E \[label = "E
112
+ A-?\d R-?\d S-?\d"\];
113
+ A -- B
114
+ B -- C
115
+ C -- D
116
+ D -- E
117
+ """
118
+
119
+ Scenario: Specify different attributes with default
120
+ When I run `diaspora-cluster names="Sparta{M5},Athens{R-5}" attributes="Magic, Religion, Science"`
121
+ Then it should pass with output like:
122
+ """
123
+ graph Cluster {
124
+ Sparta \[label = "Sparta
125
+ M5 R-?\d S-?\d"\];
126
+ Athens \[label = "Athens
127
+ M-?\d R-5 S-?\d"\];
128
+ Sparta -- Athens
129
+ """
130
+
131
+ Scenario: Specify with count parameters
132
+ When I run `diaspora-cluster count=10`
133
+ Then it should pass with output like:
134
+ """
135
+ graph Cluster {
136
+ A \[label = "A
137
+ T-?\d R-?\d E-?\d"\];
138
+ B \[label = "B
139
+ T-?\d R-?\d E-?\d"\];
140
+ C \[label = "C
141
+ T-?\d R-?\d E-?\d"\];
142
+ D \[label = "D
143
+ T-?\d R-?\d E-?\d"\];
144
+ E \[label = "E
145
+ T-?\d R-?\d E-?\d"\];
146
+ F \[label = "F
147
+ T-?\d R-?\d E-?\d"\];
148
+ G \[label = "G
149
+ T-?\d R-?\d E-?\d"\];
150
+ H \[label = "H
151
+ T-?\d R-?\d E-?\d"\];
152
+ I \[label = "I
153
+ T-?\d R-?\d E-?\d"\];
154
+ J \[label = "J
155
+ T-?\d R-?\d E-?\d"\];
156
+ A -- B
157
+ B -- C
158
+ C -- D
159
+ D -- E
160
+ E -- F
161
+ F -- G
162
+ H -- I
163
+ I -- J
164
+ }
165
+ """
@@ -0,0 +1,13 @@
1
+ Feature: Node Creation
2
+
3
+ Scenario: Node Creation
4
+ When I create a Node
5
+ Then it should have a technology rating
6
+ And it should have a resources rating
7
+ And it should have a environment rating
8
+
9
+ Scenario: Named Node Creation
10
+ When I create a Node with name "Sparta [T1 E-2 R3]"
11
+ Then it should have a technology rating of 1
12
+ And it should have a resources rating of 3
13
+ And it should have a environment rating of -2
@@ -1,11 +1,11 @@
1
- When /^I request a new cluster with (#{CAPTURE_INTEGER}) star systems?$/ do |count|
1
+ When /^I request a new cluster with (#{CAPTURE_INTEGER}) node systems?$/ do |count|
2
2
  set_current_cluster(['a']*count)
3
3
  end
4
4
 
5
5
  Then /^the output should have (#{CAPTURE_INTEGER}) nodes$/ do |count|
6
- current_graph.nodes.count.must_equal count
6
+ current_cluster.nodes.count.must_equal count
7
7
  end
8
8
 
9
9
  Then /^the output should have at least (#{CAPTURE_INTEGER}) edges$/ do |count|
10
- current_graph.edges.count.must_be :>=, count
10
+ current_cluster.edges.count.must_be :>=, count
11
11
  end
@@ -0,0 +1,7 @@
1
+ Then /^it should (pass|fail) with output like:$/ do |pass_or_fail, lines|
2
+ to_execute = ''
3
+ lines.split("\n").each_with_object(to_execute) do |line, mem|
4
+ mem << %(And it should #{pass_or_fail} with regex:\n"""\n#{line}\n"""\n)
5
+ end
6
+ steps to_execute
7
+ end
@@ -0,0 +1,16 @@
1
+ When /^I create a Node$/ do
2
+ current_node
3
+ end
4
+
5
+ When /^I create a Node with (?:the )?name "([^"]*)"$/ do |name|
6
+ set_current_node(name)
7
+ end
8
+
9
+ Then /^it should have an? (#{CAPTURE_SYSTEM_ATTRIBUTE}) rating$/ do |system_attribute|
10
+ current_node.send(system_attribute).must_be :<=, 4
11
+ current_node.send(system_attribute).must_be :>=, -4
12
+ end
13
+
14
+ Then /^it should have an? (#{CAPTURE_SYSTEM_ATTRIBUTE}) rating of (#{CAPTURE_INTEGER})$/ do |system_attribute, rating|
15
+ current_node.send(system_attribute).must_equal rating
16
+ end
@@ -0,0 +1 @@
1
+ require 'aruba/cucumber'
@@ -12,16 +12,12 @@ module KnowsTheDomain
12
12
  @current_roller ||= FateDice.new
13
13
  end
14
14
 
15
- def current_star_system
16
- @current_star_system ||= StarSystem.new(current_cluster, 1)
15
+ def current_node
16
+ @current_node ||= Node.new(current_cluster, 1)
17
17
  end
18
18
 
19
- def set_current_star_system(value)
20
- @current_star_system = StarSystem.new(current_cluster, value)
21
- end
22
-
23
- def current_graph
24
- @current_graph ||= Graph.new(current_cluster)
19
+ def set_current_node(value)
20
+ @current_node = Node.new(current_cluster, value)
25
21
  end
26
22
  end
27
23
 
@@ -4,21 +4,24 @@ module Diaspora
4
4
  module Cluster
5
5
  module Creator
6
6
  def self.run(params)
7
+ filename = params[:filename].to_s
7
8
  names = ('A'..'Z').to_a[0,params[:count] || 6]
8
- cluster = Cluster.new( params[:names] || names )
9
- graph = Graph.new(cluster)
10
- template = Template.new(graph)
11
- case File.extname(params[:filename])
9
+
10
+ cluster = Cluster.new(params[:names] || names, params[:attributes])
11
+ template = Template.new(cluster)
12
+
13
+ case File.extname(filename)
12
14
  when '.dot' then template.to_dot(params[:filename])
13
15
  when '.png' then template.to_png(params[:filename])
16
+ when '.svg' then template.to_svg(params[:filename])
17
+ else
18
+ STDOUT.write template.to_s
14
19
  end
15
20
  end
16
21
  end
17
22
  end
18
23
  end
19
24
 
20
- require_relative "diaspora-cluster-creator/fate_dice"
21
- require_relative "diaspora-cluster-creator/graph"
22
- require_relative "diaspora-cluster-creator/cluster"
23
- require_relative "diaspora-cluster-creator/star_system"
24
- require_relative "diaspora-cluster-creator/template"
25
+ Dir.glob(File.join(File.dirname(__FILE__),'diaspora-cluster-creator', '*')).each do |filename|
26
+ require filename
27
+ end
@@ -0,0 +1,29 @@
1
+ module Diaspora
2
+ module Cluster
3
+ module Creator
4
+ class Attribute
5
+ attr_reader :name, :prefix
6
+ def initialize(name)
7
+ if /\((?<extracted_prefix>\w)\)/ =~ name
8
+ @prefix = extracted_prefix.upcase
9
+ else
10
+ @prefix = name.slice(0).upcase
11
+ end
12
+ @name = name.gsub(/[\(\)]/,'')
13
+ end
14
+
15
+ def to_s
16
+ name
17
+ end
18
+
19
+ def to_sym
20
+ name.to_s.gsub(/\W+/,'_').downcase.to_sym
21
+ end
22
+
23
+ def label
24
+ prefix
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require 'dependency_injector'
2
+ module Diaspora
3
+ module Cluster
4
+ module Creator
5
+ class AttributeCollectionFactory
6
+ DEFAULT_ATTRIBUTE_NAMES = [
7
+ "Technology",
8
+ "Resources",
9
+ "Environment",
10
+ ].freeze
11
+ extend DependencyInjector
12
+ def_injector(:attribute_builder) { Attribute.public_method(:new) }
13
+
14
+ attr_reader :cluster
15
+ def initialize(cluster)
16
+ @cluster = cluster
17
+ end
18
+
19
+ def build_from(names = [])
20
+ from_these_names = (!names.nil? && names.any?) ? names : DEFAULT_ATTRIBUTE_NAMES
21
+ from_these_names.each_with_object([]) do |name, mem|
22
+ mem << attribute_builder.call(name)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -1,41 +1,54 @@
1
1
  require 'dependency_injector'
2
- require_relative 'star_system'
2
+ require_relative 'node_collection_factory'
3
+ require_relative 'attribute_collection_factory'
4
+ require_relative 'edge_drawer'
3
5
 
4
6
  module Diaspora
5
7
  module Cluster
6
8
  module Creator
7
9
  class Cluster
8
- include Enumerable
9
10
  extend DependencyInjector
10
- def_injector(:star_system_builder) { StarSystem.public_method(:new) }
11
- def_injector(:star_system_guarantor) { StarSystem.public_method(:guarantee!) }
11
+ def_injector(:edge_collection_builder) { lambda { EdgeDrawer.new(self).draw(nodes) } }
12
+ def_injector(:node_collection_builder) { lambda { NodeCollectionFactory.new(self).build_from(names) } }
13
+ def_injector(:attribute_collection_builder) { lambda { AttributeCollectionFactory.new(self).build_from(attribute_names) } }
12
14
 
13
15
  attr_reader :names
16
+ attr_reader :settings
17
+ attr_reader :attribute_names
14
18
 
15
- def initialize(*names)
16
- @names = names.flatten.compact
19
+ def initialize(names = [], attribute_names = [])
20
+ @names = names
21
+ @attribute_names = attribute_names
17
22
  end
18
23
 
19
- def each
20
- star_systems.each {|ss| yield(ss)}
24
+ def each_node
25
+ nodes.each { |node| yield(node) }
21
26
  end
22
27
 
23
- def star_systems
24
- @star_systems ||= build_star_systems
28
+ def each_edge
29
+ edges.each { |edge| yield(edge) }
25
30
  end
26
31
 
27
- def to_s
28
- 'Cluster'
32
+ def each_attribute
33
+ attributes.each { |attribute| yield(attribute) }
29
34
  end
30
35
 
31
- protected
32
- def build_star_systems
33
- @star_systems ||= star_system_guarantor.call(generate_first_pass)
36
+ def nodes
37
+ @nodes ||= node_collection_builder.call
34
38
  end
35
- def generate_first_pass
36
- names.each_with_object([]) {|name,mem| mem << star_system_builder.call(self, name)}
39
+
40
+ def edges
41
+ @edges ||= edge_collection_builder.call
42
+ end
43
+
44
+ def attributes
45
+ @attributes ||= attribute_collection_builder.call
46
+ end
47
+
48
+ def to_s
49
+ 'Cluster'
37
50
  end
38
51
  end
39
52
  end
40
53
  end
41
- end
54
+ end