gruff 0.14.0-java → 0.17.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +28 -12
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +20 -24
  5. data/CHANGELOG.md +52 -0
  6. data/README.md +10 -3
  7. data/gruff.gemspec +9 -10
  8. data/lib/gruff/accumulator_bar.rb +1 -1
  9. data/lib/gruff/area.rb +6 -4
  10. data/lib/gruff/bar.rb +53 -31
  11. data/lib/gruff/base.rb +292 -184
  12. data/lib/gruff/bezier.rb +4 -2
  13. data/lib/gruff/box_plot.rb +180 -0
  14. data/lib/gruff/bullet.rb +6 -6
  15. data/lib/gruff/candlestick.rb +120 -0
  16. data/lib/gruff/dot.rb +11 -12
  17. data/lib/gruff/font.rb +3 -0
  18. data/lib/gruff/helper/bar_conversion.rb +6 -10
  19. data/lib/gruff/helper/bar_mixin.rb +25 -0
  20. data/lib/gruff/helper/bar_value_label.rb +24 -40
  21. data/lib/gruff/helper/stacked_mixin.rb +19 -1
  22. data/lib/gruff/histogram.rb +9 -5
  23. data/lib/gruff/line.rb +49 -48
  24. data/lib/gruff/mini/legend.rb +11 -11
  25. data/lib/gruff/net.rb +23 -18
  26. data/lib/gruff/patch/rmagick.rb +0 -1
  27. data/lib/gruff/patch/string.rb +1 -0
  28. data/lib/gruff/pie.rb +26 -12
  29. data/lib/gruff/renderer/dash_line.rb +3 -2
  30. data/lib/gruff/renderer/dot.rb +28 -15
  31. data/lib/gruff/renderer/line.rb +1 -3
  32. data/lib/gruff/renderer/rectangle.rb +6 -2
  33. data/lib/gruff/renderer/renderer.rb +4 -8
  34. data/lib/gruff/renderer/text.rb +7 -1
  35. data/lib/gruff/scatter.rb +64 -56
  36. data/lib/gruff/side_bar.rb +64 -30
  37. data/lib/gruff/side_stacked_bar.rb +43 -54
  38. data/lib/gruff/spider.rb +52 -18
  39. data/lib/gruff/stacked_area.rb +18 -8
  40. data/lib/gruff/stacked_bar.rb +59 -29
  41. data/lib/gruff/store/xy_data.rb +2 -0
  42. data/lib/gruff/version.rb +1 -1
  43. data/lib/gruff.rb +67 -58
  44. metadata +17 -16
  45. data/.rubocop_todo.yml +0 -116
  46. data/lib/gruff/scene.rb +0 -200
  47. data/lib/gruff/store/custom_data.rb +0 -36
