analytics_charts 1.6.3 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/analytics_charts/custom_module.rb +14 -11
- data/lib/analytics_charts/custom_pie.rb +58 -20
- data/lib/analytics_charts/pie_and_labels.rb +15 -10
- data/lib/analytics_charts/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3591ea166bdaed5eb90ee72f9881c17f8b94f86c
|
4
|
+
data.tar.gz: 387073f74b7a5f8816ffbfa5f38c2cbc1491f5dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 828091a522244d336487604fe644b8a429d65d9d16c3060ed962bc2f349ef00a6e41e992c8f8a7fecfbb0efebe65107f73f73150a0967c56f2110c118bfb0123
|
7
|
+
data.tar.gz: 8c59f8315e3ce67d40a2b0dcc15a22080efa8a60176d03de04fb06765fcfe89ac9d457b19c28cc2641b587d5303551125b68c1676540de2bb81a666980fc6458
|
@@ -14,7 +14,6 @@ class AnalyticsCharts::CustomModule
|
|
14
14
|
@dummy_image = Image.new(1,1)
|
15
15
|
@composite_columns = @composite_image.columns
|
16
16
|
@composite_rows = @composite_image.rows
|
17
|
-
puts "@composite_columns: " + @composite_columns.to_s
|
18
17
|
text = text.gsub(/['%]/, '%' => '%%', "'" => "\'")
|
19
18
|
begin
|
20
19
|
@rows_of_text = tokenize_text_by_lines(text)
|
@@ -24,9 +23,14 @@ class AnalyticsCharts::CustomModule
|
|
24
23
|
end
|
25
24
|
|
26
25
|
num_separators = @rows_of_text.count {|row| row.empty? }
|
27
|
-
|
28
|
-
|
29
|
-
@
|
26
|
+
num_special_sep = @rows_of_text.count {|row| row.include? "@$$" }
|
27
|
+
@line_height = @pointsize + 2
|
28
|
+
@sep_offset = @line_height / 2
|
29
|
+
starting_offset = @line_height / 2
|
30
|
+
ending_offset = @line_height / 2
|
31
|
+
@height = @composite_rows + (@rows_of_text.size - num_separators) *
|
32
|
+
@line_height + (num_separators-num_special_sep) * @sep_offset +
|
33
|
+
starting_offset + ending_offset
|
30
34
|
@base_image = Image.new(@composite_columns, @height) {
|
31
35
|
self.background_color = "black"
|
32
36
|
}
|
@@ -35,19 +39,19 @@ class AnalyticsCharts::CustomModule
|
|
35
39
|
@d.stroke_width(1)
|
36
40
|
@d = @d.line(0, @composite_rows, @composite_columns, @composite_rows)
|
37
41
|
@d.draw(@base_image)
|
38
|
-
y_offset =
|
42
|
+
y_offset = @composite_rows + starting_offset
|
39
43
|
@rows_of_text.each do |text|
|
40
44
|
if text.include? "@$$" # No paragraph break if we insert this uncommonly used word
|
41
45
|
text.sub!("@$$", "")
|
42
46
|
y_offset -= @sep_offset
|
47
|
+
y_offset += @line_height
|
43
48
|
@d.annotate(@base_image, 0 ,0, @pointsize, y_offset, text)
|
44
|
-
y_offset += @pointsize
|
45
49
|
next
|
46
50
|
else
|
47
51
|
if text.empty?
|
48
52
|
y_offset += @sep_offset
|
49
53
|
else
|
50
|
-
y_offset += @
|
54
|
+
y_offset += @line_height
|
51
55
|
@d.annotate(@base_image, 0 ,0, @pointsize, y_offset, text)
|
52
56
|
end
|
53
57
|
end
|
@@ -68,12 +72,12 @@ class AnalyticsCharts::CustomModule
|
|
68
72
|
def line_wrap(text)
|
69
73
|
tokens = text.split.reverse # Pop stuff off
|
70
74
|
# Safety check, do not allow super long words.
|
71
|
-
tokens.each {|token| return "" if not fits_in_a_line(token) }
|
75
|
+
tokens.each {|token| return "" if not fits_in_a_line?(token) }
|
72
76
|
line_wrap_tokens = Array.new
|
73
77
|
line_builder = ""
|
74
78
|
while tokens.size != 0
|
75
79
|
line_builder = tokens.pop # Pop the first word in a line
|
76
|
-
while tokens.size != 0 and fits_in_a_line(line_builder + " " + tokens.last)
|
80
|
+
while tokens.size != 0 and fits_in_a_line?(line_builder + " " + tokens.last)
|
77
81
|
line_builder += " " + tokens.pop
|
78
82
|
end
|
79
83
|
line_wrap_tokens.push(line_builder) # Add to list of lines
|
@@ -81,8 +85,7 @@ class AnalyticsCharts::CustomModule
|
|
81
85
|
line_wrap_tokens
|
82
86
|
end
|
83
87
|
|
84
|
-
def fits_in_a_line(text)
|
85
|
-
puts text + " SIZE: " + @d.get_type_metrics(@dummy_image,text).width.to_s + " COLUMNS: " + (@composite_image.columns - 36).to_s
|
88
|
+
def fits_in_a_line?(text)
|
86
89
|
return @d.get_type_metrics(@dummy_image,text).width < @composite_image.columns - 36
|
87
90
|
end
|
88
91
|
end
|
@@ -10,6 +10,7 @@ class AnalyticsCharts::CustomPie
|
|
10
10
|
attr_accessor :label_start_x
|
11
11
|
attr_accessor :label_start_y
|
12
12
|
attr_accessor :label_offset
|
13
|
+
|
13
14
|
def initialize(image_path, label_hash, pie_label_hash)
|
14
15
|
@base_image = Image.read(image_path)[0]
|
15
16
|
@columns = @base_image.columns
|
@@ -44,6 +45,7 @@ class AnalyticsCharts::CustomPie
|
|
44
45
|
def highest_score(index, score)
|
45
46
|
@thresholds[index] = score
|
46
47
|
end
|
48
|
+
|
47
49
|
def insert_pie_data(name, amount, quality)
|
48
50
|
#convert all '' instances to an apostrophe
|
49
51
|
name = name.gsub(/'/, "\'")
|
@@ -58,13 +60,24 @@ class AnalyticsCharts::CustomPie
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
63
|
+
def label_attributes=(label = {})
|
64
|
+
@label_attributes = label
|
65
|
+
end
|
66
|
+
|
67
|
+
def label_attributes
|
68
|
+
@label_attributes ||= {}
|
69
|
+
end
|
70
|
+
|
71
|
+
def label_height=(height)
|
72
|
+
@label_height = height
|
73
|
+
end
|
74
|
+
|
75
|
+
def label_height
|
76
|
+
@label_height ||= 12
|
77
|
+
end
|
78
|
+
|
61
79
|
def insert_text_with_circle(x_offset, y_offset, text, features = {})
|
62
|
-
|
63
|
-
set_feature(feature, attribute)
|
64
|
-
}
|
65
|
-
# Double quotes automatically escaped in rails db. Refer to Rmagick doc for escaping stuff
|
66
|
-
text = text.gsub(/['%]/, '%' => '%%', "'" => "\'")
|
67
|
-
@d.annotate(@base_image, 0 ,0, x_offset, y_offset, text)
|
80
|
+
insert_text(x_offset, y_offset, text, features)
|
68
81
|
height = @d.get_type_metrics(@base_image, text).ascent
|
69
82
|
y_offset -= height / 2
|
70
83
|
circle_xpos = x_offset - 10
|
@@ -79,6 +92,7 @@ class AnalyticsCharts::CustomPie
|
|
79
92
|
features.each { |feature, attribute|
|
80
93
|
set_feature(feature, attribute)
|
81
94
|
}
|
95
|
+
# Double quotes automatically escaped in rails db. Refer to Rmagick doc for escaping stuff
|
82
96
|
text = text.gsub(/['%]/, '%' => '%%', "'" => "\'")
|
83
97
|
@d.annotate(@base_image, 0 ,0, x_offset, y_offset, text)
|
84
98
|
end
|
@@ -95,7 +109,7 @@ class AnalyticsCharts::CustomPie
|
|
95
109
|
# If we don't refresh draw, future "@d.draw(@base_image)" will redraw the circle,
|
96
110
|
# overlapping on the text written below
|
97
111
|
@d = Draw.new
|
98
|
-
insert_text(@pie_center_x - 30, @pie_center_y, "No Data",
|
112
|
+
insert_text(@pie_center_x - 30, @pie_center_y, "(No Data)",
|
99
113
|
@label_hash.merge({'fill'=> '#000000', 'font_weight'=> 700 }))
|
100
114
|
return
|
101
115
|
end
|
@@ -165,10 +179,10 @@ class AnalyticsCharts::CustomPie
|
|
165
179
|
end
|
166
180
|
end
|
167
181
|
prev_degrees = 60.0 # Now focus on labels
|
168
|
-
@aggregate.each_with_index do |
|
182
|
+
@aggregate.each_with_index do |cluster_data_value, i|
|
169
183
|
next if degrees[i] == 0
|
170
184
|
half_angle = prev_degrees + degrees[i] / 2
|
171
|
-
label_string =
|
185
|
+
label_string = process_pie_label_data(cluster_data_value)
|
172
186
|
draw_pie_label(@pie_center_x,@pie_center_y, half_angle + label_offset_degrees[i],
|
173
187
|
@pie_radius, label_string, i)
|
174
188
|
prev_degrees += degrees[i]
|
@@ -176,6 +190,26 @@ class AnalyticsCharts::CustomPie
|
|
176
190
|
end
|
177
191
|
end
|
178
192
|
|
193
|
+
def process_pie_label_data(cluster_data_value)
|
194
|
+
if cluster_data_value < 10**3
|
195
|
+
return '$' + cluster_data_value.round(0).to_s
|
196
|
+
elsif cluster_data_value < 10**6
|
197
|
+
cluster_data_value /= 10**3 # Truncates decimals
|
198
|
+
return '$' + cluster_data_value.round(0).to_s + 'K'# Round is unnecessary, but add anyways
|
199
|
+
elsif cluster_data_value < 10**9
|
200
|
+
cluster_data_value /= 10**6
|
201
|
+
return '$' + cluster_data_value.round(0).to_s + 'M'
|
202
|
+
elsif cluster_data_value < 10**12
|
203
|
+
cluster_data_value /= 10**9
|
204
|
+
return '$' + cluster_data_value.round(0).to_s + 'B'
|
205
|
+
elsif cluster_data_value < 10**15
|
206
|
+
cluster_data_value /= 10**12
|
207
|
+
return '$' + cluster_data_value.round(0).to_s + 'T'
|
208
|
+
else
|
209
|
+
return '>1T'
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
179
213
|
def write(filename='graph.png')
|
180
214
|
draw
|
181
215
|
draw_labels
|
@@ -187,50 +221,49 @@ class AnalyticsCharts::CustomPie
|
|
187
221
|
sorted_data = @data.sort_by{|key,value| -value[1]} # Sort by descending quality
|
188
222
|
x_offset = @label_start_x + 15
|
189
223
|
y_offset = @label_start_y
|
224
|
+
@label_hash = @label_hash.merge(label_attributes)
|
190
225
|
for data in sorted_data
|
191
226
|
has_data = false
|
192
227
|
if data[1][0] > 0 # Amount > 0
|
193
|
-
font_weight = 900 # Very Bold
|
194
228
|
text = data[0]
|
195
229
|
has_data = true
|
196
230
|
else
|
197
231
|
text = data[0]
|
198
|
-
font_weight = 900 # Very Bold
|
199
232
|
end
|
200
233
|
if has_data
|
201
234
|
case data[1][1]
|
202
235
|
when 3
|
203
236
|
# label_hash gets merged and overrided by fill and font_weight.
|
204
237
|
insert_text_with_circle(x_offset, y_offset, text,
|
205
|
-
@label_hash.merge({'fill'=> '#1E753B'
|
238
|
+
@label_hash.merge({'fill'=> '#1E753B'}))
|
206
239
|
when 2
|
207
240
|
insert_text_with_circle(x_offset, y_offset, text,
|
208
|
-
@label_hash.merge({'fill'=> '#C1B630'
|
241
|
+
@label_hash.merge({'fill'=> '#C1B630'}))
|
209
242
|
when 1
|
210
243
|
insert_text_with_circle(x_offset, y_offset, text,
|
211
|
-
@label_hash.merge({'fill'=> '#BE6428'
|
244
|
+
@label_hash.merge({'fill'=> '#BE6428'}))
|
212
245
|
when 0
|
213
246
|
insert_text_with_circle(x_offset, y_offset, text,
|
214
|
-
@label_hash.merge({'fill'=> '#AD1F25'
|
247
|
+
@label_hash.merge({'fill'=> '#AD1F25'}))
|
215
248
|
end
|
216
249
|
else
|
217
250
|
case data[1][1]
|
218
251
|
when 3
|
219
252
|
# label_hash gets merged and overrided by fill and font_weight.
|
220
253
|
insert_text(x_offset, y_offset, text,
|
221
|
-
@label_hash.merge({'fill'=> '#1E753B'
|
254
|
+
@label_hash.merge({'fill'=> '#1E753B'}))
|
222
255
|
when 2
|
223
256
|
insert_text(x_offset, y_offset, text,
|
224
|
-
@label_hash.merge({'fill'=> '#C1B630'
|
257
|
+
@label_hash.merge({'fill'=> '#C1B630'}))
|
225
258
|
when 1
|
226
259
|
insert_text(x_offset, y_offset, text,
|
227
|
-
@label_hash.merge({'fill'=> '#BE6428'
|
260
|
+
@label_hash.merge({'fill'=> '#BE6428'}))
|
228
261
|
when 0
|
229
262
|
insert_text(x_offset, y_offset, text,
|
230
|
-
@label_hash.merge({'fill'=> '#AD1F25'
|
263
|
+
@label_hash.merge({'fill'=> '#AD1F25'}))
|
231
264
|
end
|
232
265
|
end
|
233
|
-
y_offset +=
|
266
|
+
y_offset += self.label_height
|
234
267
|
end
|
235
268
|
insert_text_with_circle(x_offset, y_offset, '= purchased by you',
|
236
269
|
@label_hash.merge({'fill'=> '#252525', 'font_weight'=> 900 }))
|
@@ -269,6 +302,11 @@ class AnalyticsCharts::CustomPie
|
|
269
302
|
insert_text(x, y, percent, {'fill'=> @colors[index]}.merge(@pie_label_hash))# {'fill'=> 'black', 'font_weight'=> 700, 'pointsize'=>48})
|
270
303
|
end
|
271
304
|
|
305
|
+
def recalibrate_metrics_for_labels
|
306
|
+
label_attributes.each { |feature, attribute|
|
307
|
+
set_feature(feature, attribute)
|
308
|
+
}
|
309
|
+
end
|
272
310
|
def set_feature(feature, attribute)
|
273
311
|
begin
|
274
312
|
case feature
|
@@ -12,19 +12,24 @@ class AnalyticsCharts::PieAndLabels < AnalyticsCharts::CustomPie
|
|
12
12
|
@d.font_weight = 700
|
13
13
|
@dummy_image = Image.new(1,1)
|
14
14
|
@composite_columns = @composite_image.columns
|
15
|
-
puts @composite_columns
|
16
15
|
@composite_rows = @composite_image.rows
|
17
|
-
@org_text_size = 14
|
18
16
|
organization = organization.gsub(/['%]/, '%' => '%%', "'" => "\'")
|
17
|
+
@org_text_size = 14
|
18
|
+
@org_height = @org_text_size + 1
|
19
19
|
@org_texts = tokenize_text_by_lines(organization,
|
20
20
|
{'fill' => '#FFFFFF', 'pointsize'=> @org_text_size, 'font_weight'=> 500 })
|
21
|
+
org_text_offset = @org_texts.size * @org_height
|
22
|
+
|
21
23
|
@label_size = 16
|
22
|
-
|
24
|
+
self.label_attributes = {'pointsize' => @label_size, 'font_weight' => 900}
|
25
|
+
recalibrate_metrics_for_labels
|
26
|
+
self.label_height = @label_size + 1
|
27
|
+
|
23
28
|
# (num_labels + 1) to account for white key on bottom of labels
|
24
|
-
@height_with_no_disclaimer = [200 + 20, 20 +
|
29
|
+
@height_with_no_disclaimer = [200 + 20, 20 + self.label_height * (num_labels + 1) + 20].max + @composite_rows + org_text_offset
|
25
30
|
disclaimer = disclaimer.gsub(/['%]/, '%' => '%%', "'" => "\'")
|
26
31
|
@disclaimer_texts = tokenize_text_by_lines(disclaimer)
|
27
|
-
@height = @height_with_no_disclaimer + @disclaimer_texts.size * 12
|
32
|
+
@height = @height_with_no_disclaimer + @disclaimer_texts.size * 12
|
28
33
|
@data = Hash.new # Value is array with two items
|
29
34
|
@aggregate = Array([0,0,0,0]) # Cluster brands into categories
|
30
35
|
@label_hash = {'pointsize'=> @label_size,'font_weight'=> 700 }
|
@@ -45,11 +50,11 @@ class AnalyticsCharts::PieAndLabels < AnalyticsCharts::CustomPie
|
|
45
50
|
insert_text(22, y_offset ,text,
|
46
51
|
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> @org_text_size, 'font_weight'=> 500 }))
|
47
52
|
@d.annotate(@base_image, 0 ,0, 22, y_offset, text)
|
48
|
-
y_offset += @
|
53
|
+
y_offset += @org_height
|
49
54
|
end
|
50
55
|
end
|
51
56
|
def annotate_disclaimer
|
52
|
-
y_offset = @height_with_no_disclaimer + @d.get_type_metrics(@dummy_image,"a").height
|
57
|
+
y_offset = @height_with_no_disclaimer + @d.get_type_metrics(@dummy_image,"a").height
|
53
58
|
@disclaimer_texts.each do |text|
|
54
59
|
if text.include? "@$$" # No paragraph break if we insert this uncommonly used word
|
55
60
|
text.sub!("@$$", "")
|
@@ -153,12 +158,12 @@ class AnalyticsCharts::PieAndLabels < AnalyticsCharts::CustomPie
|
|
153
158
|
def line_wrap(text)
|
154
159
|
tokens = text.split.reverse # Pop stuff off
|
155
160
|
# Safety check, do not allow super long words.
|
156
|
-
tokens.each {|token| return "" if not fits_in_a_line(token) }
|
161
|
+
tokens.each {|token| return "" if not fits_in_a_line?(token) }
|
157
162
|
line_wrap_tokens = Array.new
|
158
163
|
line_builder = ""
|
159
164
|
while tokens.size != 0
|
160
165
|
line_builder = tokens.pop # Pop the first word in a line
|
161
|
-
while tokens.size != 0 and fits_in_a_line(line_builder + " " + tokens.last)
|
166
|
+
while tokens.size != 0 and fits_in_a_line?(line_builder + " " + tokens.last)
|
162
167
|
line_builder += " " + tokens.pop
|
163
168
|
end
|
164
169
|
line_wrap_tokens.push(line_builder) # Add to list of lines
|
@@ -166,7 +171,7 @@ class AnalyticsCharts::PieAndLabels < AnalyticsCharts::CustomPie
|
|
166
171
|
line_wrap_tokens
|
167
172
|
end
|
168
173
|
|
169
|
-
def fits_in_a_line(text)
|
174
|
+
def fits_in_a_line?(text)
|
170
175
|
return @d.get_type_metrics(@dummy_image,text).width < @composite_columns - 44
|
171
176
|
end
|
172
177
|
|