gruff 0.6.0-java → 0.11.0-java

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.
Files changed (121) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +14 -0
  3. data/.github/ISSUE_TEMPLATE.md +18 -0
  4. data/.gitignore +3 -0
  5. data/.rubocop.yml +109 -0
  6. data/.rubocop_todo.yml +112 -0
  7. data/.travis.yml +24 -15
  8. data/.yardopts +1 -0
  9. data/{History.txt → CHANGELOG.md} +72 -25
  10. data/Gemfile +3 -7
  11. data/README.md +57 -25
  12. data/Rakefile +21 -192
  13. data/assets/plastik/blue.png +0 -0
  14. data/assets/plastik/green.png +0 -0
  15. data/assets/plastik/red.png +0 -0
  16. data/docker/Dockerfile +14 -0
  17. data/docker/build.sh +4 -0
  18. data/docker/launch.sh +4 -0
  19. data/gruff.gemspec +21 -13
  20. data/init.rb +2 -0
  21. data/lib/gruff.rb +26 -2
  22. data/lib/gruff/accumulator_bar.rb +18 -8
  23. data/lib/gruff/area.rb +33 -19
  24. data/lib/gruff/bar.rb +76 -45
  25. data/lib/gruff/base.rb +435 -704
  26. data/lib/gruff/bezier.rb +32 -17
  27. data/lib/gruff/bullet.rb +62 -68
  28. data/lib/gruff/dot.rb +38 -82
  29. data/lib/gruff/helper/bar_conversion.rb +47 -0
  30. data/lib/gruff/helper/bar_value_label_mixin.rb +30 -0
  31. data/lib/gruff/helper/stacked_mixin.rb +23 -0
  32. data/lib/gruff/histogram.rb +60 -0
  33. data/lib/gruff/line.rb +134 -170
  34. data/lib/gruff/mini/bar.rb +17 -10
  35. data/lib/gruff/mini/legend.rb +24 -36
  36. data/lib/gruff/mini/pie.rb +18 -12
  37. data/lib/gruff/mini/side_bar.rb +26 -12
  38. data/lib/gruff/net.rb +68 -81
  39. data/lib/gruff/patch/rmagick.rb +33 -0
  40. data/lib/gruff/patch/string.rb +10 -0
  41. data/lib/gruff/photo_bar.rb +39 -42
  42. data/lib/gruff/pie.rb +180 -89
  43. data/lib/gruff/renderer/bezier.rb +21 -0
  44. data/lib/gruff/renderer/circle.rb +21 -0
  45. data/lib/gruff/renderer/dash_line.rb +22 -0
  46. data/lib/gruff/renderer/dot.rb +39 -0
  47. data/lib/gruff/renderer/ellipse.rb +21 -0
  48. data/lib/gruff/renderer/line.rb +42 -0
  49. data/lib/gruff/renderer/polygon.rb +23 -0
  50. data/lib/gruff/renderer/polyline.rb +21 -0
  51. data/lib/gruff/renderer/rectangle.rb +19 -0
  52. data/lib/gruff/renderer/renderer.rb +132 -0
  53. data/lib/gruff/renderer/text.rb +53 -0
  54. data/lib/gruff/scatter.rb +163 -182
  55. data/lib/gruff/scene.rb +31 -41
  56. data/lib/gruff/side_bar.rb +81 -65
  57. data/lib/gruff/side_stacked_bar.rb +78 -62
  58. data/lib/gruff/spider.rb +49 -57
  59. data/lib/gruff/stacked_area.rb +40 -32
  60. data/lib/gruff/stacked_bar.rb +86 -53
  61. data/lib/gruff/store/base_data.rb +38 -0
  62. data/lib/gruff/store/custom_data.rb +38 -0
  63. data/lib/gruff/store/store.rb +80 -0
  64. data/lib/gruff/store/xy_data.rb +59 -0
  65. data/lib/gruff/themes.rb +32 -33
  66. data/lib/gruff/version.rb +3 -1
  67. metadata +80 -102
  68. data/Manifest.txt +0 -81
  69. data/RELEASE.md +0 -30
  70. data/assets/bubble.png +0 -0
  71. data/assets/city_scene/background/0000.png +0 -0
  72. data/assets/city_scene/background/0600.png +0 -0
  73. data/assets/city_scene/background/2000.png +0 -0
  74. data/assets/city_scene/clouds/cloudy.png +0 -0
  75. data/assets/city_scene/clouds/partly_cloudy.png +0 -0
  76. data/assets/city_scene/clouds/stormy.png +0 -0
  77. data/assets/city_scene/grass/default.png +0 -0
  78. data/assets/city_scene/haze/true.png +0 -0
  79. data/assets/city_scene/number_sample/1.png +0 -0
  80. data/assets/city_scene/number_sample/2.png +0 -0
  81. data/assets/city_scene/number_sample/default.png +0 -0
  82. data/assets/city_scene/sky/0000.png +0 -0
  83. data/assets/city_scene/sky/0200.png +0 -0
  84. data/assets/city_scene/sky/0400.png +0 -0
  85. data/assets/city_scene/sky/0600.png +0 -0
  86. data/assets/city_scene/sky/0800.png +0 -0
  87. data/assets/city_scene/sky/1000.png +0 -0
  88. data/assets/city_scene/sky/1200.png +0 -0
  89. data/assets/city_scene/sky/1400.png +0 -0
  90. data/assets/city_scene/sky/1500.png +0 -0
  91. data/assets/city_scene/sky/1700.png +0 -0
  92. data/assets/city_scene/sky/2000.png +0 -0
  93. data/assets/pc306715.jpg +0 -0
  94. data/lib/gruff/bar_conversion.rb +0 -46
  95. data/lib/gruff/deprecated.rb +0 -39
  96. data/lib/gruff/stacked_mixin.rb +0 -23
  97. data/test/gruff_test_case.rb +0 -154
  98. data/test/image_compare.rb +0 -58
  99. data/test/test_accumulator_bar.rb +0 -51
  100. data/test/test_area.rb +0 -134
  101. data/test/test_bar.rb +0 -505
  102. data/test/test_base.rb +0 -8
  103. data/test/test_bezier.rb +0 -33
  104. data/test/test_bullet.rb +0 -26
  105. data/test/test_dot.rb +0 -263
  106. data/test/test_labels_for_null_data.rb +0 -27
  107. data/test/test_legend.rb +0 -68
  108. data/test/test_line.rb +0 -657
  109. data/test/test_mini_bar.rb +0 -33
  110. data/test/test_mini_pie.rb +0 -25
  111. data/test/test_mini_side_bar.rb +0 -36
  112. data/test/test_net.rb +0 -231
  113. data/test/test_photo.rb +0 -41
  114. data/test/test_pie.rb +0 -161
  115. data/test/test_scatter.rb +0 -233
  116. data/test/test_scene.rb +0 -100
  117. data/test/test_side_bar.rb +0 -56
  118. data/test/test_sidestacked_bar.rb +0 -105
  119. data/test/test_spider.rb +0 -226
  120. data/test/test_stacked_area.rb +0 -52
  121. data/test/test_stacked_bar.rb +0 -68
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magick
4
+ class Draw
5
+ # Additional method to scale annotation text since Draw.scale doesn't.
6
+ def annotate_scaled(img, width, height, x, y, text, scale)
7
+ scaled_width = (width * scale) >= 1 ? (width * scale) : 1
8
+ scaled_height = (height * scale) >= 1 ? (height * scale) : 1
9
+
10
+ annotate(img,
11
+ scaled_width, scaled_height,
12
+ x * scale, y * scale,
13
+ text.gsub('%', '%%'))
14
+ end
15
+
16
+ remove_method :stroke_opacity
17
+ def stroke_opacity(_opacity)
18
+ raise '#stroke_opacity method has different behavior between RMagick and RMagick4J. Should not use this method.'
19
+ end
20
+
21
+ if defined? JRUBY_VERSION
22
+ # FIXME(uwe): We should NOT need to implement this method.
23
+ # Remove this method as soon as RMagick4J Issue #16 is fixed.
24
+ # https://github.com/Serabe/RMagick4J/issues/16
25
+ def fill=(fill)
26
+ fill = { white: '#FFFFFF' }[fill.to_sym] || fill
27
+ @draw.fill = Magick4J.ColorDatabase.query_default(fill)
28
+ self
29
+ end
30
+ # EMXIF
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ THOUSAND_SEPARATOR = ','
5
+
6
+ #Taken from http://codesnippets.joyent.com/posts/show/330
7
+ def commify(delimiter = THOUSAND_SEPARATOR)
8
+ gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
9
+ end
10
+ end
@@ -1,36 +1,37 @@
1
- require File.dirname(__FILE__) + '/base'
1
+ # frozen_string_literal: true
2
+
3
+ require 'gruff/base'
2
4
 
