gchartrb 0.5.4 → 0.5.5
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/History.txt +4 -0
- data/Rakefile +1 -1
- data/lib/google_chart/base.rb +436 -436
- data/lib/test.rb +15 -0
- metadata +2 -2
data/History.txt
CHANGED
data/Rakefile
CHANGED
|
@@ -8,7 +8,7 @@ class Hoe
|
|
|
8
8
|
def extra_deps; @extra_deps.reject { |x| Array(x).first == "hoe" } end
|
|
9
9
|
end # copied from the Rakefile of the sup project
|
|
10
10
|
|
|
11
|
-
Hoe.new('gchartrb', "0.5.
|
|
11
|
+
Hoe.new('gchartrb', "0.5.5") do |p|
|
|
12
12
|
p.rubyforge_name = 'gchartrb'
|
|
13
13
|
p.author = 'Deepak Jois'
|
|
14
14
|
p.email = 'deepak.jois@gmail.com'
|
data/lib/google_chart/base.rb
CHANGED
|
@@ -1,460 +1,460 @@
|
|
|
1
1
|
require 'uri'
|
|
2
2
|
|
|
3
3
|
module GoogleChart
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
4
|
+
class Base
|
|
5
|
+
BASE_URL = "http://chart.apis.google.com/chart?"
|
|
6
|
+
|
|
7
|
+
SIMPLE_ENCODING = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');
|
|
8
|
+
COMPLEX_ENCODING_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.'.split('');
|
|
9
|
+
@@complex_encoding = []
|
|
10
|
+
COMPLEX_ENCODING_ALPHABET.each_with_index do |outer,index_outer|
|
|
11
|
+
COMPLEX_ENCODING_ALPHABET.each_with_index do |inner, index_inner|
|
|
12
|
+
@@complex_encoding[index_outer * 64 + index_inner] = outer + inner
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
SHAPE_MARKERS = {:arrow => "a",
|
|
17
|
+
:cross => "c",
|
|
18
|
+
:diamond => "d",
|
|
19
|
+
:circle => "o",
|
|
20
|
+
:square => "s",
|
|
21
|
+
:vline_segment => "v",
|
|
22
|
+
:vline_full => "V",
|
|
23
|
+
:hline_full => "h",
|
|
24
|
+
:x => "x"
|
|
25
|
+
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
27
|
+
# Size of the chart in WIDTHxHEIGHT format
|
|
28
|
+
attr_accessor :chart_size
|
|
29
|
+
|
|
30
|
+
# Type of the chart. Usually, you do not need to set this yourself
|
|
31
|
+
attr_accessor :chart_type
|
|
32
|
+
|
|
33
|
+
# Chart title
|
|
34
|
+
attr_accessor :chart_title
|
|
35
|
+
|
|
36
|
+
# RRGGBB hex value for the color of the title
|
|
37
|
+
attr_accessor :title_color
|
|
38
|
+
|
|
39
|
+
# Font size of the title
|
|
40
|
+
attr_accessor :title_font_size
|
|
41
|
+
|
|
42
|
+
# Data encoding to use. Can be one of <tt>:simple</tt>, <tt>:text</tt> or <tt>:extended</tt> (see http://code.google.com/apis/chart/#chart_data)
|
|
43
|
+
attr_accessor :data_encoding
|
|
44
|
+
|
|
45
|
+
# A hash of the params used to construct the URL
|
|
46
|
+
attr_accessor :params
|
|
47
|
+
|
|
48
|
+
# Set to <tt>true</tt> or <tt>false</tt> to show or hide the chart legend. Not applicable for Scatter Chart.
|
|
49
|
+
attr_accessor :show_legend
|
|
50
|
+
|
|
51
|
+
def initialize(chart_size, chart_title)
|
|
52
|
+
self.params = Hash.new
|
|
53
|
+
@labels = []
|
|
54
|
+
@data = []
|
|
55
|
+
@colors = []
|
|
56
|
+
@axis = []
|
|
57
|
+
@markers = []
|
|
58
|
+
self.chart_size = chart_size
|
|
59
|
+
self.chart_title = chart_title
|
|
60
|
+
self.data_encoding = :simple
|
|
61
|
+
self.show_legend = true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Generates the URL string that can be used to retrieve the graph image in PNG format.
|
|
65
|
+
# Use this after assigning all the properties to the graph
|
|
66
|
+
# You can pass in additional params as a hash for features that may not have been implemented
|
|
67
|
+
# For e.g
|
|
68
|
+
# lc = GoogleChart::LineChart.new('320x200', "Line Chart", false)
|
|
69
|
+
# lc.data "Trend 1", [5,4,3,1,3,5,6], '0000ff'
|
|
70
|
+
# lc.data "Trend 2", [1,2,3,4,5,6], '00ff00'
|
|
71
|
+
# lc.data "Trend 3", [6,5,4,3,2,1], 'ff0000'
|
|
72
|
+
# puts lc.to_url({:chm => "000000,0,0.1,0.11"}) # Single black line as a horizontal marker
|
|
73
|
+
def to_url(extras={})
|
|
74
|
+
params.clear
|
|
75
|
+
set_size
|
|
76
|
+
set_type
|
|
77
|
+
set_colors
|
|
78
|
+
set_fill_options
|
|
79
|
+
add_axis unless @axis.empty?
|
|
80
|
+
add_grid
|
|
81
|
+
add_data
|
|
82
|
+
add_markers unless @markers.empty?
|
|
83
|
+
add_labels(@labels) if [:p, :p3].member?(self.chart_type)
|
|
84
|
+
add_legend(@labels) if show_legend
|
|
85
|
+
add_title if chart_title.to_s.length > 0
|
|
86
|
+
|
|
87
|
+
params.merge!(extras)
|
|
88
|
+
query_string = params.map { |k,v| "#{k}=#{URI.escape(v.to_s).gsub(/%20/,'+').gsub(/%7C/,'|')}" }.join('&')
|
|
89
|
+
BASE_URL + query_string
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Adds the data to the chart, according to the type of the graph being generated.
|
|
93
|
+
#
|
|
94
|
+
# [+name+] is a string containing a label for the data.
|
|
95
|
+
# [+value+] is either a number or an array of numbers containing the data. Pie Charts and Venn Diagrams take a single number, but other graphs require an array of numbers
|
|
96
|
+
# [+color+ (optional)] is a hexadecimal RGB value for the color to represent the data
|
|
97
|
+
#
|
|
98
|
+
# ==== Examples
|
|
99
|
+
#
|
|
100
|
+
# for GoogleChart::LineChart (normal)
|
|
101
|
+
# lc.data "Trend 1", [1,2,3,4,5], 'ff00ff'
|
|
102
|
+
#
|
|
103
|
+
# for GoogleChart::LineChart (XY chart)
|
|
104
|
+
# lc.data "Trend 2", [[4,5], [2,2], [1,1], [3,4]], 'ff00ff'
|
|
105
|
+
#
|
|
106
|
+
# for GoogleChart::PieChart
|
|
107
|
+
# lc.data "Apples", 5, 'ff00ff'
|
|
108
|
+
# lc.data "Oranges", 7, '00ffff'
|
|
109
|
+
def data(name, value, color=nil)
|
|
110
|
+
@data << value
|
|
111
|
+
@labels << name
|
|
112
|
+
@colors << color if color
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Allows (optional) setting of a max value for the chart, which will be used for data encoding and axis plotting.
|
|
116
|
+
# The value to pass depends on the type of chart
|
|
117
|
+
# * For Line Chart and Bar Charts it should be a single integer or float value
|
|
118
|
+
# * For Scatter Charts and Line XY Charts, you MUST pass an array containing the maximum values for X and Y
|
|
119
|
+
#
|
|
120
|
+
# ==== Examples
|
|
121
|
+
# For bar charts
|
|
122
|
+
# bc.max_value 5 # 5 will be used to calculate the relative encoding values
|
|
123
|
+
# For scatter chart
|
|
124
|
+
# sc.max_value [5,6] # 5 is the max x value and 6 is the max y value
|
|
125
|
+
#
|
|
126
|
+
# Note : MAKE SURE you are passing the right values otherwise an exception will be raised
|
|
127
|
+
def max_value(value)
|
|
128
|
+
if [:lxy, :s].member?(self.chart_type) and value.is_a?(Array)
|
|
129
|
+
@max_x = value.first
|
|
130
|
+
@max_y = value.last
|
|
131
|
+
elsif [:lc,:bhg,:bhs,:bvg,:bvs] and (value.is_a?(Integer) or value.is_a?(Float))
|
|
132
|
+
@max_data = value
|
|
133
|
+
else
|
|
134
|
+
raise "Invalid max value for this chart type"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Adds a background or chart fill. Call this option twice if you want both a background and a chart fill
|
|
139
|
+
# [+bg_or_c+] Can be one of <tt>:background</tt> or <tt>:chart</tt> depending on the kind of fill requested
|
|
140
|
+
# [+type+] Can be one of <tt>:solid</tt>, <tt>:gradient</tt> or <tt>:stripes</tt>
|
|
141
|
+
# [+options+] : Options depend on the type of fill selected above
|
|
142
|
+
#
|
|
143
|
+
# ==== Options
|
|
144
|
+
# For <tt>:solid</tt> type
|
|
145
|
+
# * A <tt>:color</tt> option which specifies the RGB hex value of the color to be used as a fill. For e.g <tt>lc.fill(:chart, :solid, {:color => 'ffcccc'})</tt>
|
|
146
|
+
#
|
|
147
|
+
# For <tt>:gradient</tt> type
|
|
148
|
+
# * An <tt>:angle</tt>, which is the angle of the gradient between 0(horizontal) and 90(vertical)
|
|
149
|
+
# * A <tt>:color</tt> option which is a 2D array containing the colors and an offset each, which specifies at what point the color is pure where: 0 specifies the right-most chart position and 1 the left-most. e,g <tt>lc.fill :background, :gradient, :angle => 0, :color => [['76A4FB',1],['ffffff',0]]</tt>
|
|
150
|
+
#
|
|
151
|
+
# For <tt>:stripes</tt> type
|
|
152
|
+
# * An <tt>:angle</tt>, which is the angle of the stripe between 0(horizontal) and 90(vertical)
|
|
153
|
+
# * A <tt>:color</tt> option which is a 2D array containing the colors and width value each, which must be between 0 and 1 where 1 is the full width of the chart. for e.g <tt>lc.fill :chart, :stripes, :angle => 90, :color => [ ['76A4FB',0.2], ['ffffff',0.2] ]</tt>
|
|
154
|
+
def fill(bg_or_c, type, options = {})
|
|
155
|
+
case bg_or_c
|
|
156
|
+
when :background
|
|
157
|
+
@background_fill = "bg," + process_fill_options(type, options)
|
|
158
|
+
when :chart
|
|
159
|
+
@chart_fill = "c," + process_fill_options(type, options)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Adds an axis to the graph. Not applicable for Pie Chart (GoogleChart::PieChart) or Venn Diagram (GoogleChart::VennDiagram)
|
|
164
|
+
#
|
|
165
|
+
# [+type+] is a symbol which can be one of <tt>:x</tt>, <tt>:y</tt>, <tt>:right</tt>, <tt>:top</tt>
|
|
166
|
+
# [+options+] is a hash containing the options (see below)
|
|
167
|
+
#
|
|
168
|
+
# ==== Options
|
|
169
|
+
# Not all the options are mandatory.
|
|
170
|
+
# [<tt>:labels</tt>] An array containing the labels for the axis
|
|
171
|
+
# [<tt>:positions</tt>] An Array containing the positions for the labels
|
|
172
|
+
# [<tt>:range</tt>] An array containing 2 elements, the start value and end value
|
|
173
|
+
#
|
|
174
|
+
# axis styling options have to be specified as follows
|
|
175
|
+
# [<tt>:color</tt>] Hexadecimal RGB value for the color to represent the data for the axis labels
|
|
176
|
+
# [<tt>:font_size</tt>] Font size of the labels in pixels
|
|
177
|
+
# [<tt>:alignment</tt>] can be one of <tt>:left</tt>, <tt>:center</tt> or <tt>:right</tt>
|
|
178
|
+
#
|
|
179
|
+
# ==== Examples
|
|
180
|
+
# lc.axis :y, :range => [0,6], :color => 'ff00ff', :font_size => 16, :alignment => :center
|
|
181
|
+
#
|
|
182
|
+
def axis(type, options = {})
|
|
183
|
+
raise "Illegal axis type" unless [:x, :y, :right, :top].member?(type)
|
|
184
|
+
@axis << [type, options]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Adds a grid to the graph. Applicable only for Line Chart (GoogleChart::LineChart) and Scatter Chart (GoogleChart::ScatterChart)
|
|
188
|
+
#
|
|
189
|
+
# [+options+] is a hash containing the options (see below)
|
|
190
|
+
#
|
|
191
|
+
# === Options
|
|
192
|
+
# [<tt>:xstep</tt>] X axis step size
|
|
193
|
+
# [<tt>:ystep</tt>] Y axis step size
|
|
194
|
+
# [<tt>:length_segment</tt> (optional)] Length of the line segement. Useful with the :length_blank value to have dashed lines
|
|
195
|
+
# [<tt>:length_blank</tt> (optional)] Length of the blank segment. use 0 if you want a solid grid
|
|
196
|
+
#
|
|
197
|
+
# === Examples
|
|
198
|
+
# lc.grid :x_step => 5, :y_step => 5, :length_segment => 1, :length_blank => 0
|
|
199
|
+
#
|
|
200
|
+
def grid(options={})
|
|
201
|
+
@grid_str = "#{options[:x_step].to_f},#{options[:y_step].to_f}"
|
|
202
|
+
if options[:length_segment] or options[:length_blank]
|
|
203
|
+
@grid_str += ",#{options[:length_segment].to_f},#{options[:length_blank].to_f}"
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Defines a horizontal or vertical range marker. Applicable for line charts and vertical charts
|
|
208
|
+
#
|
|
209
|
+
# [+alignment+] can be <tt>:horizontal</tt> or <tt>:vertical</tt>
|
|
210
|
+
# [+options+] specifies the color, start point and end point
|
|
211
|
+
#
|
|
212
|
+
# ==== Options
|
|
213
|
+
# [<tt>:color</tt>] RRGGBB hex value for the color of the range marker
|
|
214
|
+
# [<tt>:start_point</tt>] position on the x-axis/y-axis at which the range starts where 0.00 is the left/bottom and 1.00 is the right/top
|
|
215
|
+
# [<tt>:end_point</tt>] position on the x-axis/y-axis at which the range ends where 0.00 is the left/bottom and 1.00 is the right/top
|
|
216
|
+
#
|
|
217
|
+
# ==== Examples
|
|
218
|
+
# lc.range_marker :horizontal, :color => 'E5ECF9', :start_point => 0.1, :end_point => 0.5
|
|
219
|
+
# lc.range_marker :vertical, :color => 'a0bae9', :start_point => 0.1, :end_point => 0.5
|
|
220
|
+
def range_marker(alignment, options={})
|
|
221
|
+
raise "Invalid alignment specified" unless [:horizontal, :vertical].member?(alignment)
|
|
222
|
+
str = (alignment == :horizontal ) ? "r" : "R"
|
|
223
|
+
str += ",#{options[:color]},0,#{options[:start_point]},#{options[:end_point]}"
|
|
224
|
+
@markers << str
|
|
225
|
+
end
|
|
226
226
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
227
|
+
# Defines a shape marker. Applicable for line charts and scatter plots
|
|
228
|
+
#
|
|
229
|
+
# [+type+] can be <tt>:arrow</tt>, <tt>:cross</tt>, <tt>:diamond</tt>, <tt>:circle</tt>, <tt>:square</tt>, <tt>:vline_segment</tt>, <tt>:vline_full</tt>, <tt>:hline_full</tt>, <tt>:x</tt>
|
|
230
|
+
# [+options+] specifies the color, data set index, data point index and size in pixels
|
|
231
|
+
#
|
|
232
|
+
# ==== Options
|
|
233
|
+
# [<tt>:color</tt>] RRGGBB hex value for the color of the range marker
|
|
234
|
+
# [<tt>:data_set_index</tt>] the index of the line on which to draw the marker. This is 0 for the first data set, 1 for the second and so on.
|
|
235
|
+
# [<tt>:data_point_index</tt>] is a floating point value that specifies on which data point of the data set the marker will be drawn. This is 0 for the first data point, 1 for the second and so on. Specify a fraction to interpolate a marker between two points.
|
|
236
|
+
# [<tt>:size</tt>] is the size of the marker in pixels.
|
|
237
|
+
#
|
|
238
|
+
# ==== Examples
|
|
239
|
+
# lcxy.shape_marker :circle, :color => "000000", :data_set_index => 1, :data_point_index => 2, :pixel_size => 10
|
|
240
|
+
# lcxy.shape_marker :cross, :color => "E5ECF9", :data_set_index => 0, :data_point_index => 0.5, :pixel_size => 10
|
|
241
|
+
def shape_marker(type, options={})
|
|
242
|
+
raise "Invalid shape marker type specified" unless SHAPE_MARKERS.has_key?(type)
|
|
243
|
+
shape_marker_str = "#{SHAPE_MARKERS[type]},#{options[:color]},#{options[:data_set_index]},#{options[:data_point_index]},#{options[:pixel_size]}"
|
|
244
|
+
@markers << shape_marker_str
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
protected
|
|
248
|
+
|
|
249
|
+
def process_fill_options(type, options)
|
|
250
|
+
case type
|
|
251
|
+
when :solid
|
|
252
|
+
"s,#{options[:color]}"
|
|
253
|
+
when :gradient
|
|
254
|
+
"lg,#{options[:angle]}," + options[:color].collect { |o| "#{o.first},#{o.last}" }.join(",")
|
|
255
|
+
when :stripes
|
|
256
|
+
"ls,#{options[:angle]}," + options[:color].collect { |o| "#{o.first},#{o.last}" }.join(",")
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def set_type
|
|
262
|
+
params.merge!({:cht => chart_type})
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def set_size
|
|
266
|
+
params.merge!({:chs => chart_size})
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def set_colors
|
|
270
|
+
params.merge!({:chco => @colors.collect{|c| c.downcase}.join(",") }) if @colors.size > 0
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def set_fill_options
|
|
274
|
+
fill_opt = [@background_fill, @chart_fill].compact.join("|")
|
|
275
|
+
params.merge!({:chf => fill_opt}) if fill_opt.length > 0
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def add_labels(labels)
|
|
279
|
+
params.merge!({:chl => labels.collect{|l| l.to_s}.join("|") }) if self.show_labels
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def add_legend(labels)
|
|
283
|
+
params.merge!({:chdl => labels.collect{ |l| l.to_s}.join("|")})
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def add_title
|
|
287
|
+
params.merge!({:chtt => chart_title})
|
|
288
|
+
params.merge!({:chts => title_color}) if title_color
|
|
289
|
+
params.merge!({:chts => "#{title_color},#{title_font_size}"}) if title_color and title_font_size
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def add_axis
|
|
293
|
+
chxt = []
|
|
294
|
+
chxl = []
|
|
295
|
+
chxp = []
|
|
296
|
+
chxr = []
|
|
297
|
+
chxs = []
|
|
298
|
+
# Process params
|
|
299
|
+
@axis.each_with_index do |axis, idx|
|
|
300
|
+
# Find axis type
|
|
301
|
+
case axis.first
|
|
302
|
+
when :x
|
|
303
|
+
chxt << "x"
|
|
304
|
+
when :y
|
|
305
|
+
chxt << "y"
|
|
306
|
+
when :top
|
|
307
|
+
chxt << "r"
|
|
308
|
+
when :right
|
|
309
|
+
chxt << "t"
|
|
245
310
|
end
|
|
246
311
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
def process_fill_options(type, options)
|
|
250
|
-
case type
|
|
251
|
-
when :solid
|
|
252
|
-
"s,#{options[:color]}"
|
|
253
|
-
when :gradient
|
|
254
|
-
"lg,#{options[:angle]}," + options[:color].collect { |o| "#{o.first},#{o.last}" }.join(",")
|
|
255
|
-
when :stripes
|
|
256
|
-
"ls,#{options[:angle]}," + options[:color].collect { |o| "#{o.first},#{o.last}" }.join(",")
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
end
|
|
312
|
+
# Axis labels
|
|
313
|
+
axis_opts = axis.last
|
|
260
314
|
|
|
261
|
-
|
|
262
|
-
|
|
315
|
+
if axis_opts[:labels]
|
|
316
|
+
chxl[idx] = "#{idx}:|" + axis_opts[:labels].join("|")
|
|
263
317
|
end
|
|
264
318
|
|
|
265
|
-
|
|
266
|
-
|
|
319
|
+
# Axis positions
|
|
320
|
+
if axis_opts[:positions]
|
|
321
|
+
chxp[idx] = "#{idx}," + axis_opts[:positions].join(",")
|
|
267
322
|
end
|
|
268
323
|
|
|
269
|
-
|
|
270
|
-
|
|
324
|
+
# Axis range
|
|
325
|
+
if axis_opts[:range]
|
|
326
|
+
chxr[idx] = "#{idx},#{axis_opts[:range].first},#{axis_opts[:range].last}"
|
|
271
327
|
end
|
|
272
328
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
329
|
+
# Axis Styles
|
|
330
|
+
if axis_opts[:color] or axis_opts[:font_size] or axis_opts[:alignment]
|
|
331
|
+
if axis_opts[:alignment]
|
|
332
|
+
alignment = case axis_opts[:alignment]
|
|
333
|
+
when :center
|
|
334
|
+
0
|
|
335
|
+
when :left
|
|
336
|
+
-1
|
|
337
|
+
when :right
|
|
338
|
+
1
|
|
339
|
+
else
|
|
340
|
+
nil
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
chxs[idx] = "#{idx}," + [axis_opts[:color], axis_opts[:font_size], alignment].compact.join(",")
|
|
276
344
|
end
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Add to params hash
|
|
348
|
+
params.merge!({ :chxt => chxt.join(",") }) unless chxt.empty?
|
|
349
|
+
params.merge!({ :chxl => chxl.compact.join("|") }) unless chxl.compact.empty?
|
|
350
|
+
params.merge!({ :chxp => chxp.compact.join("|") }) unless chxp.compact.empty?
|
|
351
|
+
params.merge!({ :chxr => chxr.compact.join("|") }) unless chxr.compact.empty?
|
|
352
|
+
params.merge!({ :chxs => chxs.compact.join("|") }) unless chxs.compact.empty?
|
|
353
|
+
end
|
|
281
354
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
params.merge!({:chts => "#{title_color},#{title_font_size}"}) if title_color and title_font_size
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
def add_axis
|
|
293
|
-
chxt = []
|
|
294
|
-
chxl = []
|
|
295
|
-
chxp = []
|
|
296
|
-
chxr = []
|
|
297
|
-
chxs = []
|
|
298
|
-
# Process params
|
|
299
|
-
@axis.each_with_index do |axis, idx|
|
|
300
|
-
# Find axis type
|
|
301
|
-
case axis.first
|
|
302
|
-
when :x
|
|
303
|
-
chxt << "x"
|
|
304
|
-
when :y
|
|
305
|
-
chxt << "y"
|
|
306
|
-
when :top
|
|
307
|
-
chxt << "r"
|
|
308
|
-
when :right
|
|
309
|
-
chxt << "t"
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
# Axis labels
|
|
313
|
-
axis_opts = axis.last
|
|
314
|
-
|
|
315
|
-
if axis_opts[:labels]
|
|
316
|
-
chxl[idx] = "#{idx}:|" + axis_opts[:labels].join("|")
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
# Axis positions
|
|
320
|
-
if axis_opts[:positions]
|
|
321
|
-
chxp[idx] = "#{idx}," + axis_opts[:positions].join(",")
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
# Axis range
|
|
325
|
-
if axis_opts[:range]
|
|
326
|
-
chxr[idx] = "#{idx},#{axis_opts[:range].first},#{axis_opts[:range].last}"
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
# Axis Styles
|
|
330
|
-
if axis_opts[:color] or axis_opts[:font_size] or axis_opts[:alignment]
|
|
331
|
-
if axis_opts[:alignment]
|
|
332
|
-
alignment = case axis_opts[:alignment]
|
|
333
|
-
when :center
|
|
334
|
-
0
|
|
335
|
-
when :left
|
|
336
|
-
-1
|
|
337
|
-
when :right
|
|
338
|
-
1
|
|
339
|
-
else
|
|
340
|
-
nil
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
chxs[idx] = "#{idx}," + [axis_opts[:color], axis_opts[:font_size], alignment].compact.join(",")
|
|
344
|
-
end
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
# Add to params hash
|
|
348
|
-
params.merge!({ :chxt => chxt.join(",") }) unless chxt.empty?
|
|
349
|
-
params.merge!({ :chxl => chxl.compact.join("|") }) unless chxl.compact.empty?
|
|
350
|
-
params.merge!({ :chxp => chxp.compact.join("|") }) unless chxp.compact.empty?
|
|
351
|
-
params.merge!({ :chxr => chxr.compact.join("|") }) unless chxr.compact.empty?
|
|
352
|
-
params.merge!({ :chxs => chxs.compact.join("|") }) unless chxs.compact.empty?
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
def add_grid
|
|
356
|
-
params.merge!({ :chg => @grid_str }) if @grid_str
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
def add_markers
|
|
360
|
-
params.merge!({:chm => @markers.join("|")})
|
|
361
|
-
end
|
|
355
|
+
def add_grid
|
|
356
|
+
params.merge!({ :chg => @grid_str }) if @grid_str
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def add_markers
|
|
360
|
+
params.merge!({:chm => @markers.join("|")})
|
|
361
|
+
end
|
|
362
362
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
363
|
+
def add_data
|
|
364
|
+
converted_data = process_data
|
|
365
|
+
case data_encoding
|
|
366
|
+
when :simple
|
|
367
|
+
converted_data = "s:" + converted_data
|
|
368
|
+
when :text
|
|
369
|
+
converted_data = "t:" + converted_data
|
|
370
|
+
when :extended
|
|
371
|
+
converted_data = "e:" + converted_data
|
|
372
|
+
else
|
|
373
|
+
raise "Illegal Encoding Specified"
|
|
374
|
+
end
|
|
375
|
+
params.merge!({:chd => converted_data})
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def encode_data(values, max_value=nil)
|
|
379
|
+
case data_encoding
|
|
380
|
+
when :simple
|
|
381
|
+
simple_encode(values, max_value)
|
|
382
|
+
when :text
|
|
383
|
+
text_encode(values, max_value)
|
|
384
|
+
when :extended
|
|
385
|
+
extended_encode(values, max_value)
|
|
386
|
+
else
|
|
387
|
+
raise "Illegal Encoding Specified"
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def simple_encode(values, max_value=nil)
|
|
392
|
+
alphabet_length = 61
|
|
393
|
+
max_value = values.max unless max_value
|
|
394
394
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
end
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
return chart_data.join('')
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
def text_encode(values, max_value=nil)
|
|
411
|
-
max_value = values.max unless max_value
|
|
412
|
-
values.inject("") { |sum, v|
|
|
413
|
-
if max_value == 0
|
|
414
|
-
sum += "0,"
|
|
415
|
-
else
|
|
416
|
-
sum += ( "%.1f" % (v*100/max_value) ) + ","
|
|
417
|
-
end
|
|
418
|
-
}.chomp(",")
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
def extended_encode(values, max_value)
|
|
422
|
-
max_value = values.max unless max_value
|
|
423
|
-
values.collect { |v|
|
|
424
|
-
if max_value == 0
|
|
425
|
-
@@complex_encoding[0]
|
|
426
|
-
else
|
|
427
|
-
@@complex_encoding[(v * 4095/max_value).to_i]
|
|
428
|
-
end
|
|
429
|
-
}.join('')
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
def join_encoded_data(encoded_data)
|
|
433
|
-
encoded_data.join((self.data_encoding == :simple) ? "," : "|")
|
|
434
|
-
end
|
|
435
|
-
|
|
436
|
-
def max_data_value
|
|
437
|
-
@max_data or @data.flatten.max
|
|
395
|
+
chart_data = values.collect do |val|
|
|
396
|
+
if val.to_i >=0
|
|
397
|
+
if max_value == 0
|
|
398
|
+
SIMPLE_ENCODING[0]
|
|
399
|
+
else
|
|
400
|
+
SIMPLE_ENCODING[(alphabet_length * val / max_value).to_i]
|
|
401
|
+
end
|
|
402
|
+
else
|
|
403
|
+
"_"
|
|
438
404
|
end
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
return chart_data.join('')
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def text_encode(values, max_value=nil)
|
|
411
|
+
max_value = values.max unless max_value
|
|
412
|
+
values.inject("") { |sum, v|
|
|
413
|
+
if max_value == 0
|
|
414
|
+
sum += "0,"
|
|
415
|
+
else
|
|
416
|
+
sum += ( "%.1f" % (v*100/max_value) ) + ","
|
|
442
417
|
end
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
418
|
+
}.chomp(",")
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def extended_encode(values, max_value)
|
|
422
|
+
max_value = values.max unless max_value
|
|
423
|
+
values.collect { |v|
|
|
424
|
+
if max_value == 0
|
|
425
|
+
@@complex_encoding[0]
|
|
426
|
+
else
|
|
427
|
+
@@complex_encoding[(v * 4095/max_value).to_i]
|
|
446
428
|
end
|
|
429
|
+
}.join('')
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def join_encoded_data(encoded_data)
|
|
433
|
+
encoded_data.join((self.data_encoding == :simple or self.data_encoding == :extended) ? "," : "|")
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def max_data_value
|
|
437
|
+
@max_data or @data.flatten.max
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def max_x_value
|
|
441
|
+
@max_x or x_data.flatten.max
|
|
442
|
+
end
|
|
447
443
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
end
|
|
452
|
-
end
|
|
444
|
+
def max_y_value
|
|
445
|
+
@max_y or y_data.flatten.max
|
|
446
|
+
end
|
|
453
447
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
end
|
|
448
|
+
def x_data
|
|
449
|
+
@data.collect do |series|
|
|
450
|
+
series.collect { |val| val.first }
|
|
451
|
+
end
|
|
459
452
|
end
|
|
460
|
-
|
|
453
|
+
|
|
454
|
+
def y_data
|
|
455
|
+
@data.collect do |series|
|
|
456
|
+
series.collect { |val| val.last }
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
end
|
data/lib/test.rb
CHANGED
|
@@ -138,5 +138,20 @@ stacked.title_font_size=18
|
|
|
138
138
|
puts "\nStacked Chart with colored title"
|
|
139
139
|
puts stacked.to_url
|
|
140
140
|
|
|
141
|
+
# Encoding Error (Bar Chart)
|
|
142
|
+
bc = GoogleChart::BarChart.new('800x350', nil, :vertical, true) do |chart|
|
|
143
|
+
chart.data_encoding = :extended
|
|
144
|
+
|
|
145
|
+
chart.data "2^i", (0..8).to_a.collect{|i| 2**i}, "ff0000"
|
|
146
|
+
chart.data "2.1^i", (0..8).to_a.collect{|i| 2.1**i}, "00ff00"
|
|
147
|
+
chart.data "2.2^i", (0..8).to_a.collect{|i| 2.2**i}, "0000ff"
|
|
148
|
+
max = 2.2**8
|
|
149
|
+
|
|
150
|
+
chart.show_legend = true
|
|
151
|
+
chart.axis :y, :range => [0,max], :font_size => 16, :alignment => :center
|
|
152
|
+
chart.axis :x, :labels => (0..8).to_a, :font_size => 16, :alignment => :center
|
|
153
|
+
end
|
|
141
154
|
|
|
155
|
+
puts "\nBar chart encoding error test"
|
|
156
|
+
puts bc.to_url
|
|
142
157
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gchartrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Deepak Jois
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2008-01-
|
|
12
|
+
date: 2008-01-23 00:00:00 +08:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|