gchart 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.0
2
+
3
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,7 @@
1
+ CHANGELOG.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/gchart.rb
6
+ lib/version.rb
7
+ test/test_gchart.rb
data/README.txt ADDED
@@ -0,0 +1,72 @@
1
+ = GChart
2
+
3
+ == DESCRIPTION
4
+
5
+ GChart exposes the Google Chart API (http://code.google.com/apis/chart) via
6
+ a friendly Ruby interface. It can generate the URL for a given chart
7
+ (for webpage use), or download the generated PNG (for offline use).
8
+
9
+ == PROBLEMS/TODO
10
+
11
+ * Add support for legends, fills (area or background), grid lines, shape markers, range markers
12
+ * Support shorthand colors and color names
13
+ * Make venn data specification friendlier
14
+
15
+ There are lots of missing features. Until they're implemented, you can directly specify
16
+ query parameters using the :extras key, e.g.,
17
+
18
+ # provides a legend for each data set
19
+ g = GChart.line(:data => [[1, 2], [3, 4]], :extras => { "chdl" => ["First", "Second"] })
20
+
21
+ == SYNOPSIS
22
+
23
+ # line chart
24
+ g = GChart.line(:data => [0, 10, 100])
25
+
26
+ # bar chart
27
+ g = GChart.bar(:data => [100, 1000, 10000])
28
+
29
+ # pie chart
30
+ g = GChart.pie(:data => [33, 33, 34])
31
+
32
+ # venn diagram (asize, bsize, csize, ab%, bc%, ca%, abc%)
33
+ g = GChart.venn(:data => [100, 80, 60, 30, 30, 30, 10])
34
+
35
+ # scatter plot (x coords, y coords [, sizes])
36
+ g = GChart.scatter(:data => [[1, 2, 3, 4, 5], [5, 4, 3, 2, 1], [1, 2, 3, 4, 5]])
37
+
38
+ # chart title
39
+ g = GChart.line(:title => "Awesomeness over Time", :data => [0, 10, 100])
40
+
41
+ # data set colors
42
+ g = GChart.line(:data => [[0, 10, 100], [100, 10, 0]], :colors => ["ff0000", "0000ff"])
43
+
44
+ g.to_url # generate the chart's URL, or
45
+ g.fetch # get the bytes, or
46
+ g.write("foo.png") # write to a file (defaults to "chart.png")
47
+ g.write(stream) # write to anything that quacks like IO
48
+
49
+ == LICENSE
50
+
51
+ (The MIT License)
52
+
53
+ Copyright 2007 John Barnette (jbarnette@rubyforge.org)
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining
56
+ a copy of this software and associated documentation files (the
57
+ 'Software'), to deal in the Software without restriction, including
58
+ without limitation the rights to use, copy, modify, merge, publish,
59
+ distribute, sublicense, and/or sell copies of the Software, and to
60
+ permit persons to whom the Software is furnished to do so, subject to
61
+ the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be
64
+ included in all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
67
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
69
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
71
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
72
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "rubygems"
2
+ require "hoe"
3
+ require "./lib/version.rb"
4
+
5
+ hoe = Hoe.new("gchart", GChart::VERSION) do |p|
6
+ p.rubyforge_name = "gchart"
7
+ p.author = "John Barnette"
8
+ p.email = "jbarnette@rubyforge.org"
9
+ p.summary = "GChart uses the Google Chart API to create pretty pictures."
10
+ p.description = p.paragraphs_of("README.txt", 2..5).join("\n\n")
11
+ p.url = "http://gchart.rubyforge.org"
12
+ p.changes = p.paragraphs_of("CHANGELOG.txt", 0..1).join("\n\n")
13
+ end
data/lib/gchart.rb ADDED
@@ -0,0 +1,143 @@
1
+ require File.dirname(__FILE__) + "/version"
2
+
3
+ require "open-uri"
4
+ require "uri"
5
+
6
+ class GChart
7
+ URL = "http://chart.apis.google.com/chart"
8
+ TYPES = %w(line linexy bar pie venn scatter).collect { |t| t.to_sym }
9
+ CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.".split("")
10
+ PAIRS = CHARS.collect { |first| CHARS.collect { |second| first + second } }.flatten
11
+
12
+ class << self
13
+ def encode_extended(number) #:nodoc:
14
+ return "__" if number.nil?
15
+ PAIRS[number.to_i]
16
+ end
17
+
18
+ TYPES.each do |type|
19
+ class_eval <<-END
20
+ def #{type}(options={}, &block)
21
+ new(options.merge(:type => #{type.inspect}, &block))
22
+ end
23
+ END
24
+ end
25
+ end
26
+
27
+ # Array of chart data
28
+ attr_accessor :data
29
+
30
+ # Hash of additional query params
31
+ attr_accessor :extras
32
+
33
+ # Width (in pixels)
34
+ attr_accessor :width
35
+
36
+ # Height (in pixels)
37
+ attr_accessor :height
38
+
39
+ # Orientation. Applies to bar charts
40
+ attr_accessor :horizontal
41
+
42
+ # Grouping. Applies to bar charts
43
+ attr_accessor :grouped
44
+
45
+ # Overall chart title
46
+ attr_accessor :title
47
+
48
+ # Array of RRGGBB colors, one per data set
49
+ attr_accessor :colors
50
+
51
+ # The chart type
52
+ attr_reader :type
53
+
54
+ alias_method :horizontal?, :horizontal
55
+ alias_method :grouped?, :grouped
56
+
57
+ def initialize(options={}, &block)
58
+ @type = :line
59
+ @data = []
60
+ @extras = {}
61
+ @width = 300
62
+ @height = 200
63
+ @horizontal = false
64
+ @grouped = false
65
+
66
+ options.each { |k, v| send("#{k}=", v) }
67
+ yield(self) if block_given?
68
+ end
69
+
70
+ # Sets the chart type. Raises +ArgumentError+ if +type+ isn't in +TYPES+.
71
+ def type=(type)
72
+ unless TYPES.include?(type)
73
+ raise ArgumentError, %Q(Invalid type #{type.inspect}. Valid types: #{TYPES.inspect}.)
74
+ end
75
+
76
+ @type = type
77
+ end
78
+
79
+ # Returns the chart's size as "WIDTHxHEIGHT".
80
+ def size
81
+ "#{width}x#{height}"
82
+ end
83
+
84
+ # Allows the chart's size to be set as "WIDTHxHEIGHT".
85
+ def size=(size)
86
+ self.width, self.height = size.split("x").collect { |n| Integer(n) }
87
+ end
88
+
89
+ # Returns the chart's URL.
90
+ def to_url
91
+ query = google_query_params.collect { |k, v| "#{k}=#{URI.escape(v)}" }.join("&")
92
+ "#{URL}?#{query}"
93
+ end
94
+
95
+ # Returns the chart's generated PNG as a blob.
96
+ def fetch
97
+ open(to_url) { |data| data.read }
98
+ end
99
+
100
+ # Writes the chart's generated PNG. If +io_or_file+ quacks like an IO,
101
+ # +write+ will be called. Otherwise, write to disk. +io_or_file+ defaults
102
+ # to "chart.png".
103
+ def write(io_or_file="chart.png")
104
+ return io_or_file.write(fetch) if io_or_file.respond_to?(:write)
105
+ open(io_or_file, "w+") { |f| f.write(fetch) }
106
+ end
107
+
108
+ private
109
+
110
+ def google_query_params
111
+ params = { "cht" => google_chart_type, "chd" => google_data, "chs" => size }
112
+ params["chtt"] = title.tr("\n", "|").gsub(/\s+/, "+") if title
113
+ params["chco"] = colors.join(",") if colors
114
+ params.merge(extras)
115
+ end
116
+
117
+ def google_chart_type
118
+ case type
119
+ when :line
120
+ "lc"
121
+ when :linexy
122
+ "lxy"
123
+ when :bar
124
+ "b" + (horizontal? ? "h" : "v") + (grouped? ? "g" : "s")
125
+ when :pie
126
+ "p"
127
+ when :venn
128
+ "v"
129
+ when :scatter
130
+ "s"
131
+ end
132
+ end
133
+
134
+ def google_data
135
+ # we'll just always use the extended encoding for now
136
+ sets = (Array === data.first ? data : [data]).collect do |set|
137
+ max = set.max
138
+ set.collect { |n| GChart.encode_extended(n * (PAIRS.size - 1) / max) }.join
139
+ end
140
+
141
+ "e:#{sets.join(",")}"
142
+ end
143
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ class GChart
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,114 @@
1
+ require "test/unit"
2
+ require "gchart"
3
+
4
+ class GChart
5
+ public :google_query_params, :google_chart_type, :google_data
6
+ end
7
+
8
+ class TestGChart < Test::Unit::TestCase
9
+ def test_supplies_a_version
10
+ assert_not_nil(GChart::VERSION)
11
+ end
12
+
13
+ def test_allows_hash_initialization
14
+ assert_equal(:line, GChart.new(:type => :line).type)
15
+ end
16
+
17
+ def test_complains_about_unknown_options
18
+ assert_raise(NoMethodError) { GChart.new(:monkey => :chimchim) }
19
+ end
20
+
21
+ def test_allows_block_initialization
22
+ c = GChart.new do |chart|
23
+ chart.type = :line
24
+ end
25
+
26
+ assert_equal(:line, c.type)
27
+ end
28
+
29
+ def test_allows_all_valid_chart_types
30
+ GChart::TYPES.each do |type|
31
+ assert_nothing_raised(ArgumentError) { GChart.new(:type => type) }
32
+ end
33
+ end
34
+
35
+ def test_complains_about_invalid_chart_types
36
+ assert_raise(ArgumentError) { GChart.new(:type => :monkey) }
37
+ end
38
+
39
+ def test_allows_size_to_be_specified_combined
40
+ c = GChart.new(:size => "13x14")
41
+ assert_equal(13, c.width)
42
+ assert_equal(14, c.height)
43
+ end
44
+
45
+ def test_defaults
46
+ c = GChart.new
47
+ assert_equal(:line, c.type)
48
+ assert_equal([], c.data)
49
+ assert_equal(300, c.width)
50
+ assert_equal(200, c.height)
51
+ assert(!c.horizontal?)
52
+ assert(!c.grouped?)
53
+ end
54
+
55
+ def test_google_chart_types
56
+ assert_equal("lc", GChart.new(:type => :line).google_chart_type)
57
+ assert_equal("lxy", GChart.new(:type => :linexy).google_chart_type)
58
+
59
+ assert_equal("bhg", GChart.new(:type => :bar, :horizontal => true, :grouped => true).google_chart_type)
60
+ assert_equal("bhs", GChart.new(:type => :bar, :horizontal => true, :grouped => false).google_chart_type)
61
+ assert_equal("bvs", GChart.new(:type => :bar, :horizontal => false, :grouped => false).google_chart_type)
62
+
63
+ assert_equal("p", GChart.new(:type => :pie).google_chart_type)
64
+ assert_equal("v", GChart.new(:type => :venn).google_chart_type)
65
+ assert_equal("s", GChart.new(:type => :scatter).google_chart_type)
66
+ end
67
+
68
+ def test_google_extended_notation
69
+ expected = {
70
+ 0 => "AA", 25 => "AZ", 26 => "Aa", 51 => "Az", 52 => "A0", 61 => "A9", 62 => "A-", 63 => "A.",
71
+ 64 => "BA", 89 => "BZ", 90 => "Ba", 115 => "Bz", 116 => "B0", 125 => "B9", 126 => "B-", 127 => "B.",
72
+ 4032 => ".A", 4057 => ".Z", 4058 => ".a", 4083 => ".z", 4084 => ".0", 4093 => ".9", 4094 => ".-", 4095 => ".."
73
+ }
74
+
75
+ expected.each do |original, encoded|
76
+ assert_equal(encoded, GChart.encode_extended(original))
77
+ end
78
+
79
+ assert_equal("__", GChart.encode_extended(nil))
80
+ end
81
+
82
+ def test_allows_extra_query_params
83
+ c = GChart.new(:extras => { :foo => :bar })
84
+ assert(c.google_query_params.include?(:foo))
85
+ end
86
+
87
+ def test_supports_title
88
+ chart = GChart.new
89
+
90
+ assert_nil(chart.google_query_params["chtt"])
91
+
92
+ chart.title = "foo"
93
+ assert_equal("foo", chart.google_query_params["chtt"])
94
+
95
+ chart.title = "a space"
96
+ assert_equal("a+space", chart.google_query_params["chtt"])
97
+
98
+ chart.title = "a\nnewline"
99
+ assert_equal("a|newline", chart.google_query_params["chtt"])
100
+ end
101
+
102
+ def test_supports_colors
103
+ chart = GChart.new(:colors => ["cccccc", "eeeeee"])
104
+ assert_equal(chart.google_query_params["chco"], "cccccc,eeeeee")
105
+ end
106
+
107
+ def test_generates_correct_query_params_and_url_for_simple_example
108
+ expected = { "cht" => "lc", "chs" => "300x200", "chd" => "e:AAAo..", "chtt" => "test" }
109
+
110
+ chart = GChart.new(:title => "test", :data => [1, 100, 10000])
111
+ assert_equal(expected, chart.google_query_params)
112
+ assert_equal("http://chart.apis.google.com/chart?chs=300x200&cht=lc&chtt=test&chd=e:AAAo..", chart.to_url)
113
+ end
114
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gchart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ""
6
+ authors:
7
+ - John Barnette
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2007-12-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.3.0
23
+ version:
24
+ description: "== PROBLEMS/TODO * Add support for legends, fills (area or background), grid lines, shape markers, range markers * Support shorthand colors and color names * Make venn data specification friendlier There are lots of missing features. Until they're implemented, you can directly specify query parameters using the :extras key, e.g., # provides a legend for each data set g = GChart.line(:data => [[1, 2], [3, 4]], :extras => { \"chdl\" => [\"First\", \"Second\"] })"
25
+ email: jbarnette@rubyforge.org
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - CHANGELOG.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - CHANGELOG.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - lib/gchart.rb
40
+ - lib/version.rb
41
+ - test/test_gchart.rb
42
+ has_rdoc: true
43
+ homepage: http://gchart.rubyforge.org
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --main
47
+ - README.txt
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project: gchart
65
+ rubygems_version: 0.9.5
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: GChart uses the Google Chart API to create pretty pictures.
69
+ test_files:
70
+ - test/test_gchart.rb