3
5
  # EXPERIMENTAL!
4
6
  #
5
7
  # Doesn't work yet.
6
8
  #
7
9
  class Gruff::PhotoBar < Gruff::Base
8
-
9
- # TODO
10
- #
11
- # define base and cap in yml
12
- # allow for image directory to be located elsewhere
13
- # more exact measurements for bar heights (go all the way to the bottom of the graph)
14
- # option to tile images instead of use a single image
15
- # drop base label a few px lower so photo bar graphs can have a base dropping over the lower marker line
16
- #
10
+ # TODO
11
+ #
12
+ # define base and cap in yml
13
+ # allow for image directory to be located elsewhere
14
+ # more exact measurements for bar heights (go all the way to the bottom of the graph)
15
+ # option to tile images instead of use a single image
16
+ # drop base label a few px lower so photo bar graphs can have a base dropping over the lower marker line
17
+ #
17
18
 
18
19
  # The name of a pre-packaged photo-based theme.
19
20
  attr_reader :theme
20
21
 
21
- # def initialize(target_width=800)
22
- # super
23
- # init_photo_bar_graphics()
24
- # end
22
+ # def initialize(target_width=800)
23
+ # super
24
+ # init_photo_bar_graphics()
25
+ # end
25
26
 
26
27
  def draw
