gchart 0.1.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.
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