gruff 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.
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ CHANGELOG
2
+
3
+ == 0.0.1
4
+
5
+ Initial release.
6
+ Line graphs only. Other graph styles coming soon.
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2005 Geoffrey Grosenbach boss@topfunky.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,11 @@
1
+ == Gruff Graphs
2
+
3
+ A library for making beautiful graphs.
4
+
5
+ See samples at http://nubyonrails.topfunky.com/articles/2005/10/24/gruff-graphing-library-for-ruby
6
+
7
+ See the test suite in test/line_test.rb for examples. (More documentation coming soon.)
8
+
9
+ == WARNING
10
+
11
+ This is alpha-quality software. It works well according to my tests, but the API may change and other features will be added. Backwards compatibility is not guaranteed until the 1.0 release.
data/lib/gruff.rb ADDED
@@ -0,0 +1,5 @@
1
+
2
+ %w{base area bar line pie}.each do |filename|
3
+ #puts "Requiring #{filename}"
4
+ require "gruff/#{filename}"
5
+ end
data/lib/gruff/area.rb ADDED
@@ -0,0 +1,15 @@
1
+
2
+ require 'gruff/base'
3
+
4
+ module Gruff
5
+ class Area < Base
6
+
7
+ # TODO Not yet implemented.
8
+ def draw
9
+ super
10
+
11
+ @d.draw(@base_image)
12
+ end
13
+
14
+ end
15
+ end
data/lib/gruff/bar.rb ADDED
@@ -0,0 +1,15 @@
1
+
2
+ require 'gruff/base'
3
+
4
+ module Gruff
5
+ class Bar < Base
6
+
7
+ # TODO Not yet implemented.
8
+ def draw
9
+ super
10
+
11
+ @d.draw(@base_image)
12
+ end
13
+
14
+ end
15
+ end
data/lib/gruff/base.rb ADDED
@@ -0,0 +1,364 @@
1
+ #
2
+ # = Gruff. Graphs.
3
+ #
4
+ # Author:: Geoffrey Grosenbach boss@topfunky.com
5
+ #
6
+ # Date:: October 23, 2005
7
+ #
8
+ #
9
+
10
+ require 'rmagick'
11
+ require 'yaml'
12
+
13
+ module Gruff
14
+
15
+ VERSION = '0.0.1'
16
+
17
+ class Base
18
+
19
+ include Magick
20
+
21
+ # A hash of names for the individual columns, where the key is the array index for the column this label represents.
22
+ #
23
+ # Not all columns need to be named.
24
+ #
25
+ # Example: 0 => 2005, 3 => 2006, 5 => 2007, 7 => 2008
26
+ attr_accessor :labels
27
+
28
+ # The large title of the graph displayed at the top
29
+ attr_accessor :title
30
+
31
+ # Font used for titles, labels, etc. Works best if you provide the full path to the TTF font file.
32
+ # RMagick must be built with the Freetype libraries for this to work properly.
33
+ attr_accessor :font
34
+
35
+ # Graph is drawn at 4/3 ratio (800x600, 400x300, etc.).
36
+ #
37
+ # Looks for Bitstream Vera as the default font. Expects an environment var of MAGICK_FONT_PATH to be set.
38
+ # (Uses RMagick's default font otherwise.)
39
+ def initialize(target_width=800)
40
+ @columns = target_width.to_f
41
+ @rows = target_width.to_f * 0.75
42
+
43
+ # Internal for calculations
44
+ @font = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
45
+ @marker_pointsize = 21.0
46
+ @raw_columns = 800.0
47
+ @raw_rows = 600.0
48
+ @column_count = 0
49
+ @maximum_value = 0
50
+ @data = Array.new
51
+ @labels = Hash.new
52
+ @labels_seen = Hash.new
53
+ @scale = @columns / @raw_columns
54
+
55
+ reset_themes()
56
+ theme_keynote()
57
+ end
58
+
59
+ # Add a color to the list of available colors for lines.
60
+ #
61
+ # Example:
62
+ # add_color('#c0e9d3')
63
+ def add_color(colorname)
64
+ @colors << colorname
65
+ end
66
+
67
+ # Replace the entire color list with a new array of colors. You need to have one more color
68
+ # than the number of datasets you intend to draw.
69
+ #
70
+ # Example:
71
+ # replace_colors('#cc99cc', '#d9e043', '#34d8a2')
72
+ def replace_colors(color_list=[])
73
+ @colors = color_list
74
+ end
75
+
76
+ # A color scheme similar to the popular presentation software.
77
+ def theme_keynote
78
+ reset_themes()
79
+ # Colors
80
+ @blue = '#6886B4'
81
+ @yellow = '#FDD84E'
82
+ @green = '#72AE6E'
83
+ @red = '#D1695E'
84
+ @purple = '#8A6EAF'
85
+ @orange = '#EFAA43'
86
+ @white = 'white'
87
+ @colors = [@yellow, @blue, @green, @red, @purple, @orange, @white]
88
+
89
+ @marker_color = 'white'
90
+
91
+ @base_image = render_gradiated_background('black', '#4a465a')
92
+ end
93
+
94
+ # A color scheme plucked from the colors on the popular usability blog.
95
+ def theme_37signals
96
+ reset_themes()
97
+ # Colors
98
+ @green = '#339933'
99
+ @purple = '#cc99cc'
100
+ @blue = '#336699'
101
+ @yellow = '#FFF804'
102
+ @red = '#ff0000'
103
+ @orange = '#cf5910'
104
+ @black = 'black'
105
+ @colors = [@yellow, @blue, @green, @red, @purple, @orange, @black]
106
+
107
+ @marker_color = 'black'
108
+
109
+ @base_image = render_gradiated_background('#d1edf5', 'white')
110
+ end
111
+
112
+ # A color scheme from the colors used on the 2005 Rails keynote presentation at RubyConf.
113
+ def theme_rails_keynote
114
+ reset_themes()
115
+ # Colors
116
+ @green = '#00ff00'
117
+ @grey = '#333333'
118
+ @orange = '#ff5d00'
119
+ @red = '#f61100'
120
+ @white = 'white'
121
+ @light_grey = '#999999'
122
+ @black = 'black'
123
+ @colors = [@green, @grey, @orange, @red, @white, @light_grey, @black]
124
+
125
+ @marker_color = 'white'
126
+
127
+ @base_image = render_gradiated_background('#0083a3', '#0083a3')
128
+ end
129
+
130
+ # A color scheme similar to that used on the popular podcast site.
131
+ def theme_odeo
132
+ reset_themes()
133
+ # Colors
134
+ @grey = '#202020'
135
+ @white = 'white'
136
+ @dark_pink = '#a21764'
137
+ @green = '#8ab438'
138
+ @light_grey = '#999999'
139
+ @dark_blue = '#3a5b87'
140
+ @black = 'black'
141
+ @colors = [@grey, @white, @dark_blue, @dark_pink, @green, @light_grey, @black]
142
+
143
+ @marker_color = 'white'
144
+
145
+ @base_image = render_gradiated_background('#ff47a4', '#ff1f81')
146
+ end
147
+
148
+ # dataset is an array where the first element is the name of the dataset
149
+ # and the value is an array of values to plot.
150
+ #
151
+ # Can be called multiple times with different datasets
152
+ # for a multi-valued graph.
153
+ #
154
+ # Example:
155
+ # data("Bart S.", [95, 45, 78, 89, 88, 76])
156
+ def data(name, data_points=[])
157
+ @data << [name, data_points]
158
+ # Set column count if this is larger than previous counts
159
+ @column_count = (data_points.length > @column_count) ? data_points.length : @column_count
160
+
161
+ # Pre-normalize
162
+ data_points.each do |data_point|
163
+ @maximum_value = (data_point > @maximum_value) ? data_point : @maximum_value
164
+ end
165
+ end
166
+
167
+ # Writes the graph to a file. Defaults to 'graph.png'
168
+ #
169
+ # Example: write('graphs/my_pretty_graph.png')
170
+ def write(filename="graph.png")
171
+ draw()
172
+ @base_image.write(filename)
173
+ end
174
+
175
+ # TODO Return the graph as a rendered binary blob.
176
+ def to_blob(filename="graph.png")
177
+ draw()
178
+ @base_image = @base_image.to_blob()
179
+ end
180
+
181
+ protected
182
+
183
+ # Overridden by subclasses to do the actual plotting of the graph.
184
+ #
185
+ # Subclasses should start by calling super() for this method.
186
+ def draw
187
+ setup_drawing()
188
+
189
+ # Subclasses will do some drawing here...
190
+ #@d.draw(@base_image)
191
+ end
192
+
193
+ # Draws the decorations.
194
+ # - line markers
195
+ # - legend
196
+ # - title
197
+ def setup_drawing
198
+ normalize()
199
+
200
+ draw_line_markers()
201
+ draw_legend()
202
+ draw_title
203
+ end
204
+
205
+ # Make copy of data with values scaled between 0-100
206
+ def normalize
207
+ @norm_data = Array.new
208
+ @data.each do |data_row|
209
+ norm_data_points = Array.new
210
+ data_row[1].each do |data_point|
211
+ norm_data_points << (data_point.to_f/@maximum_value.to_f)
212
+ end
213
+ @norm_data << [data_row[0], norm_data_points]
214
+ end
215
+ end
216
+
217
+ # Draws horizontal background lines and labels
218
+ def draw_line_markers
219
+ @graph_left = 130.0
220
+ @graph_right = @raw_columns - 100.0
221
+ @graph_top = 150.0
222
+ @graph_bottom = @raw_rows - 110.0
223
+ @graph_height = @graph_bottom - @graph_top
224
+ @graph_width = @graph_right - @graph_left
225
+
226
+ # Draw horizontal line markers and annotate with numbers
227
+ @d = @d.stroke(@marker_color)
228
+ @d = @d.stroke_width 1
229
+ (0..4).each do |index|
230
+ #y = ( index.to_f * (@graph_height.to_f/4.0) ) + @graph_top.to_f
231
+ y = @graph_top + @graph_height - ( index.to_f * (@graph_height.to_f/4.0) )
232
+ @d = @d.line(@graph_left, y, @graph_right, y)
233
+
234
+ marker_label = 0
235
+ marker_label = @maximum_value.to_f * (index.to_f/4.to_f) if index > 0
236
+
237
+ @d.fill = @marker_color
238
+ @d.font = @font
239
+ @d.stroke = 'transparent'
240
+ @d.pointsize = scale_fontsize(@marker_pointsize)
241
+ @d.gravity = EastGravity
242
+ @d = @d.annotate_scaled( @base_image,
243
+ 100, 20,
244
+ -10, y - (@marker_pointsize/2.0),
245
+ marker_label.to_s, @scale)
246
+ end
247
+ end
248
+
249
+ # Draws a legend with the names of the datasets matched to the colors used to draw them.
250
+ def draw_legend
251
+ @color_index = 0
252
+ @legend_labels = @data.collect {|item| item[0] }
253
+
254
+ legend_square_width = 20 # small square with color of this item
255
+
256
+ metrics = @d.get_type_metrics(@base_image, @legend_labels.join(''))
257
+ legend_text_width = metrics.width
258
+ legend_width = legend_text_width + @legend_labels.length * (legend_square_width * 2.7)
259
+ legend_left = scale(@raw_columns - legend_width) / 2
260
+ legend_increment = legend_width / @legend_labels.length.to_f
261
+
262
+ current_x_offset = legend_left
263
+ @legend_labels.each_with_index do |legend_label, index|
264
+ # Draw label
265
+ @d.fill = @marker_color
266
+ @d.font = @font
267
+ @d.pointsize = scale_fontsize(20)
268
+ @d.stroke = 'transparent'
269
+ @d.font_weight = NormalWeight
270
+ @d.gravity = WestGravity
271
+ @d = @d.annotate_scaled( @base_image,
272
+ @raw_columns, 24,
273
+ current_x_offset + (legend_square_width * 1.7), 70,
274
+ legend_label.to_s, @scale)
275
+
276
+ # Now draw box with color of this dataset
277
+ legend_box_y_offset = 2 # Move box down slightly to center
278
+ @d = @d.stroke 'transparent'
279
+ @d = @d.fill current_color
280
+ @d = @d.rectangle(current_x_offset, 70 + legend_box_y_offset,
281
+ current_x_offset + legend_square_width, 70 + legend_square_width + legend_box_y_offset)
282
+
283
+ increment_color()
284
+
285
+ @d.pointsize = 20
286
+ metrics = @d.get_type_metrics(@base_image, legend_label.to_s)
287
+ current_string_offset = metrics.width + (legend_square_width * 2.7)
288
+ current_x_offset += current_string_offset
289
+ end
290
+ @color_index = 0
291
+ end
292
+
293
+ def draw_title
294
+ @d.fill = @marker_color
295
+ @d.font = @font
296
+ @d.stroke = 'transparent'
297
+ @d.pointsize = scale_fontsize(36)
298
+ @d.font_weight = BoldWeight
299
+ @d.gravity = CenterGravity
300
+ @d = @d.annotate_scaled( @base_image,
301
+ @raw_columns, 50,
302
+ 0, 10,
303
+ @title, @scale)
304
+ end
305
+
306
+ def render_gradiated_background(top_color, bottom_color)
307
+ Image.new(@columns, @rows,
308
+ GradientFill.new(0, 0, 100, 0, top_color, bottom_color))
309
+ end
310
+
311
+ def current_color
312
+ @colors[@color_index]
313
+ end
314
+
315
+ def increment_color
316
+ @color_index += 1
317
+ raise(ColorlistExhaustedException, "There are no more colors left to use.") if @color_index == @colors.length
318
+ current_color
319
+ end
320
+
321
+ def reset_themes
322
+ @color_index = 0
323
+ @labels_seen = Hash.new
324
+
325
+ @d = Draw.new
326
+ # Scale down from 800x600 used to calculate drawing.
327
+ # NOTE: Font annotation is now affected and has to be done manually.
328
+ @d = @d.scale(@scale, @scale)
329
+ end
330
+
331
+ def scale(value)
332
+ value * @scale
333
+ end
334
+
335
+ def scale_fontsize(value)
336
+ new_fontsize = value * @scale
337
+ return 10 if new_fontsize < 10
338
+ return new_fontsize
339
+ end
340
+
341
+ end
342
+
343
+ class ColorlistExhaustedException < StandardError; end
344
+
345
+
346
+ end
347
+
348
+
349
+ module Magick
350
+ class Draw
351
+
352
+ # Additional method since Draw.scale doesn't affect annotations.
353
+ def annotate_scaled(img, width, height, x, y, text, scale)
354
+ scaled_width = (width * scale) >= 1 ? (width * scale) : 1
355
+ scaled_height = (height * scale) >= 1 ? (height * scale) : 1
356
+
357
+ self.annotate( img,
358
+ scaled_width, scaled_height,
359
+ x * scale, y * scale,
360
+ text)
361
+ end
362
+
363
+ end
364
+ end
data/lib/gruff/line.rb ADDED
@@ -0,0 +1,62 @@
1
+
2
+ require 'gruff/base'
3
+
4
+ module Gruff
5
+ class Line < Base
6
+
7
+ def draw
8
+ super
9
+
10
+ @x_increment = @graph_width / (@column_count - 1).to_f
11
+ circle_radius = 5.0
12
+
13
+ @d = @d.stroke_opacity 1.0
14
+ @d = @d.stroke_width 5.0
15
+
16
+ @norm_data.each do |data_row|
17
+ prev_x = prev_y = 0.0
18
+ @d = @d.stroke current_color
19
+ @d = @d.fill current_color
20
+
21
+ data_row[1].each_with_index do |data_point, index|
22
+ # Use incremented x and scaled y
23
+ new_x = @graph_left + (@x_increment * index)
24
+ new_y = @graph_top + (@graph_height - data_point * @graph_height)
25
+
26
+ @d = @d.line(prev_x, prev_y, new_x, new_y) if (prev_x > 0) && (prev_y > 0)
27
+ @d = @d.circle(new_x, new_y, new_x - circle_radius, new_y)
28
+
29
+ draw_label(new_x, index)
30
+
31
+ prev_x = new_x
32
+ prev_y = new_y
33
+ end
34
+
35
+ increment_color()
36
+ end
37
+
38
+ @d.draw(@base_image)
39
+ end
40
+
41
+ private
42
+
43
+ # Draws column labels below graph
44
+ def draw_label(x_offset, index)
45
+ if !@labels[index].nil? && @labels_seen[index].nil?
46
+ @d.fill = @marker_color
47
+ @d.font = @font
48
+ @d.stroke = 'transparent'
49
+ @d.font_weight = NormalWeight
50
+ @d.pointsize = scale_fontsize(@marker_pointsize)
51
+ @d.gravity = CenterGravity
52
+ @d = @d.annotate_scaled(@base_image,
53
+ 1, 1,
54
+ #150, 30,
55
+ x_offset, @raw_rows - 80,
56
+ @labels[index], @scale)
57
+ @labels_seen[index] = 1
58
+ end
59
+ end
60
+
61
+ end
62
+ end
data/lib/gruff/pie.rb ADDED
@@ -0,0 +1,15 @@
1
+
2
+ require 'gruff/base'
3
+
4
+ module Gruff
5
+ class Pie < Base
6
+
7
+ # TODO Not yet implemented.
8
+ def draw
9
+ super
10
+
11
+ @d.draw(@base_image)
12
+ end
13
+
14
+ end
15
+ end
data/rakefile ADDED
@@ -0,0 +1,192 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ $:.unshift(File.dirname(__FILE__) + "/lib")
10
+ require 'gruff'
11
+
12
+ PKG_NAME = 'gruff'
13
+ PKG_VERSION = Gruff::VERSION
14
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
+
16
+ RELEASE_NAME = "REL #{PKG_VERSION}"
17
+
18
+ RUBY_FORGE_PROJECT = "gruff"
19
+ RUBY_FORGE_USER = "topfunky"
20
+
21
+ desc "Default Task"
22
+ task :default => [ :test ]
23
+
24
+ # Run the unit tests
25
+ Rake::TestTask.new { |t|
26
+ t.libs << "test"
27
+ t.pattern = 'test/*_test.rb'
28
+ t.verbose = true
29
+ }
30
+
31
+
32
+ # Genereate the RDoc documentation
33
+ Rake::RDocTask.new { |rdoc|
34
+ rdoc.rdoc_dir = 'doc'
35
+ rdoc.title = "Gruff -- Beautiful graphs"
36
+ rdoc.options << '--line-numbers --inline-source --main README --accessor adv_attr_accessor=M'
37
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
38
+ rdoc.rdoc_files.include('README', 'CHANGELOG')
39
+ rdoc.rdoc_files.include('lib/gruff.rb')
40
+ rdoc.rdoc_files.include('lib/gruff/*.rb')
41
+ }
42
+
43
+
44
+ # Create compressed packages
45
+ spec = Gem::Specification.new do |s|
46
+ s.platform = Gem::Platform::RUBY
47
+ s.name = PKG_NAME
48
+ s.summary = "Beautiful graphs for one or multiple datasets."
49
+ s.description = %q{Make colorful graphs for use on websites or documents.}
50
+ s.version = PKG_VERSION
51
+
52
+ s.author = "Geoffrey Grosenbach"
53
+ s.email = "boss@topfunky.com"
54
+ s.rubyforge_project = RUBY_FORGE_PROJECT
55
+ s.homepage = "http://www.topfunky.com"
56
+
57
+ s.has_rdoc = true
58
+ s.requirements << 'none'
59
+ s.require_path = 'lib'
60
+ s.autorequire = 'gruff'
61
+
62
+ s.files = [ "rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
63
+ s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
64
+ s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
65
+ end
66
+
67
+ Rake::GemPackageTask.new(spec) do |p|
68
+ p.gem_spec = spec
69
+ p.need_tar = true
70
+ p.need_zip = true
71
+ end
72
+
73
+
74
+ desc "Publish the API documentation"
75
+ task :pgem => [:package] do
76
+ Rake::SshFilePublisher.new("boss@topfunky.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
77
+ end
78
+
79
+ desc "Publish the release files to RubyForge."
80
+ task :release => [:package] do
81
+ files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
82
+
83
+ if RUBY_FORGE_PROJECT then
84
+ require 'net/http'
85
+ require 'open-uri'
86
+
87
+ project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
88
+ project_data = open(project_uri) { |data| data.read }
89
+ group_id = project_data[/[?&]group_id=(\d+)/, 1]
90
+ raise "Couldn't get group id" unless group_id
91
+
92
+ # This echos password to shell which is a bit sucky
93
+ if ENV["RUBY_FORGE_PASSWORD"]
94
+ password = ENV["RUBY_FORGE_PASSWORD"]
95
+ else
96
+ print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
97
+ password = STDIN.gets.chomp
98
+ end
99
+
100
+ login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
101
+ data = [
102
+ "login=1",
103
+ "form_loginname=#{RUBY_FORGE_USER}",
104
+ "form_pw=#{password}"
105
+ ].join("&")
106
+ http.post("/account/login.php", data)
107
+ end
108
+
109
+ cookie = login_response["set-cookie"]
110
+ raise "Login failed" unless cookie
111
+ headers = { "Cookie" => cookie }
112
+
113
+ release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
114
+ release_data = open(release_uri, headers) { |data| data.read }
115
+ package_id = release_data[/[?&]package_id=(\d+)/, 1]
116
+ raise "Couldn't get package id" unless package_id
117
+
118
+ first_file = true
119
+ release_id = ""
120
+
121
+ files.each do |filename|
122
+ basename = File.basename(filename)
123
+ file_ext = File.extname(filename)
124
+ file_data = File.open(filename, "rb") { |file| file.read }
125
+
126
+ puts "Releasing #{basename}..."
127
+
128
+ release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
129
+ release_date = Time.now.strftime("%Y-%m-%d %H:%M")
130
+ type_map = {
131
+ ".zip" => "3000",
132
+ ".tgz" => "3110",
133
+ ".gz" => "3110",
134
+ ".gem" => "1400"
135
+ }; type_map.default = "9999"
136
+ type = type_map[file_ext]
137
+ boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
138
+
139
+ query_hash = if first_file then
140
+ {
141
+ "group_id" => group_id,
142
+ "package_id" => package_id,
143
+ "release_name" => RELEASE_NAME,
144
+ "release_date" => release_date,
145
+ "type_id" => type,
146
+ "processor_id" => "8000", # Any
147
+ "release_notes" => "",
148
+ "release_changes" => "",
149
+ "preformatted" => "1",
150
+ "submit" => "1"
151
+ }
152
+ else
153
+ {
154
+ "group_id" => group_id,
155
+ "release_id" => release_id,
156
+ "package_id" => package_id,
157
+ "step2" => "1",
158
+ "type_id" => type,
159
+ "processor_id" => "8000", # Any
160
+ "submit" => "Add This File"
161
+ }
162
+ end
163
+
164
+ query = "?" + query_hash.map do |(name, value)|
165
+ [name, URI.encode(value)].join("=")
166
+ end.join("&")
167
+
168
+ data = [
169
+ "--" + boundary,
170
+ "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
171
+ "Content-Type: application/octet-stream",
172
+ "Content-Transfer-Encoding: binary",
173
+ "", file_data, ""
174
+ ].join("\x0D\x0A")
175
+
176
+ release_headers = headers.merge(
177
+ "Content-Type" => "multipart/form-data; boundary=#{boundary}"
178
+ )
179
+
180
+ target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
181
+ http.post(target + query, data, release_headers)
182
+ end
183
+
184
+ if first_file then
185
+ release_id = release_response.body[/release_id=(\d+)/, 1]
186
+ raise("Couldn't get release id") unless release_id
187
+ end
188
+
189
+ first_file = false
190
+ end
191
+ end
192
+ end
data/test/line_test.rb ADDED
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift(File.dirname(__FILE__) + "/../lib/")
4
+ #$:.unshift File.dirname(__FILE__) + "/fixtures/helpers"
5
+
6
+ require 'test/unit'
7
+ require 'gruff'
8
+
9
+ class TestGruffLines < Test::Unit::TestCase
10
+
11
+ # TODO Delete old output files once when starting tests
12
+
13
+ def setup
14
+ @datasets = [
15
+ [:Jimmy, [25, 36, 86, 39, 25, 31, 79, 88]],
16
+ [:Charles, [80, 54, 67, 54, 68, 70, 90, 95]],
17
+ [:Julie, [22, 29, 35, 38, 36, 40, 46, 57]],
18
+ [:Jane, [95, 95, 95, 90, 85, 80, 88, 100]],
19
+ [:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
20
+ ["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
21
+ ]
22
+ end
23
+
24
+ def test_line_graph_with_themes
25
+ g = Gruff::Line.new
26
+ g.title = "Visual Multi-Line Graph Test"
27
+ g.labels = {
28
+ 0 => '5/6',
29
+ 2 => '5/15',
30
+ 4 => '5/24',
31
+ 6 => '5/30',
32
+ }
33
+ @datasets.each do |data|
34
+ g.data(data[0], data[1])
35
+ end
36
+
37
+ # Default theme
38
+ g.write("test/output/line_keynote.png")
39
+
40
+ g.theme_37signals
41
+ g.write("test/output/line_37signals.png")
42
+
43
+ g.theme_rails_keynote
44
+ g.write("test/output/line_rails_keynote.png")
45
+
46
+ g.theme_odeo
47
+ g.write("test/output/line_odeo.png")
48
+ end
49
+
50
+ def test_line_small_values
51
+ @datasets = [
52
+ [:small, [0.25, 0.14356, 0.0, 0.5674839, 0.456]],
53
+ [:small2, [0.2, 0.3, 0.1, 0.05, 0.9]]
54
+ ]
55
+
56
+ g = Gruff::Line.new
57
+ g.title = "Small Values Line Graph Test"
58
+ @datasets.each do |data|
59
+ g.data(data[0], data[1])
60
+ end
61
+
62
+ g.write("test/output/line_small.png")
63
+ end
64
+
65
+ def test_line_large_values
66
+ @datasets = [
67
+ [:large, [100_005, 35_000, 28_000, 27_000]],
68
+ [:large2, [35_000, 28_000, 27_000, 100_005]],
69
+ [:large3, [28_000, 27_000, 100_005, 35_000]],
70
+ [:large4, [1_238, 39_092, 27_938, 48_876]]
71
+ ]
72
+
73
+ g = Gruff::Line.new
74
+ g.title = "Very Large Values Line Graph Test"
75
+ @datasets.each do |data|
76
+ g.data(data[0], data[1])
77
+ end
78
+
79
+ g.write("test/output/line_large.png")
80
+ end
81
+
82
+ def test_resize
83
+ g = Gruff::Line.new(400)
84
+ g.title = "Small Size Multi-Line Graph Test"
85
+ g.labels = {
86
+ 0 => '5/6',
87
+ 2 => '5/15',
88
+ 4 => '5/24',
89
+ 6 => '5/30',
90
+ }
91
+ @datasets.each do |data|
92
+ g.data(data[0], data[1])
93
+ end
94
+
95
+ # Default theme
96
+ g.write("test/output/line_keynote_small.png")
97
+
98
+ g.theme_37signals
99
+ g.write("test/output/line_37signals_small.png")
100
+
101
+ g.theme_rails_keynote
102
+ g.write("test/output/line_rails_keynote_small.png")
103
+
104
+ g.theme_odeo
105
+ g.write("test/output/line_odeo_small.png")
106
+ end
107
+
108
+ def test_long_title
109
+
110
+ end
111
+
112
+ def test_add_colors
113
+
114
+ end
115
+
116
+ def test_request_too_many_colors
117
+
118
+ end
119
+
120
+ def test_add_data
121
+
122
+ end
123
+
124
+ def test_many_datapoints
125
+ g = Gruff::Line.new
126
+ g.title = "Many Multi-Line Graph Test"
127
+ g.labels = {
128
+ 0 => 'June',
129
+ 10 => 'July',
130
+ 30 => 'August',
131
+ 50 => 'September',
132
+ }
133
+ g.data('many points', (0..50).collect {|i| rand(100) })
134
+
135
+ # Default theme
136
+ g.write("test/output/line_many.png")
137
+ end
138
+
139
+
140
+ def test_similar_high_end_values
141
+ g = Gruff::Line.new
142
+ g.title = "Similar High End Values Test"
143
+ g.data('similar points', [100, 98, 99, 97, 96, 95, 96, 97, 98, 99, 100, 96] )
144
+
145
+ # Default theme
146
+ g.write("test/output/similar_high_end_values.png")
147
+ end
148
+
149
+
150
+ # Requires the Creative Block font from http://www.blambot.com
151
+ def test_font
152
+ g = Gruff::Line.new
153
+ g.title = "Font Test"
154
+ g.labels = {
155
+ 0 => '5/6',
156
+ 2 => '5/15',
157
+ 4 => '5/24',
158
+ 6 => '5/30',
159
+ 8 => '6/2',
160
+ 10 => '6/4',
161
+ }
162
+ g.data('many points', (0..10).collect {|i| rand(100) })
163
+ g.font = File.expand_path('CREABBRG.TTF', ENV['MAGICK_FONT_PATH'])
164
+
165
+ # Default theme
166
+ g.write("test/output/line_font.png")
167
+ end
168
+
169
+ =begin
170
+ def test_very_small_graphs
171
+ [300, 200, 100].each do |size|
172
+ g = Gruff::Line.new(size)
173
+ g.title = "#{size}px Graph Test"
174
+ g.labels = {
175
+ 0 => '5/6',
176
+ 2 => '5/15',
177
+ 4 => '5/24',
178
+ 6 => '5/30',
179
+ }
180
+ @datasets.each do |data|
181
+ g.data(data[0], data[1])
182
+ end
183
+
184
+ # Default theme
185
+ g.write("test/output/line_#{size}.png")
186
+ end
187
+ end
188
+ =end
189
+
190
+ =begin
191
+ def test_for_blog
192
+ g = Gruff::Line.new
193
+ g.labels = {
194
+ 0 => '2002',
195
+ 2 => '2003',
196
+ 4 => '2004',
197
+ 6 => '2005',
198
+ }
199
+ @datasets.each do |data|
200
+ g.data(data[0], data[1])
201
+ end
202
+
203
+ # Default theme
204
+ g.title = "Gruff...graphs"
205
+ g.write("test/output/1.png")
206
+
207
+ g.theme_odeo
208
+ g.title = "Themes, Colors, and Fonts!"
209
+ g.font = File.expand_path('CREABBRG.TTF', ENV['MAGICK_FONT_PATH'])
210
+ g.write("test/output/2.png")
211
+
212
+ g.theme_rails_keynote
213
+ g.title = "Source Coming Soon..."
214
+ g.font = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
215
+ g.write("test/output/3.png")
216
+
217
+ end
218
+
219
+ def test_for_blog_small
220
+ g = Gruff::Line.new(400)
221
+ g.labels = {
222
+ 0 => '2002',
223
+ 2 => '2003',
224
+ 4 => '2004',
225
+ 6 => '2005',
226
+ }
227
+ @datasets.each do |data|
228
+ g.data(data[0], data[1])
229
+ end
230
+
231
+ # Default theme
232
+ g.title = "Gruff...graphs"
233
+ g.write("test/output/1_small.png")
234
+
235
+ g.theme_odeo
236
+ g.title = "Themes, Colors, and Fonts!"
237
+ g.font = File.expand_path('CREABBRG.TTF', ENV['MAGICK_FONT_PATH'])
238
+ g.write("test/output/2_small.png")
239
+
240
+ g.theme_rails_keynote
241
+ g.title = "Source Coming Soon..."
242
+ g.font = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
243
+ g.write("test/output/3_small.png")
244
+
245
+ end
246
+ =end
247
+
248
+
249
+ end
250
+
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: gruff
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2005-10-25 00:00:00 -07:00
8
+ summary: Beautiful graphs for one or multiple datasets.
9
+ require_paths:
10
+ - lib
11
+ email: boss@topfunky.com
12
+ homepage: http://www.topfunky.com
13
+ rubyforge_project: gruff
14
+ description: Make colorful graphs for use on websites or documents.
15
+ autorequire: gruff
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Geoffrey Grosenbach
31
+ files:
32
+ - rakefile
33
+ - README
34
+ - CHANGELOG
35
+ - MIT-LICENSE
36
+ - lib/gruff
37
+ - lib/gruff.rb
38
+ - lib/gruff/area.rb
39
+ - lib/gruff/bar.rb
40
+ - lib/gruff/base.rb
41
+ - lib/gruff/line.rb
42
+ - lib/gruff/pie.rb
43
+ - test/line_test.rb
44
+ - test/output
45
+ - test/output/line_37signals.png
46
+ - test/output/line_37signals_small.png
47
+ - test/output/line_font.png
48
+ - test/output/line_keynote.png
49
+ - test/output/line_keynote_small.png
50
+ - test/output/line_large.png
51
+ - test/output/line_many.png
52
+ - test/output/line_odeo.png
53
+ - test/output/line_odeo_small.png
54
+ - test/output/line_rails_keynote.png
55
+ - test/output/line_rails_keynote_small.png
56
+ - test/output/line_small.png
57
+ - test/output/similar_high_end_values.png
58
+ test_files: []
59
+ rdoc_options: []
60
+ extra_rdoc_files: []
61
+ executables: []
62
+ extensions: []
63
+ requirements:
64
+ - none
65
+ dependencies: []