27
28
  super
28
- return unless @has_data
29
+ return unless data_given?
29
30
 
30
- return # TODO Remove for further development
31
+ return # TODO: Remove for further development
32
+
33
+ init_photo_bar_graphics
31
34
 
32
- init_photo_bar_graphics()
33
-
34
35
  #Draw#define_clip_path()
35
36
  #Draw#clip_path(pathname)
36
37
  #Draw#composite....with bar graph image OverCompositeOp
@@ -38,44 +39,41 @@ class Gruff::PhotoBar < Gruff::Base
38
39
  # See also
39
40
  #
40
41
  # Draw.pattern # define an image to tile as the filling of a draw object
41
- #
42
+ #
42
43
 
43
44
  # Setup spacing.
44
45
  #
45
46
  # Columns sit side-by-side.
46
47
  spacing_factor = 0.9
47
- @bar_width = @norm_data[0][DATA_COLOR_INDEX].columns
48
+ bar_width = store.norm_data[0].color.columns
48
49
 
49
- @norm_data.each_with_index do |data_row, row_index|
50
-
51
- data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
50
+ store.norm_data.each_with_index do |data_row, row_index|
51
+ data_row.points.each_with_index do |data_point, point_index|
52
52
  data_point = 0 if data_point.nil?
53
53
  # Use incremented x and scaled y
54
- left_x = @graph_left + (@bar_width * (row_index + point_index + ((@data.length - 1) * point_index)))
54
+ left_x = @graph_left + (bar_width * (row_index + point_index + ((store.length - 1) * point_index)))
55
55
  left_y = @graph_top + (@graph_height - data_point * @graph_height) + 1
56
- right_x = left_x + @bar_width * spacing_factor
56
+ right_x = left_x + bar_width * spacing_factor
57
57
  right_y = @graph_top + @graph_height - 1
58
-
59
- bar_image_width = data_row[DATA_COLOR_INDEX].columns
58
+
59
+ bar_image_width = data_row.color.columns
60
60
  bar_image_height = right_y.to_f - left_y.to_f
61
-
61
+
62
62
  # Crop to scale for data
63
- bar_image = data_row[DATA_COLOR_INDEX].crop(0, 0, bar_image_width, bar_image_height)
64
-
65
- @d.gravity = NorthWestGravity
66
- @d = @d.composite(left_x, left_y, bar_image_width, bar_image_height, bar_image)
67
-
63
+ bar_image = data_row.color.crop(0, 0, bar_image_width, bar_image_height)
64
+
65
+ @d.gravity = Magick::NorthWestGravity
66
+ @d.composite(left_x, left_y, bar_image_width, bar_image_height, bar_image)
67
+
68
68
  # Calculate center based on bar_width and current row