data/lib/gruff/scene.rb DELETED
@@ -1,200 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'observer'
4
-
5
- # A scene is a non-linear graph that assembles layers together to tell a story.
6
- # Layers are folders with appropriately named files (see below). You can group
7
- # layers and control them together or just set their values individually.
8
- #
9
- # Examples:
10
- #
11
- # * A city scene that changes with the time of day and the weather conditions.
12
- # * A traffic map that shows red lines on streets that are crowded and green on free-flowing ones.
13
- #
14
- # g = Gruff::Scene.new("500x100", "path/to/city_scene_directory")
15
- #
16
- # # Define order of layers, back to front
17
- # g.layers = %w(background haze sky clouds)
18
- #
19
- # # Define groups that will be controlled by the same input
20
- # g.weather_group = %w(clouds)
21
- # g.time_group = %w(background sky)
22
- #
23
- # # Set values for the layers or groups
24
- # g.weather = "cloudy"
25
- # g.time = Time.now
26
- # g.haze = true
27
- #
28
- # # Write the final graph to disk
29
- # g.write "hazy_daytime_city_scene.png"
30
- #
31
- # There are several rules that will magically select a layer when possible.
32
- #
33
- # * Numbered files will be selected according to the closest value that is less than the input value.
34
- # * +'true.png'+ and +'false.png'+ will be used as booleans.
35
- # * Other named files will be used if the input matches the filename (without the filetype extension).
36
- # * If there is a file named +'default.png'+, it will be used unless other input values are set for the corresponding layer.
37
- class Gruff::Scene < Gruff::Base
38
- # An array listing the folder names that will be rendered, from back to front.
39
- #
40
- # @example
41
- # g.layers = %w(sky clouds buildings street people)
42
- attr_reader :layers
43
-
44
- def initialize(target_width, base_dir)
45
- @base_dir = base_dir
46
- @groups = {}
47
- @layers = []
48
- super target_width
49
- end
50
-
51
- def draw
52
- # Join all the custom paths and filter out the empty ones
53
- image_paths = @layers.map(&:path).reject(&:empty?)
54
- images = Magick::ImageList.new(*image_paths)
55
- renderer.background_image = images.flatten_images
56
- end
57
-
58
- def layers=(ordered_list)
59
- ordered_list.each do |layer_name|
60
- @layers << Gruff::Layer.new(@base_dir, layer_name)
61
- end
62
- end
63
-
64
- # Group layers to input values
65
- #
66
- # g.weather_group = ["sky", "sea", "clouds"]
67
- #
68
- # Set input values
69
- #
70
- # g.weather = "cloudy"
71
- #
72
- def method_missing(method_name, *args)
73
- case method_name.to_s
74
- when /^(\w+)_group=$/
75
- add_group Regexp.last_match(1), *args
76
- return
77
- when /^(\w+)=$/
78
- set_input Regexp.last_match(1), args.first
79
- return
80
- end
81
- super
82
- end
83
-
84
- private
85
-
86
- def add_group(input_name, layer_names)
87
- @groups[input_name] = Gruff::Group.new(input_name, @layers.select { |layer| layer_names.include?(layer.name) })
88
- end
89
-
90
- def set_input(input_name, input_value)
91
- if !@groups[input_name].nil?
92
- @groups[input_name].send_updates(input_value)
93
- elsif chosen_layer = @layers.find { |layer| layer.name == input_name }
94
- chosen_layer.update input_value
95
- end
96
- end
97
- end
98
-
99
- # @private
100
- class Gruff::Group
101
- include Observable
102
- attr_reader :name
103
-
104
- def initialize(folder_name, layers)
105
- @name = folder_name
106
- layers.each do |layer|
107
- layer.observe self
108
- end
109
- end
110
-
111
- def send_updates(value)
112
- changed
113
- notify_observers value
114
- end
115
- end
116
-
117
- # @private
118
- class Gruff::Layer
119
- attr_reader :name
120
-
121
- def initialize(base_dir, folder_name)
122
- @base_dir = base_dir.to_s
123
- @name = folder_name.to_s
124
- @filenames = Dir.open(File.join(base_dir, folder_name)).entries.select { |file| file =~ /^[^.]+\.png$/ }.sort
125
- @selected_filename = select_default
126
- end
127
-
128
- # Register this layer so it receives updates from the group
129
- def observe(obj)
130
- obj.add_observer self
131
- end
132
-
133
- # Choose the appropriate filename for this layer, based on the input
134
- def update(value)
135
- @selected_filename = begin
136
- case value.to_s
137
- when /^(true|false)$/
138
- select_boolean value
139
- when /^(\w|\s)+$/
140
- select_string value
141
- when /^-?(\d+\.)?\d+$/
142
- select_numeric value
143
- when /(\d\d):(\d\d):\d\d/
144
- select_time "#{Regexp.last_match(1)}#{Regexp.last_match(2)}"
145
- else
146
- select_default
147
- end
148
- end
149
- # Finally, try to use 'default' if we're still blank
150
- @selected_filename ||= select_default
151
- end
152
-
153
- # Returns the full path to the selected image, or a blank string
154
- def path
155
- unless @selected_filename.nil? || @selected_filename.empty?
156
- return File.join(@base_dir, @name, @selected_filename)
157
- end
158
-
159
- ''
160
- end
161
-
162
- private
163
-
164
- # Match "true.png" or "false.png"
165
- def select_boolean(value)
166
- file_exists_or_blank value.to_s
167
- end
168
-
169
- # Match -5 to _5.png
170
- def select_numeric(value)
171
- file_exists_or_blank value.to_s.gsub('-', '_')
172
- end
173
-
174
- def select_time(value)
175
- times = @filenames.map { |filename| filename.gsub('.png', '') }
176
- times.each_with_index do |time, index|
177
- if (time > value) && (index > 0)
178
- return "#{times[index - 1]}.png"
179
- end
180
- end
181
-
182
- "#{times.last}.png"
183
- end
184
-
185
- # Match "partly cloudy" to "partly_cloudy.png"
186
- def select_string(value)
187
- file_exists_or_blank value.to_s.gsub(' ', '_')
188
- end
189
-
190
- def select_default
191
- @filenames.include?('default.png') ? 'default.png' : ''
192
- end
193
-
194
- # Returns the string "#{filename}.png", if it exists.
195
- #
196
- # Failing that, it returns default.png, or '' if that doesn't exist.
197
- def file_exists_or_blank(filename)
198
- @filenames.include?("#{filename}.png") ? "#{filename}.png" : select_default
199
- end
200
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gruff
4
- class Store
5
- # @private
6
- class CustomData < Struct.new(:label, :points, :color, :custom)
7
- def initialize(label, points, color, custom = nil)
8
- super(label.to_s, Array(points), color, custom)
9
- end
10
-
11
- def empty?
12
- points.empty?
13
- end
14
-
15
- def columns
16
- points.length
17
- end
18
-
19
- def min
20
- points.compact.min
21
- end
22
-
23
- def max
24
- points.compact.max
25
- end
26
-
27
- def normalize(minimum:, spread:)
28
- norm_points = points.map do |point|
29
- point.nil? ? nil : (point.to_f - minimum.to_f) / spread
30
- end
31
-
32
- self.class.new(label, norm_points, color, custom)
33
- end
34
- end
35
- end
36
- end