analytics_charts 1.6.3 → 1.7.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.
- 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
|
|