69
- label_center = @graph_left + (@data.length * @bar_width * point_index) + (@data.length * @bar_width / 2.0)
69
+ label_center = @graph_left + (store.length * bar_width * point_index) + (store.length * bar_width / 2.0)
70
70
  draw_label(label_center, point_index)
71
71
  end
72
-
73
72
  end
74
73
 
75
- @d.draw(@base_image)
74
+ Gruff::Renderer.finish
76
75
  end
77
76
 
78
-
79
77
  # Return the chosen theme or the default
80
78
  def theme
81
79
  @theme || 'plastik'
@@ -85,16 +83,15 @@ protected
85
83
 
86
84
  # Sets up colors with a list of images that will be used.
87
85
  # Images should be 340px tall
88
- def init_photo_bar_graphics
89
- color_list = Array.new
86
+ def init_photo_bar_graphics
87
+ color_list = []
90
88
  theme_dir = File.dirname(__FILE__) + '/../../assets/' + theme
91
89
 
92
90
  Dir.open(theme_dir).each do |file|
93
91
  next unless /\.png$/.match(file)
94
- color_list << Image.read("#{theme_dir}/#{file}").first
92
+
93
+ color_list << Magick::Image.read("#{theme_dir}/#{file}").first
95
94
  end
96
95
  @colors = color_list
97
96
  end
98
-
99
97
  end
100
-
@@ -1,31 +1,40 @@
1
- require File.dirname(__FILE__) + '/base'
1
+ # frozen_string_literal: true
2
2
 
3
- ##
4
- # Here's how to make a Pie graph:
3
+ require 'gruff/base'
4
+
5
+ #
6
+ # Here's how to make a Gruff::Pie.
5
7
  #
6
8
  # g = Gruff::Pie.new
7
9
  # g.title = "Visual Pie Graph Test"
8
10
  # g.data 'Fries', 20
9
11
  # g.data 'Hamburgers', 50
10
- # g.write("test/output/pie_keynote.png")
12
+ # g.write("pie_keynote.png")
13
+ #
14
+ # To control where the pie chart starts creating slices, use {#zero_degree=}.
11
15
  #
12
- # To control where the pie chart starts creating slices, use #zero_degree.
13
-
14
16
  class Gruff::Pie < Gruff::Base
15
-
16
17
  DEFAULT_TEXT_OFFSET_PERCENTAGE = 0.15
17
18
 
18
19
  # Can be used to make the pie start cutting slices at the top (-90.0)
19
- # or at another angle. Default is 0.0, which starts at 3 o'clock.
20
- attr_accessor :zero_degree
20
+ # or at another angle. Default is +0.0+, which starts at 3 o'clock.
21
+ attr_writer :zero_degree
22
+
21
23
  # Do not show labels for slices that are less than this percent. Use 0 to always show all labels.
22
- # Defaults to 0
23
- attr_accessor :hide_labels_less_than
24
- # Affect the distance between the percentages and the pie chart
25
- # Defaults to 0.15
26
- attr_accessor :text_offset_percentage
27
- ## Use values instead of percentages
28
- attr_accessor :show_values_as_labels
24
+ # Defaults to +0+.
25
+ attr_writer :hide_labels_less_than
26
+
27
+ # Affect the distance between the percentages and the pie chart.
28
+ # Defaults to +0.15+.
29
+ attr_writer :text_offset_percentage
30
+
31
+ ## Use values instead of percentages.
32
+ attr_writer :show_values_as_labels
33
+
34
+ def initialize_store
35
+ @store = Gruff::Store.new(Gruff::Store::CustomData)
36
+ end
37
+ private :initialize_store
29
38
 
30
39
  def initialize_ivars
31
40
  super
@@ -34,90 +43,172 @@ class Gruff::Pie < Gruff::Base
34
43
  @text_offset_percentage = DEFAULT_TEXT_OFFSET_PERCENTAGE
35
44
  @show_values_as_labels = false
36
45
  end
