unicode_plot 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/unicode_plot.rb +2 -0
- data/lib/unicode_plot/boxplot.rb +171 -4
- data/lib/unicode_plot/lineplot.rb +6 -62
- data/lib/unicode_plot/renderer.rb +12 -0
- data/lib/unicode_plot/utils.rb +61 -0
- data/lib/unicode_plot/version.rb +1 -1
- data/test/test-boxplot.rb +38 -3
- data/unicode_plot.gemspec +3 -1
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30cc04427f90664c0157ae18002b8e241cb54d232b33f66edc72b0e6b2dac3d7
|
4
|
+
data.tar.gz: 05c0bfc5b3d2c910bb39f655fb1b10f44c76a552b6e87ede46b4b3f3d04055ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6111ed2d7cc47821286ff5da5a33660c24298a04eaeb56377717aa548b9ba150a4c2b67e0ccf62b4aa36c577413babf0bf7fdc50fd37b6945142628ad0d9ed5a
|
7
|
+
data.tar.gz: 0d11730310f093b679a71ca4bb00b760d10e127030cbe797cbf7a171094e192908a3bb3cf7d9de2ba83527ccd8b60ce8f5dbb1956870741aa4a4f55b5c45ac95
|
data/README.md
CHANGED
data/lib/unicode_plot.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'unicode_plot/version'
|
2
2
|
|
3
|
+
require 'unicode_plot/utils'
|
3
4
|
require 'unicode_plot/styled_printer'
|
4
5
|
require 'unicode_plot/value_transformer'
|
5
6
|
require 'unicode_plot/renderer'
|
@@ -11,4 +12,5 @@ require 'unicode_plot/braille_canvas'
|
|
11
12
|
require 'unicode_plot/plot'
|
12
13
|
|
13
14
|
require 'unicode_plot/barplot'
|
15
|
+
require 'unicode_plot/boxplot'
|
14
16
|
require 'unicode_plot/lineplot'
|
data/lib/unicode_plot/boxplot.rb
CHANGED
@@ -1,6 +1,100 @@
|
|
1
|
+
require 'enumerable/statistics'
|
2
|
+
|
1
3
|
module UnicodePlot
|
2
4
|
class Boxplot < Plot
|
3
|
-
|
5
|
+
MIN_WIDTH = 10
|
6
|
+
DEFAULT_COLOR = :green
|
7
|
+
DEFAULT_WIDTH = 40
|
8
|
+
|
9
|
+
def initialize(data, width, color, min_x, max_x, **kw)
|
10
|
+
if min_x == max_x
|
11
|
+
min_x -= 1
|
12
|
+
max_x += 1
|
13
|
+
end
|
14
|
+
width = [width, MIN_WIDTH].max
|
15
|
+
@data = [data.percentile([0, 25, 50, 75, 100])]
|
16
|
+
@color = color
|
17
|
+
@width = [width, MIN_WIDTH].max
|
18
|
+
@min_x = min_x
|
19
|
+
@max_x = max_x
|
20
|
+
super(**kw)
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :min_x, :max_x
|
24
|
+
|
25
|
+
def n_data
|
26
|
+
@data.length
|
27
|
+
end
|
28
|
+
|
29
|
+
def n_rows
|
30
|
+
3 * @data.length
|
31
|
+
end
|
32
|
+
|
33
|
+
def n_columns
|
34
|
+
@width
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_series!(data)
|
38
|
+
mi, ma = data.minmax
|
39
|
+
@data << data.percentile([0, 25, 50, 75, 100])
|
40
|
+
@min_x = [mi, @min_x].min
|
41
|
+
@max_x = [ma, @max_x].max
|
42
|
+
end
|
43
|
+
|
44
|
+
def print_row(out, row_index)
|
45
|
+
check_row_index(row_index)
|
46
|
+
series = @data[(row_index / 3.0).to_i]
|
47
|
+
|
48
|
+
series_row = row_index % 3
|
49
|
+
|
50
|
+
min_char = ['╷', '├' , '╵'][series_row]
|
51
|
+
line_char = [' ', '─' , ' '][series_row]
|
52
|
+
left_box_char = ['┌', '┤' , '└'][series_row]
|
53
|
+
line_box_char = ['─', ' ' , '─'][series_row]
|
54
|
+
median_char = ['┬', '│' , '┴'][series_row]
|
55
|
+
right_box_char = ['┐', '├' , '┘'][series_row]
|
56
|
+
max_char = ['╷', '┤' , '╵'][series_row]
|
57
|
+
|
58
|
+
line = (0 ... @width).map { ' ' }
|
59
|
+
|
60
|
+
# Draw shapes first - this is most important,
|
61
|
+
# so they'll always be drawn even if there's not enough space
|
62
|
+
|
63
|
+
transformed = transform(series)
|
64
|
+
line[transformed[0] - 1] = min_char
|
65
|
+
line[transformed[1] - 1] = left_box_char
|
66
|
+
line[transformed[2] - 1] = median_char
|
67
|
+
line[transformed[3] - 1] = right_box_char
|
68
|
+
line[transformed[4] - 1] = max_char
|
69
|
+
|
70
|
+
(transformed[0] ... (transformed[1] - 1)).each do |i|
|
71
|
+
line[i] = line_char
|
72
|
+
end
|
73
|
+
(transformed[1] ... (transformed[2] - 1)).each do |i|
|
74
|
+
line[i] = line_box_char
|
75
|
+
end
|
76
|
+
(transformed[2] ... (transformed[3] - 1)).each do |i|
|
77
|
+
line[i] = line_box_char
|
78
|
+
end
|
79
|
+
(transformed[3] ... (transformed[4] - 1)).each do |i|
|
80
|
+
line[i] = line_char
|
81
|
+
end
|
82
|
+
|
83
|
+
print_styled(out, line.join(''), color: @color)
|
84
|
+
end
|
85
|
+
|
86
|
+
private def transform(values)
|
87
|
+
values.map do |val|
|
88
|
+
val = (val - @min_x).fdiv(@max_x - @min_x) * @width
|
89
|
+
val.round(half: :even).clamp(1, @width).to_i
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private def check_row_index(row_index)
|
94
|
+
unless 0 <= row_index && row_index < n_rows
|
95
|
+
raise ArgumentError, "row_index out of bounds"
|
96
|
+
end
|
97
|
+
end
|
4
98
|
end
|
5
99
|
|
6
100
|
module_function def boxplot(*args,
|
@@ -15,14 +109,87 @@ module UnicodePlot
|
|
15
109
|
data = Hash(data)
|
16
110
|
text = data.keys
|
17
111
|
data = data.values
|
112
|
+
when 1
|
113
|
+
data = args[0]
|
18
114
|
when 2
|
19
|
-
text, data = *args
|
20
115
|
text = Array(args[0])
|
21
|
-
data =
|
116
|
+
data = args[1]
|
22
117
|
else
|
23
118
|
raise ArgumentError, "wrong number of arguments"
|
24
119
|
end
|
25
120
|
|
26
|
-
|
121
|
+
case data[0]
|
122
|
+
when Numeric
|
123
|
+
data = [data]
|
124
|
+
when Array
|
125
|
+
# do nothing
|
126
|
+
else
|
127
|
+
data = data.to_ary
|
128
|
+
end
|
129
|
+
text ||= Array.new(data.length, "")
|
130
|
+
|
131
|
+
unless text.length == data.length
|
132
|
+
raise ArgumentError, "wrong number of text"
|
133
|
+
end
|
134
|
+
|
135
|
+
unless xlim.length == 2
|
136
|
+
raise ArgumentError, "xlim must be a length 2 array"
|
137
|
+
end
|
138
|
+
|
139
|
+
min_x, max_x = Utils.extend_limits(data.map(&:minmax).flatten, xlim)
|
140
|
+
width = [width, Boxplot::MIN_WIDTH].max
|
141
|
+
|
142
|
+
plot = Boxplot.new(data[0], width, color, min_x, max_x,
|
143
|
+
border: border, **kw)
|
144
|
+
(1 ... data.length).each do |i|
|
145
|
+
plot.add_series!(data[i])
|
146
|
+
end
|
147
|
+
|
148
|
+
mean_x = (min_x + max_x) / 2.0
|
149
|
+
min_x_str = (Utils.roundable?(min_x) ? min_x.round : min_x).to_s
|
150
|
+
mean_x_str = (Utils.roundable?(mean_x) ? mean_x.round : mean_x).to_s
|
151
|
+
max_x_str = (Utils.roundable?(max_x) ? max_x.round : max_x).to_s
|
152
|
+
plot.annotate!(:bl, min_x_str, color: :light_black)
|
153
|
+
plot.annotate!(:b, mean_x_str, color: :light_black)
|
154
|
+
plot.annotate!(:br, max_x_str, color: :light_black)
|
155
|
+
|
156
|
+
text.each_with_index do |name, i|
|
157
|
+
plot.annotate_row!(:l, i*3+1, name) if name.length > 0
|
158
|
+
end
|
159
|
+
|
160
|
+
plot
|
161
|
+
end
|
162
|
+
|
163
|
+
module_function def boxplot!(plot, *args, **kw)
|
164
|
+
case args.length
|
165
|
+
when 1
|
166
|
+
data = args[0]
|
167
|
+
name = kw[:name] || ""
|
168
|
+
when 2
|
169
|
+
name = args[0]
|
170
|
+
data = args[1]
|
171
|
+
else
|
172
|
+
raise ArgumentError, "worng number of arguments"
|
173
|
+
end
|
174
|
+
|
175
|
+
if data.empty?
|
176
|
+
raise ArgumentError, "Can't append empty array to boxplot"
|
177
|
+
end
|
178
|
+
|
179
|
+
plot.add_series!(data)
|
180
|
+
|
181
|
+
plot.annotate_row!(:l, (plot.n_data - 1)*3+1, name) if name && name != ""
|
182
|
+
|
183
|
+
min_x = plot.min_x
|
184
|
+
max_x = plot.max_x
|
185
|
+
mean_x = (min_x + max_x) / 2.0
|
186
|
+
min_x_str = (Utils.roundable?(min_x) ? min_x.round : min_x).to_s
|
187
|
+
mean_x_str = (Utils.roundable?(mean_x) ? mean_x.round : mean_x).to_s
|
188
|
+
max_x_str = (Utils.roundable?(max_x) ? max_x.round : max_x).to_s
|
189
|
+
plot.annotate!(:bl, min_x_str, color: :light_black)
|
190
|
+
plot.annotate!(:b, mean_x_str, color: :light_black)
|
191
|
+
plot.annotate!(:br, max_x_str, color: :light_black)
|
192
|
+
|
193
|
+
plot
|
27
194
|
end
|
28
195
|
end
|
@@ -19,8 +19,8 @@ module UnicodePlot
|
|
19
19
|
end
|
20
20
|
width = [width, MIN_WIDTH].max
|
21
21
|
height = [height, MIN_HEIGHT].max
|
22
|
-
min_x, max_x = extend_limits(x, xlim)
|
23
|
-
min_y, max_y = extend_limits(y, ylim)
|
22
|
+
min_x, max_x = Utils.extend_limits(x, xlim)
|
23
|
+
min_y, max_y = Utils.extend_limits(y, ylim)
|
24
24
|
origin_x = min_x
|
25
25
|
origin_y = min_y
|
26
26
|
plot_width = max_x - origin_x
|
@@ -32,10 +32,10 @@ module UnicodePlot
|
|
32
32
|
plot_height: plot_height)
|
33
33
|
super(**kw)
|
34
34
|
|
35
|
-
min_x_str = (roundable?(min_x) ? min_x.round : min_x).to_s
|
36
|
-
max_x_str = (roundable?(max_x) ? max_x.round : max_x).to_s
|
37
|
-
min_y_str = (roundable?(min_y) ? min_y.round : min_y).to_s
|
38
|
-
max_y_str = (roundable?(max_y) ? max_y.round : max_y).to_s
|
35
|
+
min_x_str = (Utils.roundable?(min_x) ? min_x.round : min_x).to_s
|
36
|
+
max_x_str = (Utils.roundable?(max_x) ? max_x.round : max_x).to_s
|
37
|
+
min_y_str = (Utils.roundable?(min_y) ? min_y.round : min_y).to_s
|
38
|
+
max_y_str = (Utils.roundable?(max_y) ? max_y.round : max_y).to_s
|
39
39
|
|
40
40
|
annotate_row!(:l, 0, max_y_str, color: :light_black)
|
41
41
|
annotate_row!(:l, height-1, min_y_str, color: :light_black)
|
@@ -93,62 +93,6 @@ module UnicodePlot
|
|
93
93
|
def print_row(out, row_index)
|
94
94
|
@canvas.print_row(out, row_index)
|
95
95
|
end
|
96
|
-
|
97
|
-
def extend_limits(values, limits)
|
98
|
-
mi, ma = limits.minmax.map(&:to_f)
|
99
|
-
if mi == 0 && ma == 0
|
100
|
-
mi, ma = values.minmax.map(&:to_f)
|
101
|
-
end
|
102
|
-
diff = ma - mi
|
103
|
-
if diff == 0
|
104
|
-
ma = mi + 1
|
105
|
-
mi = mi - 1
|
106
|
-
end
|
107
|
-
if limits == [0, 0]
|
108
|
-
plotting_range_narrow(mi, ma)
|
109
|
-
else
|
110
|
-
[mi, ma]
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def plotting_range_narrow(xmin, xmax)
|
115
|
-
diff = xmax - xmin
|
116
|
-
xmax = round_up_subtick(xmax, diff)
|
117
|
-
xmin = round_down_subtick(xmin, diff)
|
118
|
-
[xmin.to_f, xmax.to_f]
|
119
|
-
end
|
120
|
-
|
121
|
-
def round_up_subtick(x, m)
|
122
|
-
if x == 0
|
123
|
-
0.0
|
124
|
-
elsif x > 0
|
125
|
-
x.ceil(ceil_neg_log10(m) + 1)
|
126
|
-
else
|
127
|
-
-(-x).floor(ceil_neg_log10(m) + 1)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def round_down_subtick(x, m)
|
132
|
-
if x == 0
|
133
|
-
0.0
|
134
|
-
elsif x > 0
|
135
|
-
x.floor(ceil_neg_log10(m) + 1)
|
136
|
-
else
|
137
|
-
-(-x).ceil(ceil_neg_log10(m) + 1)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def ceil_neg_log10(x)
|
142
|
-
if roundable?(-Math.log10(x))
|
143
|
-
(-Math.log10(x)).ceil
|
144
|
-
else
|
145
|
-
(-Math.log10(x)).floor
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def roundable?(x)
|
150
|
-
x.to_i == x
|
151
|
-
end
|
152
96
|
end
|
153
97
|
|
154
98
|
class Lineplot < GridCanvas
|
@@ -11,6 +11,17 @@ module UnicodePlot
|
|
11
11
|
r: "│"
|
12
12
|
}.freeze
|
13
13
|
|
14
|
+
BORDER_CORNERS = {
|
15
|
+
tl: "┌",
|
16
|
+
tr: "┐",
|
17
|
+
bl: "└",
|
18
|
+
br: "┘",
|
19
|
+
t: " ",
|
20
|
+
l: " ",
|
21
|
+
b: " ",
|
22
|
+
r: " ",
|
23
|
+
}.freeze
|
24
|
+
|
14
25
|
BORDER_BARPLOT = {
|
15
26
|
tl: "┌",
|
16
27
|
tr: "┐",
|
@@ -25,6 +36,7 @@ module UnicodePlot
|
|
25
36
|
|
26
37
|
BORDER_MAP = {
|
27
38
|
solid: BorderMaps::BORDER_SOLID,
|
39
|
+
corners: BorderMaps::BORDER_CORNERS,
|
28
40
|
barplot: BorderMaps::BORDER_BARPLOT,
|
29
41
|
}.freeze
|
30
42
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module UnicodePlot
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def extend_limits(values, limits)
|
6
|
+
mi, ma = limits.minmax.map(&:to_f)
|
7
|
+
if mi == 0 && ma == 0
|
8
|
+
mi, ma = values.minmax.map(&:to_f)
|
9
|
+
end
|
10
|
+
diff = ma - mi
|
11
|
+
if diff == 0
|
12
|
+
ma = mi + 1
|
13
|
+
mi = mi - 1
|
14
|
+
end
|
15
|
+
if limits == [0, 0]
|
16
|
+
plotting_range_narrow(mi, ma)
|
17
|
+
else
|
18
|
+
[mi, ma]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def plotting_range_narrow(xmin, xmax)
|
23
|
+
diff = xmax - xmin
|
24
|
+
xmax = round_up_subtick(xmax, diff)
|
25
|
+
xmin = round_down_subtick(xmin, diff)
|
26
|
+
[xmin.to_f, xmax.to_f]
|
27
|
+
end
|
28
|
+
|
29
|
+
def round_up_subtick(x, m)
|
30
|
+
if x == 0
|
31
|
+
0.0
|
32
|
+
elsif x > 0
|
33
|
+
x.ceil(ceil_neg_log10(m) + 1)
|
34
|
+
else
|
35
|
+
-(-x).floor(ceil_neg_log10(m) + 1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def round_down_subtick(x, m)
|
40
|
+
if x == 0
|
41
|
+
0.0
|
42
|
+
elsif x > 0
|
43
|
+
x.floor(ceil_neg_log10(m) + 1)
|
44
|
+
else
|
45
|
+
-(-x).ceil(ceil_neg_log10(m) + 1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def ceil_neg_log10(x)
|
50
|
+
if roundable?(-Math.log10(x))
|
51
|
+
(-Math.log10(x)).ceil
|
52
|
+
else
|
53
|
+
(-Math.log10(x)).floor
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def roundable?(x)
|
58
|
+
x.to_i == x
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/unicode_plot/version.rb
CHANGED
data/test/test-boxplot.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
__END__
|
2
1
|
class BoxplotTest < Test::Unit::TestCase
|
3
2
|
include Helper::Fixture
|
4
3
|
include Helper::WithTerm
|
@@ -8,7 +7,7 @@ class BoxplotTest < Test::Unit::TestCase
|
|
8
7
|
test("without name") do
|
9
8
|
plot = UnicodePlot.boxplot([1, 2, 3, 4, 5])
|
10
9
|
_, output = with_term { plot.render($stdout) }
|
11
|
-
assert_equal(fixture_path("boxplot/
|
10
|
+
assert_equal(fixture_path("boxplot/default.txt").read,
|
12
11
|
output)
|
13
12
|
end
|
14
13
|
|
@@ -29,7 +28,7 @@ class BoxplotTest < Test::Unit::TestCase
|
|
29
28
|
end
|
30
29
|
|
31
30
|
test("print to tty") do
|
32
|
-
_, output = with_term { plot.render($stdout) }
|
31
|
+
_, output = with_term { @plot.render($stdout) }
|
33
32
|
assert_equal(fixture_path("boxplot/default_parameters.txt").read,
|
34
33
|
output)
|
35
34
|
end
|
@@ -44,5 +43,41 @@ class BoxplotTest < Test::Unit::TestCase
|
|
44
43
|
output)
|
45
44
|
end
|
46
45
|
end
|
46
|
+
|
47
|
+
data([5, 6, 10, 20, 40].map.with_index {|max_x, i|
|
48
|
+
["max_x: #{max_x}", [i + 1, max_x]] }.to_h)
|
49
|
+
test("with scaling") do
|
50
|
+
i, max_x = data
|
51
|
+
plot = UnicodePlot.boxplot([1, 2, 3, 4, 5], xlim: [0, max_x])
|
52
|
+
_, output = with_term { plot.render($stdout) }
|
53
|
+
assert_equal(fixture_path("boxplot/scale#{i}.txt").read,
|
54
|
+
output)
|
55
|
+
end
|
56
|
+
|
57
|
+
test("multi-series") do
|
58
|
+
plot = UnicodePlot.boxplot(["one", "two"],
|
59
|
+
[
|
60
|
+
[1, 2, 3, 4, 5],
|
61
|
+
[2, 3, 4, 5, 6, 7, 8, 9]
|
62
|
+
],
|
63
|
+
title: "Multi-series",
|
64
|
+
xlabel: "foo",
|
65
|
+
color: :yellow)
|
66
|
+
_, output = with_term { plot.render($stdout) }
|
67
|
+
assert_equal(fixture_path("boxplot/multi1.txt").read,
|
68
|
+
output)
|
69
|
+
|
70
|
+
assert_same(plot,
|
71
|
+
UnicodePlot.boxplot!(plot, "one more", [-1, 2, 3, 4, 11]))
|
72
|
+
_, output = with_term { plot.render($stdout) }
|
73
|
+
assert_equal(fixture_path("boxplot/multi2.txt").read,
|
74
|
+
output)
|
75
|
+
|
76
|
+
assert_same(plot,
|
77
|
+
UnicodePlot.boxplot!(plot, [4, 2, 2.5, 4, 14], name: "last one"))
|
78
|
+
_, output = with_term { plot.render($stdout) }
|
79
|
+
assert_equal(fixture_path("boxplot/multi3.txt").read,
|
80
|
+
output)
|
81
|
+
end
|
47
82
|
end
|
48
83
|
end
|
data/unicode_plot.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.summary = %q{Plot your data by Unicode characters}
|
18
18
|
spec.description = %q{Plot your data by Unicode characters}
|
19
|
-
spec.homepage = "https://github.com/
|
19
|
+
spec.homepage = "https://github.com/red-data-tools/unicode_plot.rb"
|
20
20
|
spec.license = "MIT"
|
21
21
|
|
22
22
|
spec.files = ["README.md", "Rakefile", "Gemfile", "#{spec.name}.gemspec"]
|
@@ -29,6 +29,8 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
|
30
30
|
spec.require_paths = ["lib"]
|
31
31
|
|
32
|
+
spec.add_runtime_dependency "enumerable-statistics", ">= 2.0.0.pre"
|
33
|
+
|
32
34
|
spec.add_development_dependency "bundler", ">= 1.17"
|
33
35
|
spec.add_development_dependency "rake"
|
34
36
|
spec.add_development_dependency "test-unit"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicode_plot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mrkn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: enumerable-statistics
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0.pre
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.0.pre
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,6 +87,7 @@ files:
|
|
73
87
|
- lib/unicode_plot/plot.rb
|
74
88
|
- lib/unicode_plot/renderer.rb
|
75
89
|
- lib/unicode_plot/styled_printer.rb
|
90
|
+
- lib/unicode_plot/utils.rb
|
76
91
|
- lib/unicode_plot/value_transformer.rb
|
77
92
|
- lib/unicode_plot/version.rb
|
78
93
|
- test/helper.rb
|
@@ -84,7 +99,7 @@ files:
|
|
84
99
|
- test/test-canvas.rb
|
85
100
|
- test/test-lineplot.rb
|
86
101
|
- unicode_plot.gemspec
|
87
|
-
homepage: https://github.com/
|
102
|
+
homepage: https://github.com/red-data-tools/unicode_plot.rb
|
88
103
|
licenses:
|
89
104
|
- MIT
|
90
105
|
metadata: {}
|