ellington 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ellington/passenger.rb +4 -0
- data/lib/ellington/route.rb +4 -2
- data/lib/ellington/version.rb +1 -1
- data/lib/ellington/visualizer.rb +186 -74
- metadata +3 -5
- data/Blast.pdf +0 -0
data/lib/ellington/passenger.rb
CHANGED
@@ -43,6 +43,10 @@ module Ellington
|
|
43
43
|
@state_history ||= []
|
44
44
|
end
|
45
45
|
|
46
|
+
def state_history_includes?(*states)
|
47
|
+
(state_history & states).length == states.length
|
48
|
+
end
|
49
|
+
|
46
50
|
def transition_to(new_state)
|
47
51
|
if !locked?
|
48
52
|
message = "Cannot transition an unlocked #{self.class.name}'s state"
|
data/lib/ellington/route.rb
CHANGED
@@ -40,10 +40,11 @@ module Ellington
|
|
40
40
|
(@subclasses ||= []) << subclass
|
41
41
|
end
|
42
42
|
|
43
|
-
def generate_graphs(dir)
|
43
|
+
def generate_graphs(dir, options={})
|
44
|
+
options[:format] ||= :svg
|
44
45
|
FileUtils.mkdir_p(dir)
|
45
46
|
@subclasses.each do |subclass|
|
46
|
-
Ellington::Visualizer.new(subclass.new, dir).
|
47
|
+
Ellington::Visualizer.new(subclass.new, dir, options[:format]).graph_all
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -122,6 +123,7 @@ module Ellington
|
|
122
123
|
log route_info
|
123
124
|
end
|
124
125
|
Ellington.logger.info "\n" if Ellington.logger
|
126
|
+
binding.pry
|
125
127
|
end
|
126
128
|
|
127
129
|
required_connections.each do |connection|
|
data/lib/ellington/version.rb
CHANGED
data/lib/ellington/visualizer.rb
CHANGED
@@ -28,76 +28,122 @@ module Ellington
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
attr_reader :route, :dir
|
31
|
+
attr_reader :route, :dir, :format
|
32
32
|
|
33
|
-
def initialize(route, dir)
|
33
|
+
def initialize(route, dir, format=:svg)
|
34
34
|
@route = route
|
35
35
|
@dir = dir
|
36
|
+
@format = format
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
FONTNAME = "Helvetica"
|
40
|
+
RANKSEP = 0.4
|
41
|
+
NODE_COLOR = "white"
|
42
|
+
NODE_COLOR_VIRTUAL = "gray50"
|
43
|
+
NODE_COLOR_LINE_GOAL = "green2"
|
44
|
+
NODE_COLOR_ROUTE_GOAL = "gold"
|
45
|
+
NODE_COLOR_PASSENGER_HIT = "royalblue1"
|
46
|
+
NODE_FILLCOLOR = "white"
|
47
|
+
NODE_FILLCOLOR_LINE_GOAL = "green2"
|
48
|
+
NODE_FILLCOLOR_ROUTE_GOAL = "gold"
|
49
|
+
NODE_FONTCOLOR_VIRTUAL = "gray40"
|
50
|
+
NODE_SHAPE = "box"
|
51
|
+
NODE_STYLE = "filled,rounded"
|
52
|
+
NODE_STYLE_VIRTUAL = "rounded"
|
53
|
+
NODE_PENWIDTH_PASSENGER_HIT = 2
|
54
|
+
EDGE_PENWIDTH_PASSENGER_HIT = 2
|
55
|
+
EDGE_COLOR_PASSENGER_HIT = "royalblue1"
|
56
|
+
EDGE_STYLE_PASSENGER_MISS = "dotted"
|
57
|
+
CLUSTER_STYLE = "filled"
|
58
|
+
CLUSTER_COLOR = "gray70"
|
59
|
+
CLUSTER_FILLCOLOR = "gray70"
|
60
|
+
CLUSTER_PENCOLOR = "gray50"
|
61
|
+
|
62
|
+
def graph_all(passenger=nil)
|
63
|
+
graph_route_basic passenger
|
64
|
+
graph_route passenger
|
65
|
+
graph_lines_basic passenger
|
66
|
+
graph_lines passenger
|
43
67
|
end
|
44
68
|
|
45
|
-
def graph_lines_basic
|
46
|
-
g = Node.new(nil, GraphViz.new("
|
69
|
+
def graph_lines_basic(passenger=nil)
|
70
|
+
g = Node.new(nil, GraphViz.new("GraphLinesBasic"))
|
71
|
+
set_graph_defaults g.viz
|
47
72
|
g.viz["label"] = "#{route.name} Lines - basic"
|
48
|
-
g.viz["ranksep"] = 0.4
|
49
|
-
g.viz["fontname"] = "Helvetica"
|
50
|
-
g.viz.node["fontname"] = "Helvetica"
|
51
|
-
g.viz.node["shape"] = "box"
|
52
|
-
g.viz.node["style"] = "rounded"
|
53
73
|
|
54
74
|
route.lines.each_with_index do |line, index|
|
55
75
|
line_cluster = Node.new(line, g.viz.add_graph("cluster#{index}"))
|
76
|
+
set_cluster_defaults line_cluster.viz
|
56
77
|
line_cluster.viz["label"] = line.class.name
|
57
|
-
line_cluster.viz["style"] = "filled"
|
58
78
|
g << line_cluster
|
59
79
|
|
60
80
|
line.stations.each do |station|
|
61
81
|
station_node = Node.new(station, line_cluster.viz.add_nodes(station.class.name))
|
62
|
-
station_node.viz["style"] = "filled,rounded"
|
63
|
-
station_node.viz["color"] = "white"
|
64
82
|
line_cluster << station_node
|
83
|
+
|
84
|
+
if !(line.goal & station.states.keys).empty?
|
85
|
+
station_node.viz["color"] = NODE_COLOR_LINE_GOAL
|
86
|
+
station_node.viz["fillcolor"] = NODE_COLOR_LINE_GOAL
|
87
|
+
end
|
88
|
+
|
89
|
+
if !(route.goal & station.states.keys).empty?
|
90
|
+
station_node.viz["color"] = NODE_COLOR_ROUTE_GOAL
|
91
|
+
station_node.viz["fillcolor"] = NODE_COLOR_ROUTE_GOAL
|
92
|
+
end
|
93
|
+
|
94
|
+
if passenger && !(passenger.state_history & station.states.keys).empty?
|
95
|
+
station_node.viz["color"] = NODE_COLOR_PASSENGER_HIT
|
96
|
+
station_node.viz["penwidth"] = NODE_PENWIDTH_PASSENGER_HIT
|
97
|
+
end
|
65
98
|
end
|
66
99
|
|
67
100
|
line_cluster.each_with_index.each do |node, node_index|
|
68
101
|
next_node = line_cluster[node_index + 1]
|
69
|
-
|
102
|
+
if next_node
|
103
|
+
station = node.base
|
104
|
+
next_station = next_node.base
|
105
|
+
edge = line_cluster.viz.add_edges(node.viz, next_node.viz)
|
106
|
+
if passenger
|
107
|
+
if color_name(node.viz["color"]) == NODE_COLOR_PASSENGER_HIT &&
|
108
|
+
color_name(next_node.viz["color"]) == NODE_COLOR_PASSENGER_HIT
|
109
|
+
edge["color"] = EDGE_COLOR_PASSENGER_HIT
|
110
|
+
edge["penwidth"] = EDGE_PENWIDTH_PASSENGER_HIT
|
111
|
+
else
|
112
|
+
edge["style"] = EDGE_STYLE_PASSENGER_MISS
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
70
116
|
end
|
71
117
|
end
|
72
118
|
|
73
|
-
file_name = "#{route.name.downcase.gsub("::", "_")}-lines-basic
|
74
|
-
g.viz.output(
|
119
|
+
file_name = "#{route.name.downcase.gsub("::", "_")}-lines-basic.#{format}"
|
120
|
+
g.viz.output(format => File.join(dir, file_name))
|
75
121
|
end
|
76
122
|
|
77
|
-
def graph_lines
|
78
|
-
g = Node.new(nil, GraphViz.new("
|
123
|
+
def graph_lines(passenger=nil)
|
124
|
+
g = Node.new(nil, GraphViz.new("GraphLines"))
|
125
|
+
set_graph_defaults g.viz
|
79
126
|
g.viz["label"] = "#{route.name} Lines"
|
80
|
-
g.viz["ranksep"] = 0.4
|
81
|
-
g.viz["fontname"] = "Helvetica"
|
82
|
-
g.viz.node["fontname"] = "Helvetica"
|
83
|
-
g.viz.node["shape"] = "box"
|
84
|
-
g.viz.node["style"] = "rounded"
|
85
127
|
|
86
128
|
route.lines.each_with_index do |line, index|
|
87
129
|
line_cluster = Node.new(line, g.viz.add_graph("cluster#{index}"))
|
130
|
+
set_cluster_defaults line_cluster.viz
|
88
131
|
line_cluster.viz["label"] = line.class.name
|
89
|
-
line_cluster.viz["style"] = "filled"
|
90
132
|
g << line_cluster
|
91
133
|
|
92
134
|
line.states.keys.each do |state|
|
93
135
|
state_node = Node.new(state, line_cluster.viz.add_nodes(state))
|
94
|
-
state_node.viz["style"] = "filled,rounded"
|
95
|
-
state_node.viz["color"] = "white"
|
96
136
|
if line.goal.include?(state)
|
97
|
-
state_node.viz["color"] =
|
137
|
+
state_node.viz["color"] = NODE_COLOR_LINE_GOAL
|
138
|
+
state_node.viz["fillcolor"] = NODE_FILLCOLOR_LINE_GOAL
|
98
139
|
end
|
99
140
|
if route.goal.include?(state)
|
100
|
-
state_node.viz["color"] =
|
141
|
+
state_node.viz["color"] = NODE_COLOR_ROUTE_GOAL
|
142
|
+
state_node.viz["fillcolor"] = NODE_FILLCOLOR_ROUTE_GOAL
|
143
|
+
end
|
144
|
+
if passenger && passenger.state_history_includes?(state)
|
145
|
+
state_node.viz["color"] = NODE_COLOR_PASSENGER_HIT
|
146
|
+
state_node.viz["penwidth"] = NODE_PENWIDTH_PASSENGER_HIT
|
101
147
|
end
|
102
148
|
line_cluster << state_node
|
103
149
|
end
|
@@ -106,45 +152,64 @@ module Ellington
|
|
106
152
|
a = line_cluster.find(state)
|
107
153
|
(transitions || []).each do |transition|
|
108
154
|
b = line_cluster.find(transition)
|
109
|
-
line_cluster.viz.add_edges
|
155
|
+
edge = line_cluster.viz.add_edges(a.viz, b.viz)
|
156
|
+
if passenger
|
157
|
+
if passenger.state_history_includes?(state, transition)
|
158
|
+
edge["color"] = EDGE_COLOR_PASSENGER_HIT
|
159
|
+
edge["penwidth"] = EDGE_PENWIDTH_PASSENGER_HIT
|
160
|
+
else
|
161
|
+
edge["style"] = EDGE_STYLE_PASSENGER_MISS
|
162
|
+
end
|
163
|
+
end
|
110
164
|
end
|
111
165
|
end
|
112
166
|
end
|
113
167
|
|
114
|
-
file_name = "#{route.name.downcase.gsub("::", "_")}-lines
|
115
|
-
g.viz.output(
|
168
|
+
file_name = "#{route.name.downcase.gsub("::", "_")}-lines.#{format}"
|
169
|
+
g.viz.output(format => File.join(dir, file_name))
|
116
170
|
end
|
117
171
|
|
118
|
-
def graph_route_basic
|
119
|
-
g = Node.new(nil, GraphViz.new("
|
172
|
+
def graph_route_basic(passenger=nil)
|
173
|
+
g = Node.new(nil, GraphViz.new("GraphRouteBasic"))
|
174
|
+
set_graph_defaults g.viz
|
175
|
+
g.viz["ranksep"] = 1
|
120
176
|
g.viz["label"] = "#{route.name} Route - basic"
|
121
|
-
g.viz["compound"] = true
|
122
|
-
g.viz["ranksep"] = 1.2
|
123
|
-
g.viz["fontname"] = "Helvetica"
|
124
|
-
g.viz.node["fontname"] = "Helvetica"
|
125
|
-
g.viz.node["shape"] = "box"
|
126
|
-
g.viz.node["style"] = "rounded"
|
127
177
|
|
128
178
|
route.lines.each_with_index do |line, index|
|
129
179
|
line_cluster = Node.new(line, g.viz.add_graph("cluster#{index}"))
|
180
|
+
set_cluster_defaults line_cluster.viz
|
130
181
|
line_cluster.viz["label"] = line.class.name
|
131
|
-
line_cluster.viz["style"] = "filled"
|
132
182
|
g << line_cluster
|
133
183
|
|
184
|
+
passenger_hit = false
|
134
185
|
%w{PASS FAIL ERROR}.each do |state|
|
135
186
|
state_node = Node.new(state, line_cluster.viz.add_nodes("#{line.class.name}#{state}", "label" => state))
|
136
|
-
state_node.viz["style"] = "filled,rounded"
|
137
|
-
state_node.viz["color"] = "white"
|
138
|
-
if !(route.goal & line.stations.map{ |s| "#{state} #{s.name}" }).empty?
|
139
|
-
state_node.viz["color"] = "gold"
|
140
|
-
end
|
141
187
|
line_cluster << state_node
|
188
|
+
states = line.stations.map{ |s| "#{state} #{s.name}" }
|
189
|
+
|
190
|
+
if !(line.goal & states).empty?
|
191
|
+
state_node.viz["color"] = NODE_COLOR_LINE_GOAL
|
192
|
+
state_node.viz["fillcolor"] = NODE_COLOR_LINE_GOAL
|
193
|
+
end
|
194
|
+
|
195
|
+
if !(route.goal & states).empty?
|
196
|
+
state_node.viz["color"] = NODE_COLOR_ROUTE_GOAL
|
197
|
+
state_node.viz["fillcolor"] = NODE_COLOR_ROUTE_GOAL
|
198
|
+
end
|
199
|
+
|
200
|
+
if passenger
|
201
|
+
if !passenger_hit && !(passenger.state_history & line.send("#{state.downcase}ed")).empty?
|
202
|
+
passenger_hit = true
|
203
|
+
state_node.viz["color"] = NODE_COLOR_PASSENGER_HIT
|
204
|
+
state_node.viz["penwidth"] = NODE_PENWIDTH_PASSENGER_HIT
|
205
|
+
end
|
206
|
+
end
|
142
207
|
end
|
143
208
|
end
|
144
209
|
|
145
210
|
route.connections.each do |connection|
|
146
211
|
to_node = g.find(connection.line)
|
147
|
-
|
212
|
+
to_line = to_node.base
|
148
213
|
|
149
214
|
combos = {}
|
150
215
|
g.to_a.each do |node|
|
@@ -157,10 +222,10 @@ module Ellington
|
|
157
222
|
if connection.type == :if_any
|
158
223
|
combos.each do |state, nodes|
|
159
224
|
nodes.each do |node|
|
160
|
-
|
225
|
+
from_line = node.base
|
161
226
|
g.viz.add_edges(
|
162
|
-
node.viz.get_node("#{
|
163
|
-
to_node.viz.get_node("#{
|
227
|
+
node.viz.get_node("#{from_line.class.name}#{state}"),
|
228
|
+
to_node.viz.get_node("#{to_line.class.name}PASS"),
|
164
229
|
"lhead" => to_node.viz.id
|
165
230
|
)
|
166
231
|
end
|
@@ -172,9 +237,9 @@ module Ellington
|
|
172
237
|
node_name = nodes.map{ |n| n.base.class.name }.join + state
|
173
238
|
node_label = nodes.map{ |n| "#{n.base.class.name} #{state}"}.join("\n")
|
174
239
|
viz = g.viz.add_nodes(node_name, "label" => node_label)
|
175
|
-
viz["style"] =
|
176
|
-
viz["color"] =
|
177
|
-
viz["fontcolor"] =
|
240
|
+
viz["style"] = NODE_STYLE_VIRTUAL
|
241
|
+
viz["color"] = NODE_COLOR_VIRTUAL
|
242
|
+
viz["fontcolor"] = NODE_FONTCOLOR_VIRTUAL
|
178
243
|
|
179
244
|
nodes.each do |node|
|
180
245
|
from_viz = node.viz.get_node("#{node.base.class.name}#{state}")
|
@@ -190,41 +255,62 @@ module Ellington
|
|
190
255
|
end
|
191
256
|
end
|
192
257
|
|
193
|
-
file_name = "#{route.name.downcase.gsub("::", "_")}-route-basic
|
194
|
-
g.viz.output(
|
258
|
+
file_name = "#{route.name.downcase.gsub("::", "_")}-route-basic.#{format}"
|
259
|
+
g.viz.output(format => File.join(dir, file_name))
|
195
260
|
end
|
196
261
|
|
197
|
-
def graph_route
|
198
|
-
g = Node.new(nil, GraphViz.new("
|
262
|
+
def graph_route(passenger=nil)
|
263
|
+
g = Node.new(nil, GraphViz.new("GraphRoute"))
|
264
|
+
set_graph_defaults g.viz
|
199
265
|
g.viz["label"] = "#{route.name} Lines"
|
200
|
-
g.viz["compound"] = true
|
201
266
|
g.viz["ranksep"] = 0.8
|
202
|
-
g.viz["fontname"] = "Helvetica"
|
203
|
-
g.viz.node["fontname"] = "Helvetica"
|
204
|
-
g.viz.node["shape"] = "box"
|
205
|
-
g.viz.node["style"] = "rounded"
|
206
267
|
|
207
268
|
route.lines.each_with_index do |line, index|
|
208
269
|
line_cluster = Node.new(line, g.viz.add_graph("cluster#{index}"))
|
270
|
+
set_cluster_defaults line_cluster.viz
|
209
271
|
line_cluster.viz["label"] = line.class.name
|
210
|
-
line_cluster.viz["style"] = "filled"
|
211
272
|
g << line_cluster
|
212
273
|
|
213
274
|
line.states.keys.each do |state|
|
214
275
|
state_node = Node.new(state, line_cluster.viz.add_nodes(state))
|
215
|
-
state_node.viz["style"] = "filled,rounded"
|
216
|
-
state_node.viz["color"] = "white"
|
217
276
|
if line.goal.include?(state)
|
218
|
-
state_node.viz["color"] =
|
277
|
+
state_node.viz["color"] = NODE_COLOR_LINE_GOAL
|
278
|
+
state_node.viz["fillcolor"] = NODE_FILLCOLOR_LINE_GOAL
|
219
279
|
end
|
220
280
|
if route.goal.include?(state)
|
221
|
-
state_node.viz["color"] =
|
281
|
+
state_node.viz["color"] = NODE_COLOR_ROUTE_GOAL
|
282
|
+
state_node.viz["fillcolor"] = NODE_FILLCOLOR_ROUTE_GOAL
|
283
|
+
end
|
284
|
+
if passenger && passenger.state_history_includes?(state)
|
285
|
+
state_node.viz["color"] = NODE_COLOR_PASSENGER_HIT
|
286
|
+
state_node.viz["penwidth"] = NODE_PENWIDTH_PASSENGER_HIT
|
222
287
|
end
|
223
288
|
line_cluster << state_node
|
224
289
|
end
|
225
290
|
end
|
226
291
|
|
227
292
|
viz = g.viz.add_nodes(route.initial_state)
|
293
|
+
rendered_edges = {}
|
294
|
+
|
295
|
+
if passenger
|
296
|
+
passenger_nodes = g.reduce([]) do |memo, line_cluster|
|
297
|
+
line_cluster.children.each do |node|
|
298
|
+
if node.viz["color"].to_s.gsub(/\W/, "") == NODE_COLOR_PASSENGER_HIT
|
299
|
+
memo << node
|
300
|
+
end
|
301
|
+
end
|
302
|
+
memo
|
303
|
+
end
|
304
|
+
previous_node = nil
|
305
|
+
passenger_nodes.each do |node|
|
306
|
+
from_viz = previous_node.nil? ? viz : previous_node.viz
|
307
|
+
rendered_edges[from_viz.id + node.viz.id] = true
|
308
|
+
edge = g.viz.add_edges(from_viz, node.viz)
|
309
|
+
edge["color"] = EDGE_COLOR_PASSENGER_HIT
|
310
|
+
edge["penwidth"] = EDGE_PENWIDTH_PASSENGER_HIT
|
311
|
+
previous_node = node
|
312
|
+
end
|
313
|
+
end
|
228
314
|
|
229
315
|
route.states.each do |from_state, to_states|
|
230
316
|
(to_states || []).each do |to_state|
|
@@ -237,17 +323,43 @@ module Ellington
|
|
237
323
|
to_viz = to_node.viz.get_node(to_state) if to_node
|
238
324
|
to_viz ||= g.viz.get_node(to_state)
|
239
325
|
|
240
|
-
if from_viz && to_viz
|
241
|
-
|
326
|
+
if from_viz && to_viz && !rendered_edges[from_viz.id + to_viz.id]
|
327
|
+
rendered_edges[from_viz.id + to_viz.id] = true
|
328
|
+
edge = g.viz.add_edges(
|
242
329
|
from_viz,
|
243
330
|
to_viz
|
244
331
|
)
|
332
|
+
edge["style"] = EDGE_STYLE_PASSENGER_MISS if passenger
|
245
333
|
end
|
246
334
|
end
|
247
335
|
end
|
248
336
|
|
249
|
-
file_name = "#{route.name.downcase.gsub("::", "_")}-route
|
250
|
-
g.viz.output(
|
337
|
+
file_name = "#{route.name.downcase.gsub("::", "_")}-route.#{format}"
|
338
|
+
g.viz.output(format => File.join(dir, file_name))
|
339
|
+
end
|
340
|
+
|
341
|
+
private
|
342
|
+
|
343
|
+
def color_name(graphviz_color)
|
344
|
+
graphviz_color.to_s.gsub("\"", "")
|
345
|
+
end
|
346
|
+
|
347
|
+
def set_graph_defaults(graph)
|
348
|
+
graph["compound"] = true
|
349
|
+
graph["ranksep"] = RANKSEP
|
350
|
+
graph["fontname"] = FONTNAME
|
351
|
+
graph.node["fontname"] = FONTNAME
|
352
|
+
graph.node["shape"] = NODE_SHAPE
|
353
|
+
graph.node["style"] = NODE_STYLE
|
354
|
+
graph.node["color"] = NODE_COLOR
|
355
|
+
graph.node["fillcolor"] = NODE_FILLCOLOR
|
356
|
+
end
|
357
|
+
|
358
|
+
def set_cluster_defaults(cluster)
|
359
|
+
cluster["style"] = CLUSTER_STYLE
|
360
|
+
cluster["color"] = CLUSTER_COLOR
|
361
|
+
cluster["fillcolor"] = CLUSTER_FILLCOLOR
|
362
|
+
cluster["pencolor"] = CLUSTER_PENCOLOR
|
251
363
|
end
|
252
364
|
|
253
365
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ellington
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-03-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hero
|
@@ -90,7 +90,6 @@ files:
|
|
90
90
|
- lib/ellington/version.rb
|
91
91
|
- lib/ellington/visualizer.rb
|
92
92
|
- lib/ellington.rb
|
93
|
-
- Blast.pdf
|
94
93
|
- Gemfile
|
95
94
|
- Gemfile.lock
|
96
95
|
- LICENSE.txt
|
@@ -134,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
133
|
version: '0'
|
135
134
|
requirements: []
|
136
135
|
rubyforge_project:
|
137
|
-
rubygems_version: 1.8.
|
136
|
+
rubygems_version: 1.8.25
|
138
137
|
signing_key:
|
139
138
|
specification_version: 3
|
140
139
|
summary: A micro framework to ensure your projects are easy to manage, develop, &
|
@@ -157,4 +156,3 @@ test_files:
|
|
157
156
|
- test/ticket_test.rb
|
158
157
|
- test/transition_info_test.rb
|
159
158
|
- test/unique_type_array_test.rb
|
160
|
-
has_rdoc:
|
data/Blast.pdf
DELETED
Binary file
|