46
+ private :initialize_ivars
47
+
48
+ def options
49
+ {
50
+ zero_degree: @zero_degree,
51
+ hide_labels_less_than: @hide_labels_less_than,
52
+ text_offset_percentage: @text_offset_percentage,
53
+ show_values_as_labels: @show_values_as_labels
54
+ }
55
+ end
37
56
 
38
57
  def draw
39
- @hide_line_markers = true
40
-
58
+ hide_line_markers
59
+
41
60
  super
42
61
 
43
- return unless @has_data
44
-
45
- diameter = @graph_height
46
- radius = ([@graph_width, @graph_height].min / 2.0) * 0.8
47
- center_x = @graph_left + (@graph_width / 2.0)
48
- center_y = @graph_top + (@graph_height / 2.0) - 10 # Move graph up a bit
49
- total_sum = sums_for_pie()
50
- prev_degrees = @zero_degree
51
-
52
- # Use full data since we can easily calculate percentages
53
- data = (@sort ? @data.sort{ |a, b| a[DATA_VALUES_INDEX].first <=> b[DATA_VALUES_INDEX].first } : @data)
54
- data.each do |data_row|
55
- if data_row[DATA_VALUES_INDEX].first > 0
56
- @d = @d.stroke data_row[DATA_COLOR_INDEX]
57
- @d = @d.fill 'transparent'
58
- @d.stroke_width(radius) # stroke width should be equal to radius. we'll draw centered on (radius / 2)
59
-
60
- current_degrees = (data_row[DATA_VALUES_INDEX].first / total_sum) * 360.0
61
-
62
- # ellipse will draw the the stroke centered on the first two parameters offset by the second two.
63
- # therefore, in order to draw a circle of the proper diameter we must center the stroke at
64
- # half the radius for both x and y
65
- @d = @d.ellipse(center_x, center_y,
66
- radius / 2.0, radius / 2.0,
67
- prev_degrees, prev_degrees + current_degrees + 0.5) # <= +0.5 'fudge factor' gets rid of the ugly gaps
68
-
69
- half_angle = prev_degrees + ((prev_degrees + current_degrees) - prev_degrees) / 2
70
-
71
- label_val = ((data_row[DATA_VALUES_INDEX].first / total_sum) * 100.0).round
72
- unless label_val < @hide_labels_less_than
73
- # RMagick must use sprintf with the string and % has special significance.
74
- label_string = @show_values_as_labels ? data_row[DATA_VALUES_INDEX].first.to_s : label_val.to_s + '%'
75
- @d = draw_label(center_x,center_y, half_angle,
76
- radius + (radius * @text_offset_percentage),
77
- label_string)
78
- end
79
-
80
- prev_degrees += current_degrees
62
+ return unless data_given?
63
+
64
+ slices.each do |slice|
65
+ if slice.value > 0
66
+ Gruff::Renderer::Ellipse.new(color: slice.color, width: radius)
67
+ .render(center_x, center_y, radius / 2.0, radius / 2.0, chart_degrees, chart_degrees + slice.degrees + 0.5)
68
+ process_label_for slice
69
+ update_chart_degrees_with slice.degrees
81
70
  end
82
71
  end
83
72
 
84
- # TODO debug a circle where the text is drawn...
85
-
86
- @d.draw(@base_image)
73
+ Gruff::Renderer.finish
87
74
  end
88
75
 
89
76
  private
90
77
 
