analytics_charts 1.0.1 → 1.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93a5bd0a808bfc90c8f26d22a999a5e9adf2413e
|
4
|
+
data.tar.gz: be519887864455ab6f7fc1f12ea87efdf6799c60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9872c528be5c5a08b3d241e99889b258672654f4eb169c17a3ce7afafa837a4322bdf8b767eb5de2523a37c9e410561d0d6ef9a00d919c96d441f16c31c525b4
|
7
|
+
data.tar.gz: 654eff27a17925d1134d695dfcdb39a06ad749d98c3add848068e11d390b7a527a1b29e379e59d631383dbdb6a6d7d4a43b540114e9e2d26b52acb2501bf4ba3
|
data/lib/analytics_charts.rb
CHANGED
@@ -23,7 +23,6 @@ class AnalyticsCharts::CustomModule
|
|
23
23
|
self.background_color = "black"
|
24
24
|
}
|
25
25
|
@base_image.composite!(@composite_image,0,0,OverCompositeOp)
|
26
|
-
#@d.stroke = 'white'
|
27
26
|
@d = @d.stroke_color 'white'
|
28
27
|
@d.stroke_width(1)
|
29
28
|
@d = @d.line(0, @composite_rows, @composite_columns, @composite_rows)
|
@@ -29,6 +29,7 @@ class AnalyticsCharts::CustomPie
|
|
29
29
|
@label_start_y = label_start_y
|
30
30
|
@label_offset = label_offset
|
31
31
|
end
|
32
|
+
|
32
33
|
def set_pie_geometry(x, y, radius)
|
33
34
|
@pie_center_x = x
|
34
35
|
@pie_center_y = y
|
@@ -131,7 +132,6 @@ class AnalyticsCharts::CustomPie
|
|
131
132
|
@pie_radius, label_string, i)
|
132
133
|
prev_degrees += degrees[i]
|
133
134
|
end
|
134
|
-
@d.draw(@base_image)
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'RMagick'
|
2
|
+
|
3
|
+
class AnalyticsCharts::PieAndLabels < AnalyticsCharts::CustomPie
|
4
|
+
include Magick
|
5
|
+
def initialize(meme, width, num_labels, organization, disclaimer)
|
6
|
+
@organization = organization
|
7
|
+
@legend_data = Array.new(["","","",""])
|
8
|
+
@columns = width
|
9
|
+
@composite_image = Image.read(meme)[0]
|
10
|
+
@composite_columns = @composite_image.columns
|
11
|
+
@composite_rows = @composite_image.rows
|
12
|
+
@rows_with_no_disclaimer = [200 + 20, 20 + 16 * num_labels + 20].max + @composite_rows
|
13
|
+
@dummy_image = Image.new(1,1)
|
14
|
+
@d = Draw.new
|
15
|
+
@d.pointsize = 12
|
16
|
+
@d.font_weight = 700
|
17
|
+
@rows_of_text = tokenize_text_by_lines(disclaimer)
|
18
|
+
@rows = @rows_with_no_disclaimer + @rows_of_text.size * 12 + 5
|
19
|
+
@data = Hash.new # Value is array with two items
|
20
|
+
@aggregate = Array([0,0,0,0]) # Cluster brands into categories
|
21
|
+
@label_hash = {'pointsize'=> 16,'font_weight'=> 700 }
|
22
|
+
@pie_label_hash = {'pointsize'=> 14, 'font_weight' => 600 }
|
23
|
+
set_pie_colors(%w(#AD1F25 #BE6428 #C1B630 #1E753B))
|
24
|
+
@base_image = Image.new(@columns, @rows) {
|
25
|
+
self.background_color = "black"
|
26
|
+
}
|
27
|
+
@base_image.composite!(@composite_image,0,0,OverCompositeOp)
|
28
|
+
set_pie_geometry(325, 100+ @composite_rows, 50)
|
29
|
+
set_label_values(22, 20+@composite_rows, 16)
|
30
|
+
y_offset = @rows_with_no_disclaimer + @d.get_type_metrics(@dummy_image,"a").height + 5
|
31
|
+
@rows_of_text.each do |text|
|
32
|
+
if text.include? "@$$" # No paragraph break if we insert this uncommonly used word
|
33
|
+
text.sub!("@$$", "")
|
34
|
+
insert_text(22, y_offset ,text,
|
35
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 12 }))
|
36
|
+
@d.annotate(@base_image, 0 ,0, 22, y_offset, text)
|
37
|
+
next
|
38
|
+
else
|
39
|
+
insert_text(22, y_offset ,text,
|
40
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 12 }))
|
41
|
+
y_offset += 12
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def write(filename='graph.png')
|
47
|
+
draw
|
48
|
+
draw_labels
|
49
|
+
draw_organization
|
50
|
+
draw_legend
|
51
|
+
draw_line
|
52
|
+
@d.draw(@base_image)
|
53
|
+
@base_image.write(filename)
|
54
|
+
end
|
55
|
+
|
56
|
+
def draw_organization
|
57
|
+
insert_text(22, @rows_with_no_disclaimer - 10, @organization,
|
58
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 10 }))
|
59
|
+
end
|
60
|
+
|
61
|
+
def insert_legend(label, quality)
|
62
|
+
@legend_data[quality] = label
|
63
|
+
end
|
64
|
+
|
65
|
+
def draw_legend
|
66
|
+
y_offset = 230 + @composite_rows
|
67
|
+
@d.fill_opacity(1)
|
68
|
+
@d.stroke_width(0)
|
69
|
+
@d = @d.stroke 'transparent'
|
70
|
+
x_pos = 230
|
71
|
+
side_length = 15
|
72
|
+
@legend_data.each_with_index do |data, index|
|
73
|
+
case index
|
74
|
+
when 3
|
75
|
+
insert_text(x_pos + 20, y_offset + 12, data,
|
76
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 10 }))
|
77
|
+
@d.fill('#1E753B')
|
78
|
+
@d.rectangle(x_pos,y_offset,x_pos + side_length, y_offset + side_length)
|
79
|
+
when 2
|
80
|
+
insert_text(x_pos + 20, y_offset + 12, data,
|
81
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 10 }))
|
82
|
+
@d.fill('#C1B630')
|
83
|
+
@d.rectangle(x_pos,y_offset,x_pos + side_length, y_offset + side_length)
|
84
|
+
when 1
|
85
|
+
insert_text(x_pos + 20, y_offset + 12, data,
|
86
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 10 }))
|
87
|
+
@d.fill('#BE6428')
|
88
|
+
@d.rectangle(x_pos,y_offset,x_pos + side_length, y_offset + side_length)
|
89
|
+
when 0
|
90
|
+
insert_text(x_pos + 20, y_offset + 12, data,
|
91
|
+
@label_hash.merge({'fill' => '#FFFFFF', 'pointsize'=> 10 }))
|
92
|
+
@d.fill('#AD1F25')
|
93
|
+
@d.rectangle(x_pos,y_offset,x_pos + side_length, y_offset + side_length)
|
94
|
+
end
|
95
|
+
y_offset -= side_length
|
96
|
+
end
|
97
|
+
end
|
98
|
+
def draw_line
|
99
|
+
@d.stroke('white')
|
100
|
+
@d.stroke_width(1)
|
101
|
+
@d.line(0,@rows_with_no_disclaimer,@columns,@rows_with_no_disclaimer)
|
102
|
+
end
|
103
|
+
|
104
|
+
def tokenize_text_by_lines(text)
|
105
|
+
# First split the text by the line carriage element
|
106
|
+
carriage_split_lines = text.split("\r\n")
|
107
|
+
line_tokens = Array.new
|
108
|
+
carriage_split_lines.each do |carriage_split_line|
|
109
|
+
line_wrap_lines = line_wrap(carriage_split_line)
|
110
|
+
line_wrap_lines.each { |line| line_tokens.push(line) }
|
111
|
+
line_tokens.push("\r\n")
|
112
|
+
end
|
113
|
+
line_tokens
|
114
|
+
end
|
115
|
+
def line_wrap(text)
|
116
|
+
tokens = text.split.reverse # Pop stuff off
|
117
|
+
# Safety check, do not allow super long words.
|
118
|
+
tokens.each {|token| return "" if not fits_in_a_line(token) }
|
119
|
+
line_wrap_tokens = Array.new
|
120
|
+
line_builder = ""
|
121
|
+
while tokens.size != 0
|
122
|
+
line_builder = tokens.pop # Pop the first word in a line
|
123
|
+
while tokens.size != 0 and fits_in_a_line(line_builder + " " + tokens.last)
|
124
|
+
line_builder += " " + tokens.pop
|
125
|
+
end
|
126
|
+
line_wrap_tokens.push(line_builder) # Add to list of lines
|
127
|
+
end
|
128
|
+
line_wrap_tokens
|
129
|
+
end
|
130
|
+
|
131
|
+
def fits_in_a_line(text)
|
132
|
+
return @d.get_type_metrics(@dummy_image,text).width < @columns - 44
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: analytics_charts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- STEPHEN YU
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- lib/analytics_charts.rb
|
74
74
|
- lib/analytics_charts/custom_module.rb
|
75
75
|
- lib/analytics_charts/custom_pie.rb
|
76
|
+
- lib/analytics_charts/pie_and_labels.rb
|
76
77
|
- lib/analytics_charts/version.rb
|
77
78
|
homepage: https://github.com/tryceattack/analytics_charts
|
78
79
|
licenses:
|