91
- ##
92
- # Labels are drawn around a slightly wider ellipse to give room for
93
- # labels on the left and right.
94
- def draw_label(center_x, center_y, angle, radius, amount)
95
- # TODO Don't use so many hard-coded numbers
96
- r_offset = 20.0 # The distance out from the center of the pie to get point
97
- x_offset = center_x # + 15.0 # The label points need to be tweaked slightly
98
- y_offset = center_y # This one doesn't though
99
- radius_offset = (radius + r_offset)
100
- ellipse_factor = radius_offset * @text_offset_percentage
101
- x = x_offset + ((radius_offset + ellipse_factor) * Math.cos(deg2rad(angle)))
102
- y = y_offset + (radius_offset * Math.sin(deg2rad(angle)))
103
-
104
- # Draw label
105
- @d.fill = @font_color
106
- @d.font = @font if @font
107
- @d.pointsize = scale_fontsize(@marker_font_size)
108
- @d.stroke = 'transparent'
109
- @d.font_weight = BoldWeight
110
- @d.gravity = CenterGravity
111
- @d.annotate_scaled( @base_image,
112
- 0, 0,
113
- x, y,
114
- amount, @scale)
115
- end
116
-
117
- def sums_for_pie
118
- total_sum = 0.0
119
- @data.collect {|data_row| total_sum += data_row[DATA_VALUES_INDEX].first }
120
- total_sum
78
+ def slices
79
+ @slices ||= begin
80
+ slices = store.data.map { |data| slice_class.new(data, options) }
81
+
82
+ slices.sort_by(&:value) if @sort
83
+
84
+ total = slices.map(&:value).inject(:+).to_f
85
+ slices.each { |slice| slice.total = total }
86
+ end
87
+ end
88
+
89
+ # General Helper Methods
90
+
91
+ def hide_line_markers
92
+ @hide_line_markers = true
93
+ end
94
+
95
+ def update_chart_degrees_with(degrees)
96
+ @chart_degrees = chart_degrees + degrees
97
+ end
98
+
99
+ def slice_class
100
+ PieSlice
101
+ end
102
+
103
+ # Spatial Value-Related Methods
104
+
105
+ def chart_degrees
106
+ @chart_degrees ||= @zero_degree
107
+ end
108
+
109
+ attr_reader :graph_height
110
+
111
+ attr_reader :graph_width
112
+
113
+ def diameter
114
+ graph_height
115
+ end
116
+
117
+ def half_width
118
+ graph_width / 2.0
119
+ end
120
+
121
+ def half_height
122
+ graph_height / 2.0
123
+ end
124
+
125
+ def radius
126
+ @radius ||= ([graph_width, graph_height].min / 2.0) * 0.8
127
+ end
128
+
129
+ def center_x
130
+ @center_x ||= @graph_left + half_width
131
+ end
132
+
133
+ def center_y
134
+ @center_y ||= @graph_top + half_height - 10
135
+ end
136
+
137
+ def distance_from_center
138
+ 20.0
139
+ end
140
+
141
+ def radius_offset
142
+ radius + (radius * @text_offset_percentage) + distance_from_center
143
+ end
144
+
145
+ def ellipse_factor
146
+ radius_offset * @text_offset_percentage
147
+ end
148
+
149
+ # Label-Related Methods
150
+
151
+ def process_label_for(slice)
152
+ if slice.percentage >= @hide_labels_less_than
153
+ x, y = label_coordinates_for slice
154
+
155
+ draw_label(x, y, slice.label)
156
+ end
157
+ end
158
+
159
+ def label_coordinates_for(slice)
160
+ angle = chart_degrees + slice.degrees / 2
161
+
162
+ [x_label_coordinate(angle), y_label_coordinate(angle)]
121
163
  end
122
164
 
165
+ def x_label_coordinate(angle)
166
+ center_x + ((radius_offset + ellipse_factor) * Math.cos(deg2rad(angle)))
167
+ end
168
+
169
+ def y_label_coordinate(angle)
170
+ center_y + (radius_offset * Math.sin(deg2rad(angle)))
171
+ end
172
+
173
+ # Drawing-Related Methods
174
+
175
+ def draw_label(x, y, value)
176
+ text_renderer = Gruff::Renderer::Text.new(value, font: @font, size: @marker_font_size, color: @font_color, weight: Magick::BoldWeight)
177
+ text_renderer.add_to_render_queue(0, 0, x, y, Magick::CenterGravity)
178
+ end
179
+
180
+ # Helper Classes
181
+ #
182
+ # @private
183
+ class PieSlice < Struct.new(:data_array, :options)
184
+ attr_accessor :total
185
+
186
+ def name
187
+ data_array[0]
188
+ end
189
+
190
+ def value
191
+ data_array[1].first
192
+ end
193
+
194
+ def color
195
+ data_array[2]
196
+ end
197
+
198
+ def size
199
+ @size ||= value / total
200
+ end
201
+
202
+ def percentage
203
+ @percentage ||= (size * 100.0).round
204
+ end
205
+
206
+ def degrees
207
+ @degrees ||= size * 360.0
208
+ end
209
+
210
+ def label
211
+ options[:show_values_as_labels] ? value.to_s : "#{percentage}%"
212
+ end
213
+ end
123
214
  end