opal-d3 0.0.20170205
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/README.md +7 -0
- data/Rakefile +31 -0
- data/d3.js +16393 -0
- data/demo/Gemfile +4 -0
- data/demo/README.md +7 -0
- data/demo/app/data/elections_2016.rb +10 -0
- data/demo/app/data/harry_potter.rb +19 -0
- data/demo/app/data/iphones.rb +29 -0
- data/demo/app/data/london_population.rb +26 -0
- data/demo/app/data/man_vs_horse.rb +55 -0
- data/demo/app/data/mtg_modern_colors.rb +96 -0
- data/demo/app/data/mtg_modern_creatures.rb +116 -0
- data/demo/app/data/olympics_2016_medals.rb +100 -0
- data/demo/app/data/paradox.rb +60 -0
- data/demo/app/data/polish_pms.rb +28 -0
- data/demo/app/data/star_trek_voyager.rb +183 -0
- data/demo/app/data/weather_in_london.rb +381 -0
- data/demo/app/elections_2016.rb +19 -0
- data/demo/app/harry_potter.rb +35 -0
- data/demo/app/iphones.rb +47 -0
- data/demo/app/london_population.rb +46 -0
- data/demo/app/london_population_area.rb +42 -0
- data/demo/app/man_vs_horse.rb +53 -0
- data/demo/app/mtg_modern_colors.rb +49 -0
- data/demo/app/mtg_modern_creatures.rb +63 -0
- data/demo/app/olympics_2016_medals.rb +54 -0
- data/demo/app/paradox.rb +57 -0
- data/demo/app/polish_pms.rb +53 -0
- data/demo/app/star_trek_voyager.rb +39 -0
- data/demo/app/weather_in_london.rb +62 -0
- data/demo/assets/d3.js +16393 -0
- data/demo/assets/style.css +0 -0
- data/demo/config.ru +39 -0
- data/demo/views/index.erb +21 -0
- data/demo/views/visualization.erb +29 -0
- data/lib/opal/d3/arc.rb +21 -0
- data/lib/opal/d3/area.rb +49 -0
- data/lib/opal/d3/axis.rb +77 -0
- data/lib/opal/d3/band_scale.rb +29 -0
- data/lib/opal/d3/collections.rb +10 -0
- data/lib/opal/d3/color.rb +78 -0
- data/lib/opal/d3/continuous_scale.rb +64 -0
- data/lib/opal/d3/creator.rb +11 -0
- data/lib/opal/d3/curve.rb +74 -0
- data/lib/opal/d3/dsv.rb +103 -0
- data/lib/opal/d3/ease.rb +319 -0
- data/lib/opal/d3/format.rb +97 -0
- data/lib/opal/d3/histograms.rb +44 -0
- data/lib/opal/d3/interpolate.rb +125 -0
- data/lib/opal/d3/line.rb +29 -0
- data/lib/opal/d3/map.rb +52 -0
- data/lib/opal/d3/misc.rb +15 -0
- data/lib/opal/d3/native.rb +84 -0
- data/lib/opal/d3/nest.rb +100 -0
- data/lib/opal/d3/ordinal_scale.rb +56 -0
- data/lib/opal/d3/path.rb +22 -0
- data/lib/opal/d3/pie.rb +23 -0
- data/lib/opal/d3/point_scale.rb +26 -0
- data/lib/opal/d3/polygon.rb +16 -0
- data/lib/opal/d3/quadtree.rb +95 -0
- data/lib/opal/d3/quantile_scale.rb +21 -0
- data/lib/opal/d3/quantize_scale.rb +23 -0
- data/lib/opal/d3/radial_area.rb +49 -0
- data/lib/opal/d3/radial_line.rb +29 -0
- data/lib/opal/d3/random.rb +12 -0
- data/lib/opal/d3/search.rb +28 -0
- data/lib/opal/d3/selection.rb +149 -0
- data/lib/opal/d3/sequential_scale.rb +96 -0
- data/lib/opal/d3/set.rb +33 -0
- data/lib/opal/d3/stack.rb +11 -0
- data/lib/opal/d3/statistics.rb +81 -0
- data/lib/opal/d3/symbol.rb +70 -0
- data/lib/opal/d3/threshold_scale.rb +23 -0
- data/lib/opal/d3/time_format.rb +48 -0
- data/lib/opal/d3/time_interval.rb +81 -0
- data/lib/opal/d3/transformations.rb +13 -0
- data/lib/opal/d3/version.rb +5 -0
- data/lib/opal/d3.rb +62 -0
- data/lib/opal-d3.rb +9 -0
- data/opal-d3.gemspec +20 -0
- data/spec/arc_spec.rb +86 -0
- data/spec/area_spec.rb +102 -0
- data/spec/axis_spec.rb +174 -0
- data/spec/band_scale_spec.rb +73 -0
- data/spec/color_spec.rb +74 -0
- data/spec/continuous_scale_spec.rb +217 -0
- data/spec/coverage_spec.rb +23 -0
- data/spec/creator_spec.rb +15 -0
- data/spec/curve_spec.rb +214 -0
- data/spec/dsv_spec.rb +194 -0
- data/spec/ease_spec.rb +370 -0
- data/spec/format_spec.rb +87 -0
- data/spec/histograms_spec.rb +61 -0
- data/spec/html/d3.js +16393 -0
- data/spec/html/index.html.erb +12 -0
- data/spec/interpolate_spec.rb +152 -0
- data/spec/line_spec.rb +58 -0
- data/spec/map_spec.rb +80 -0
- data/spec/misc_spec.rb +19 -0
- data/spec/nest_spec.rb +89 -0
- data/spec/objects_spec.rb +22 -0
- data/spec/ordinal_scale_spec.rb +59 -0
- data/spec/path_spec.rb +65 -0
- data/spec/pie_spec.rb +114 -0
- data/spec/point_scale_spec.rb +58 -0
- data/spec/polygon_spec.rb +51 -0
- data/spec/quadtree_spec.rb +128 -0
- data/spec/quantile_scale_spec.rb +24 -0
- data/spec/quantize_scale_spec.rb +40 -0
- data/spec/radial_area_spec.rb +127 -0
- data/spec/radial_line_spec.rb +54 -0
- data/spec/random_spec.rb +34 -0
- data/spec/search_spec.rb +69 -0
- data/spec/selection_data_spec.rb +71 -0
- data/spec/selection_manipulation_spec.rb +179 -0
- data/spec/selection_spec.rb +214 -0
- data/spec/sequential_scale_spec.rb +90 -0
- data/spec/set_spec.rb +57 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/stack_spec.rb +23 -0
- data/spec/statistics_spec.rb +65 -0
- data/spec/symbol_spec.rb +121 -0
- data/spec/threshold_scale_spec.rb +28 -0
- data/spec/time_format_spec.rb +99 -0
- data/spec/time_interval_spec.rb +304 -0
- data/spec/transformations_spec.rb +51 -0
- metadata +258 -0
@@ -0,0 +1,217 @@
|
|
1
|
+
require "time"
|
2
|
+
|
3
|
+
describe "d3 - continuous scale" do
|
4
|
+
describe "linear" do
|
5
|
+
it "d3.scale_linear" do
|
6
|
+
expect(D3.scale_linear).to be_instance_of(D3::ContinuousScale)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "basics" do
|
10
|
+
x = D3.scale_linear.domain([10, 130]).range([0, 960])
|
11
|
+
expect(x.domain).to eq([10, 130])
|
12
|
+
expect(x.range).to eq([0, 960])
|
13
|
+
expect(x.(20)).to eq(80)
|
14
|
+
expect(x.(50)).to eq(320)
|
15
|
+
expect(x.(-10)).to eq(-160)
|
16
|
+
expect(x.invert(-160)).to eq(-10)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "range_round" do
|
20
|
+
x = D3.scale_linear.domain([0,6]).range([0, 100])
|
21
|
+
y = D3.scale_linear.domain([0,6]).range_round([0, 100])
|
22
|
+
expect(x.(4)).to eq(66.66666666666666)
|
23
|
+
expect(y.(4)).to eq(67)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "interpolate" do
|
27
|
+
let(:x) { D3.scale_linear.domain([0,6]).range([0, 100]) }
|
28
|
+
let(:xf) { x.copy.interpolate{|a,b| proc{|t| (a + (b-a)*t).floor }}}
|
29
|
+
let(:xc) { x.copy.interpolate{|a,b| proc{|t| (a + (b-a)*t).ceil }}}
|
30
|
+
let(:xr) { x.copy.interpolate(&D3.interpolate_round) }
|
31
|
+
it "floor" do
|
32
|
+
expect(xf.(4)).to eq(66)
|
33
|
+
end
|
34
|
+
it "ceil" do
|
35
|
+
expect(xc.(4)).to eq(67)
|
36
|
+
end
|
37
|
+
it "round" do
|
38
|
+
expect(xr.(4)).to eq(67)
|
39
|
+
end
|
40
|
+
it "get interpolator" do
|
41
|
+
expect(x.interpolate.(0,10).(0.34)).to eq(3.4000000000000004)
|
42
|
+
expect(xr.interpolate.(0,10).(0.34)).to eq(3)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it ".clamp" do
|
47
|
+
x = D3.scale_linear.domain([10, 130]).range([0, 960])
|
48
|
+
expect(x.clamp).to eq(false)
|
49
|
+
x.clamp(true)
|
50
|
+
expect(x.clamp).to eq(true)
|
51
|
+
expect(x.(-10)).to eq(0)
|
52
|
+
expect(x.invert(-160)).to eq(10)
|
53
|
+
end
|
54
|
+
|
55
|
+
it ".nice / .copy" do
|
56
|
+
x = D3.scale_linear.domain([7, 127]).range([3, 955])
|
57
|
+
xn = x.copy.nice
|
58
|
+
expect(xn.domain).to eq([0, 130])
|
59
|
+
expect(xn.range).to eq([3, 955])
|
60
|
+
|
61
|
+
xc = x.copy
|
62
|
+
x5 = x.nice(5)
|
63
|
+
expect(x5.domain).to eq([0, 140])
|
64
|
+
expect(x5.range).to eq([3, 955])
|
65
|
+
expect(xc.domain).to eq([7, 127])
|
66
|
+
expect(xc.range).to eq([3, 955])
|
67
|
+
expect(x.domain).to eq(x5.domain)
|
68
|
+
expect(x.range).to eq(x5.range)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "color" do
|
72
|
+
color = D3.scale_linear.domain([10, 100]).range(["brown", "steelblue"])
|
73
|
+
expect(color.(20)).to eq("rgb(154, 52, 57)")
|
74
|
+
expect(color.(50)).to eq("rgb(123, 81, 103)")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "color piecewise" do
|
78
|
+
color = D3.scale_linear.domain([-1, 0, 1]).range(["red", "white", "green"])
|
79
|
+
expect(color.(-1)).to eq("rgb(255, 0, 0)")
|
80
|
+
expect(color.(-0.5)).to eq("rgb(255, 128, 128)")
|
81
|
+
expect(color.(0)).to eq("rgb(255, 255, 255)")
|
82
|
+
expect(color.(+0.5)).to eq("rgb(128, 192, 128)")
|
83
|
+
expect(color.(1)).to eq("rgb(0, 128, 0)")
|
84
|
+
end
|
85
|
+
|
86
|
+
it ".ticks / .tick_format" do
|
87
|
+
x = D3.scale_linear.domain([-1, 1]).range([0, 960])
|
88
|
+
expect(x.ticks(5)).to eq([-1, -0.5, 0, 0.5, 1])
|
89
|
+
expect(x.ticks.map{|v| v.round(2)}).to eq([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])
|
90
|
+
tick_format = x.tick_format(5, "+%")
|
91
|
+
expect(x.ticks(5).map(&tick_format)).to eq(["-100%", "-50%", "+0%", "+50%", "+100%"])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "pow" do
|
96
|
+
it "d3.scale_pow" do
|
97
|
+
expect(D3.scale_pow).to be_instance_of(D3::PowScale)
|
98
|
+
expect(D3.scale_pow.exponent).to eq(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "basics" do
|
102
|
+
x = D3.scale_pow.exponent(2).domain([0, 10]).range([0, 10000])
|
103
|
+
expect(x.(5)).to eq(2500)
|
104
|
+
expect(x.invert(4900)).to eq(7)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "sqrt" do
|
109
|
+
it "d3.scale_sqrt" do
|
110
|
+
expect(D3.scale_sqrt).to be_instance_of(D3::PowScale)
|
111
|
+
expect(D3.scale_sqrt.exponent).to eq(0.5)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "log" do
|
116
|
+
it 'd3.scale_log' do
|
117
|
+
expect(D3.scale_log).to be_instance_of(D3::LogScale)
|
118
|
+
expect(D3.scale_log.base).to eq(10)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "basics" do
|
122
|
+
x = D3.scale_log.base(2).domain([1, 1024]).range([0, 100])
|
123
|
+
expect(x.(256)).to eq(80)
|
124
|
+
expect(x.invert(50)).to eq(32)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "identity" do
|
129
|
+
it 'd3.scale_log' do
|
130
|
+
expect(D3.scale_identity).to be_instance_of(D3::ContinuousScale)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "basics" do
|
134
|
+
x = D3.scale_identity.domain([10,20])
|
135
|
+
expect(x.(16)).to eq(16)
|
136
|
+
expect(x.invert(12)).to eq(12)
|
137
|
+
expect(x.domain).to eq([10,20])
|
138
|
+
expect(x.range).to eq([10,20])
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Sadly this can't be tested totally properly due to ridiculous mess
|
143
|
+
# javascript timezone management is
|
144
|
+
describe "time" do
|
145
|
+
let(:x) { D3.scale_time.domain([Time.parse("Jan 01 1990 00:00:00"), Time.parse(Time.parse("Jan 01 1998 00:00:00"))]).range([0,100]) }
|
146
|
+
let(:y) { D3.scale_utc.domain([Time.parse("Jan 01 1990 00:00:00"), Time.parse(Time.parse("Jan 01 1998 00:00:00"))]).range([0,100]) }
|
147
|
+
it "d3.scale_time" do
|
148
|
+
expect(D3.scale_time).to be_instance_of(D3::ContinuousScale)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "d3.scale_utc" do
|
152
|
+
expect(D3.scale_utc).to be_instance_of(D3::ContinuousScale)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "basics" do
|
156
|
+
expect(x.(Time.parse("Jul 01 1995 00:00:00")).round(1)).to eq(68.7)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "invert" do
|
160
|
+
expect(x.invert(75).to_s).to eq("1996-01-01 12:00:00 -0000")
|
161
|
+
end
|
162
|
+
|
163
|
+
it "ticks" do
|
164
|
+
expect(x.ticks(4).map(&:to_s)).to eq([
|
165
|
+
"1990-01-01 00:00:00 -0000",
|
166
|
+
"1992-01-01 00:00:00 -0000",
|
167
|
+
"1994-01-01 00:00:00 -0000",
|
168
|
+
"1996-01-01 00:00:00 -0000",
|
169
|
+
"1998-01-01 00:00:00 -0000",
|
170
|
+
])
|
171
|
+
end
|
172
|
+
|
173
|
+
it "ticks interval" do
|
174
|
+
expect(x.ticks(D3.time_month.every(8)).map{|d| d.to_s.split[0]}).to eq([
|
175
|
+
"1990-01-01",
|
176
|
+
"1990-09-01",
|
177
|
+
"1991-01-01",
|
178
|
+
"1991-09-01",
|
179
|
+
"1992-01-01",
|
180
|
+
"1992-09-01",
|
181
|
+
"1993-01-01",
|
182
|
+
"1993-09-01",
|
183
|
+
"1994-01-01",
|
184
|
+
"1994-09-01",
|
185
|
+
"1995-01-01",
|
186
|
+
"1995-09-01",
|
187
|
+
"1996-01-01",
|
188
|
+
"1996-09-01",
|
189
|
+
"1997-01-01",
|
190
|
+
"1997-09-01",
|
191
|
+
"1998-01-01",
|
192
|
+
])
|
193
|
+
end
|
194
|
+
|
195
|
+
it "utc ticks interval" do
|
196
|
+
expect(y.ticks(D3.utc_month.every(8)).map{|d| d.to_s.split[0]}).to eq([
|
197
|
+
"1990-01-01",
|
198
|
+
"1990-09-01",
|
199
|
+
"1991-01-01",
|
200
|
+
"1991-09-01",
|
201
|
+
"1992-01-01",
|
202
|
+
"1992-09-01",
|
203
|
+
"1993-01-01",
|
204
|
+
"1993-09-01",
|
205
|
+
"1994-01-01",
|
206
|
+
"1994-09-01",
|
207
|
+
"1995-01-01",
|
208
|
+
"1995-09-01",
|
209
|
+
"1996-01-01",
|
210
|
+
"1996-09-01",
|
211
|
+
"1997-01-01",
|
212
|
+
"1997-09-01",
|
213
|
+
"1998-01-01",
|
214
|
+
])
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
describe "D3 coverage" do
|
2
|
+
# Test code is here because opal-repl doesn't support aggregate_failures mode
|
3
|
+
native_methods = `Opal.hash(window.d3)`.keys.sort
|
4
|
+
nice_methods = native_methods.map{|m| m.gsub(/([a-z])(?=[A-Z0-9])/, "\\1_").downcase }
|
5
|
+
|
6
|
+
it "everything is covered" do
|
7
|
+
working_methods = nice_methods.select{|m| D3.respond_to?(m) }
|
8
|
+
expect(working_methods.size).to eq(nice_methods.size)
|
9
|
+
end
|
10
|
+
|
11
|
+
# DETAILED
|
12
|
+
# format conflict with base ruby
|
13
|
+
|
14
|
+
# nice_methods.each do |method|
|
15
|
+
# it method do
|
16
|
+
# if D3.respond_to?(method)
|
17
|
+
# # OK
|
18
|
+
# else
|
19
|
+
# skip "not implemented yet"
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe "d3 - creator" do
|
2
|
+
after(:each) do
|
3
|
+
D3.select("#test-area").html("")
|
4
|
+
end
|
5
|
+
let(:root) { D3.select("#test-area") }
|
6
|
+
let(:html) { root.html }
|
7
|
+
|
8
|
+
it "d3.creator" do
|
9
|
+
expect(D3.creator("div")).to be_instance_of(D3::Creator)
|
10
|
+
D3.select("div").append(D3.creator("span"))
|
11
|
+
expect(html).to eq(
|
12
|
+
"<span></span>"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
data/spec/curve_spec.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
describe "d3 - curve" do
|
2
|
+
let(:curve) { D3.send(name) }
|
3
|
+
# 5 x-x
|
4
|
+
# / \
|
5
|
+
# 4 x | x
|
6
|
+
# \ /
|
7
|
+
# 3 x
|
8
|
+
# 0 1 2 3 4
|
9
|
+
let(:data) { [[0, 4], [1, 5], [2, 5], [3, 3], [4, 4]] }
|
10
|
+
let(:line) { D3.line.curve(curve).(data) }
|
11
|
+
let(:rounded) { line.gsub(/\d+\.\d+/){$&.to_f.round(2)} }
|
12
|
+
describe "curve_basis" do
|
13
|
+
let(:name){ :curve_basis }
|
14
|
+
it do
|
15
|
+
expect(curve).to be_instance_of(D3::Curve)
|
16
|
+
expect(rounded).to eq("M0,4L0.17,4.17C0.33,4.33,0.67,4.67,1,4.83C1.33,5,1.67,5,2,4.67C2.33,4.33,2.67,3.67,3,3.5C3.33,3.33,3.67,3.67,3.83,3.83L4,4")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "curve_basis_closed" do
|
21
|
+
let(:name){ :curve_basis_closed }
|
22
|
+
it do
|
23
|
+
expect(curve).to be_instance_of(D3::Curve)
|
24
|
+
expect(rounded).to eq("M1,4.83C1.33,5,1.67,5,2,4.67C2.33,4.33,2.67,3.67,3,3.5C3.33,3.33,3.67,3.67,3.17,3.83C2.67,4,1.33,4,0.83,4.17C0.33,4.33,0.67,4.67,1,4.83")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "curve_basis_open" do
|
29
|
+
let(:name){ :curve_basis_open }
|
30
|
+
it do
|
31
|
+
expect(curve).to be_instance_of(D3::Curve)
|
32
|
+
expect(rounded).to eq("M1,4.83C1.33,5,1.67,5,2,4.67C2.33,4.33,2.67,3.67,3,3.5")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "curve_bundle" do
|
37
|
+
let(:name){ :curve_bundle }
|
38
|
+
it do
|
39
|
+
expect(curve).to be_instance_of(D3::CurveBundle)
|
40
|
+
expect(rounded).to eq("M0,4L0.17,4.14C0.33,4.28,0.67,4.57,1,4.71C1.33,4.85,1.67,4.85,2,4.57C2.33,4.28,2.67,3.72,3,3.58C3.33,3.43,3.67,3.72,3.83,3.86L4,4")
|
41
|
+
end
|
42
|
+
|
43
|
+
describe ".beta" do
|
44
|
+
let(:curve) { D3.curve_bundle.beta(0.5) }
|
45
|
+
it do
|
46
|
+
expect(curve).to be_instance_of(D3::CurveBundle)
|
47
|
+
expect(rounded).to eq("M0,4L0.17,4.08C0.33,4.17,0.67,4.33,1,4.42C1.33,4.5,1.67,4.5,2,4.33C2.33,4.17,2.67,3.83,3,3.75C3.33,3.67,3.67,3.83,3.83,3.92L4,4")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "curve_cardinal" do
|
53
|
+
let(:name){ :curve_cardinal }
|
54
|
+
it do
|
55
|
+
expect(curve).to be_instance_of(D3::CurveCardinal)
|
56
|
+
expect(rounded).to eq("M0,4C0,4,0.67,4.83,1,5C1.33,5.17,1.67,5.33,2,5C2.33,4.67,2.67,3.17,3,3C3.33,2.83,4,4,4,4")
|
57
|
+
end
|
58
|
+
describe ".tension" do
|
59
|
+
let(:curve) { D3.curve_cardinal.tension(0.5) }
|
60
|
+
it do
|
61
|
+
expect(curve).to be_instance_of(D3::CurveCardinal)
|
62
|
+
expect(rounded).to eq("M0,4C0,4,0.83,4.92,1,5C1.17,5.08,1.83,5.17,2,5C2.17,4.83,2.83,3.08,3,3C3.17,2.92,4,4,4,4")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "curve_cardinal_closed" do
|
68
|
+
let(:name){ :curve_cardinal_closed }
|
69
|
+
it do
|
70
|
+
expect(curve).to be_instance_of(D3::CurveCardinal)
|
71
|
+
expect(rounded).to eq("M1,5C1.33,5.17,1.67,5.33,2,5C2.33,4.67,2.67,3.17,3,3C3.33,2.83,4.5,3.83,4,4C3.5,4.17,0.5,3.83,0,4C-0.5,4.17,0.67,4.83,1,5")
|
72
|
+
end
|
73
|
+
describe ".tension" do
|
74
|
+
let(:curve) { D3.curve_cardinal_closed.tension(0.5) }
|
75
|
+
it do
|
76
|
+
expect(curve).to be_instance_of(D3::CurveCardinal)
|
77
|
+
expect(rounded).to eq("M1,5C1.17,5.08,1.83,5.17,2,5C2.17,4.83,2.83,3.08,3,3C3.17,2.92,4.25,3.92,4,4C3.75,4.08,0.25,3.92,0,4C-0.25,4.08,0.83,4.92,1,5")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "curve_cardinal_open" do
|
83
|
+
let(:name){ :curve_cardinal_open }
|
84
|
+
it do
|
85
|
+
expect(curve).to be_instance_of(D3::CurveCardinal)
|
86
|
+
expect(rounded).to eq("M1,5C1.33,5.17,1.67,5.33,2,5C2.33,4.67,2.67,3.17,3,3")
|
87
|
+
end
|
88
|
+
describe ".tension" do
|
89
|
+
let(:curve) { D3.curve_cardinal_open.tension(0.5) }
|
90
|
+
it do
|
91
|
+
expect(curve).to be_instance_of(D3::CurveCardinal)
|
92
|
+
expect(rounded).to eq("M1,5C1.17,5.08,1.83,5.17,2,5C2.17,4.83,2.83,3.08,3,3")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "curve_catmull_rom" do
|
98
|
+
let(:name){ :curve_catmull_rom }
|
99
|
+
it do
|
100
|
+
expect(curve).to be_instance_of(D3::CurveCatmullRom)
|
101
|
+
expect(rounded).to eq("M0,4C0,4,0.63,4.85,1,5C1.31,5.13,1.71,5.18,2,5C2.43,4.73,2.62,3.06,3,3C3.3,2.95,4,4,4,4")
|
102
|
+
end
|
103
|
+
describe ".alpha" do
|
104
|
+
let(:curve) { D3.curve_catmull_rom.alpha(0.75) }
|
105
|
+
it do
|
106
|
+
expect(curve).to be_instance_of(D3::CurveCatmullRom)
|
107
|
+
expect(rounded).to eq("M0,4C0,4,0.61,4.85,1,5C1.3,5.11,1.72,5.13,2,5C2.51,4.76,2.59,3,3,3C3.29,3,4,4,4,4")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "curve_catmull_rom_closed" do
|
113
|
+
let(:name){ :curve_catmull_rom_closed }
|
114
|
+
it do
|
115
|
+
expect(curve).to be_instance_of(D3::CurveCatmullRom)
|
116
|
+
expect(rounded).to eq("M1,5C1.31,5.13,1.71,5.18,2,5C2.43,4.73,2.62,3.06,3,3C3.3,2.95,4.09,3.79,4,4C3.85,4.35,0.15,3.65,0,4C-0.09,4.21,0.63,4.85,1,5")
|
117
|
+
end
|
118
|
+
describe ".alpha" do
|
119
|
+
let(:curve) { D3.curve_catmull_rom_closed.alpha(0.75) }
|
120
|
+
it do
|
121
|
+
expect(curve).to be_instance_of(D3::CurveCatmullRom)
|
122
|
+
expect(rounded).to eq("M1,5C1.3,5.11,1.72,5.13,2,5C2.51,4.76,2.59,3,3,3C3.29,3,3.96,3.77,4,4C4.08,4.5,-0.08,3.5,0,4C0.04,4.23,0.61,4.85,1,5")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "curve_catmull_rom_open" do
|
128
|
+
let(:name){ :curve_catmull_rom_open }
|
129
|
+
it do
|
130
|
+
expect(curve).to be_instance_of(D3::CurveCatmullRom)
|
131
|
+
expect(rounded).to eq("M1,5C1.31,5.13,1.71,5.18,2,5C2.43,4.73,2.62,3.06,3,3")
|
132
|
+
end
|
133
|
+
describe ".alpha" do
|
134
|
+
let(:curve) { D3.curve_catmull_rom_open.alpha(0.75) }
|
135
|
+
it do
|
136
|
+
expect(curve).to be_instance_of(D3::CurveCatmullRom)
|
137
|
+
expect(rounded).to eq("M1,5C1.3,5.11,1.72,5.13,2,5C2.51,4.76,2.59,3,3,3")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "curve_linear" do
|
143
|
+
let(:name){ :curve_linear }
|
144
|
+
it do
|
145
|
+
expect(curve).to be_instance_of(D3::Curve)
|
146
|
+
expect(rounded).to eq("M0,4L1,5L2,5L3,3L4,4")
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "curve_linear_closed" do
|
151
|
+
let(:name){ :curve_linear_closed }
|
152
|
+
it do
|
153
|
+
expect(curve).to be_instance_of(D3::Curve)
|
154
|
+
expect(rounded).to eq("M0,4L1,5L2,5L3,3L4,4Z")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "curve_monotone_x" do
|
159
|
+
let(:name){ :curve_monotone_x }
|
160
|
+
it do
|
161
|
+
expect(curve).to be_instance_of(D3::Curve)
|
162
|
+
expect(rounded).to eq("M0,4C0.33,4.5,0.67,5,1,5C1.33,5,1.67,5,2,5C2.33,5,2.67,3,3,3C3.33,3,3.67,3.5,4,4")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "curve_monotone_y" do
|
167
|
+
let(:name){ :curve_monotone_y }
|
168
|
+
it do
|
169
|
+
expect(curve).to be_instance_of(D3::Curve)
|
170
|
+
expect(rounded).to eq("M0,4C0.17,4.33,0.33,4.67,1,5C1,5,2,5,2,5C2.67,4.33,3,3.67,3,3C3,3.33,3.5,3.67,4,4")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "curve_natural" do
|
175
|
+
let(:name){ :curve_natural }
|
176
|
+
it do
|
177
|
+
expect(curve).to be_instance_of(D3::Curve)
|
178
|
+
expect(rounded).to eq("M0,4C0.33,4.36,0.67,4.71,1,5C1.33,5.29,1.67,5.5,2,5C2.33,4.5,2.67,3.29,3,3C3.33,2.71,3.67,3.36,4,4")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "curve_step" do
|
183
|
+
let(:name){ :curve_step }
|
184
|
+
it do
|
185
|
+
expect(curve).to be_instance_of(D3::Curve)
|
186
|
+
expect(rounded).to eq("M0,4L0.5,4L0.5,5L1.5,5L1.5,5L2.5,5L2.5,3L3.5,3L3.5,4L4,4")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "curve_step_after" do
|
191
|
+
let(:name){ :curve_step_after }
|
192
|
+
it do
|
193
|
+
expect(curve).to be_instance_of(D3::Curve)
|
194
|
+
expect(rounded).to eq("M0,4L1,4L1,5L2,5L2,5L3,5L3,3L4,3L4,4")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "curve_step_before" do
|
199
|
+
let(:name){ :curve_step_before }
|
200
|
+
it do
|
201
|
+
expect(curve).to be_instance_of(D3::Curve)
|
202
|
+
expect(rounded).to eq("M0,4L0,5L1,5L1,5L2,5L2,3L3,3L3,4L4,4")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
__END__
|
209
|
+
|
210
|
+
curve.areaStart - start a new area segment.
|
211
|
+
curve.areaEnd - end the current area segment.
|
212
|
+
curve.lineStart - start a new line segment.
|
213
|
+
curve.lineEnd - end the current line segment.
|
214
|
+
curve.point - add a point to the current line segment.
|
data/spec/dsv_spec.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
describe "d3 - dsv" do
|
2
|
+
let(:csv_example) do
|
3
|
+
"Year,Make,Model,Length\n"+
|
4
|
+
"1997,Ford,E350,2.34\n"+
|
5
|
+
"2000,Mercury,Cougar,2.38\n"
|
6
|
+
end
|
7
|
+
let(:tsv_example) do
|
8
|
+
"Year\tMake\tModel\tLength\n"+
|
9
|
+
"1997\tFord\tE350\t2.34\n"+
|
10
|
+
"2000\tMercury\tCougar\t2.38\n"
|
11
|
+
end
|
12
|
+
let(:dsv_example) do
|
13
|
+
"Year;Make;Model;Length\n"+
|
14
|
+
"1997;Ford;E350;2.34\n"+
|
15
|
+
"2000;Mercury;Cougar;2.38\n"
|
16
|
+
end
|
17
|
+
let(:rows_example) {
|
18
|
+
[
|
19
|
+
["Year", "Make", "Model", "Length"],
|
20
|
+
["1997", "Ford", "E350", "2.34"],
|
21
|
+
["2000", "Mercury", "Cougar", "2.38"],
|
22
|
+
]
|
23
|
+
}
|
24
|
+
let(:objs_example) {
|
25
|
+
[
|
26
|
+
{"Year"=>"1997", "Make"=>"Ford", "Model"=>"E350", "Length"=>"2.34"},
|
27
|
+
{"Year"=>"2000", "Make"=>"Mercury", "Model"=>"Cougar", "Length"=>"2.38"},
|
28
|
+
]
|
29
|
+
}
|
30
|
+
let(:csv_format) { D3.dsv_format(",") }
|
31
|
+
let(:tsv_format) { D3.dsv_format("\t") }
|
32
|
+
let(:dsv_format) { D3.dsv_format(";") }
|
33
|
+
let(:format_row) { proc{|(y,f,m,l)|
|
34
|
+
["converted", (Integer(y) rescue y), f, m, (Float(l) rescue l)]
|
35
|
+
}}
|
36
|
+
let(:filter_row) { proc{|d|
|
37
|
+
format_row.(d) if d[0] == "2000" or d[0] == "1997"
|
38
|
+
}}
|
39
|
+
let(:format_obj) { proc{|o|
|
40
|
+
{y: o["Year"].to_i, f:o["Make"], m:o["Model"], l:o["Length"].to_f}
|
41
|
+
}}
|
42
|
+
let(:filter_obj) { proc{|o|
|
43
|
+
format_obj.(o) if o["Year"] == "2000"
|
44
|
+
}}
|
45
|
+
|
46
|
+
it "d3.dsv_format" do
|
47
|
+
expect(D3.dsv_format(";")).to be_instance_of(D3::DsvFormat)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "dsv_format.parse_rows" do
|
51
|
+
expect(dsv_format.parse_rows(dsv_example)).to eq(rows_example)
|
52
|
+
expect(dsv_format.parse_rows(dsv_example, format_row)).to eq(
|
53
|
+
dsv_format.parse_rows(dsv_example, &format_row)
|
54
|
+
)
|
55
|
+
expect(dsv_format.parse_rows(dsv_example, format_row)).to eq([
|
56
|
+
["converted", "Year", "Make", "Model", "Length"],
|
57
|
+
["converted", 1997, "Ford", "E350", 2.34],
|
58
|
+
["converted", 2000, "Mercury", "Cougar", 2.38],
|
59
|
+
])
|
60
|
+
expect(dsv_format.parse_rows(dsv_example, filter_row)).to eq([
|
61
|
+
["converted", 1997, "Ford", "E350", 2.34],
|
62
|
+
["converted", 2000, "Mercury", "Cougar", 2.38],
|
63
|
+
])
|
64
|
+
end
|
65
|
+
|
66
|
+
it "d3.csv_parse_rows" do
|
67
|
+
expect(D3.csv_parse_rows(csv_example)).to eq(
|
68
|
+
csv_format.parse_rows(csv_example))
|
69
|
+
expect(dsv_format.parse_rows(dsv_example)).to eq(
|
70
|
+
csv_format.parse_rows(csv_example))
|
71
|
+
expect(D3.csv_parse_rows(csv_example, format_row)).to eq(
|
72
|
+
csv_format.parse_rows(csv_example, format_row))
|
73
|
+
expect(D3.csv_parse_rows(csv_example, &format_row)).to eq(
|
74
|
+
csv_format.parse_rows(csv_example, &format_row))
|
75
|
+
expect(D3.csv_parse_rows(csv_example, filter_row)).to eq(
|
76
|
+
csv_format.parse_rows(csv_example, filter_row))
|
77
|
+
expect(D3.csv_parse_rows(csv_example, &filter_row)).to eq(
|
78
|
+
csv_format.parse_rows(csv_example, &filter_row))
|
79
|
+
end
|
80
|
+
|
81
|
+
it "d3.tsv_parse_rows" do
|
82
|
+
expect(D3.tsv_parse_rows(tsv_example)).to eq(
|
83
|
+
tsv_format.parse_rows(tsv_example))
|
84
|
+
expect(dsv_format.parse_rows(dsv_example)).to eq(
|
85
|
+
tsv_format.parse_rows(tsv_example))
|
86
|
+
expect(D3.tsv_parse_rows(tsv_example, format_row)).to eq(
|
87
|
+
tsv_format.parse_rows(tsv_example, format_row))
|
88
|
+
expect(D3.tsv_parse_rows(tsv_example, &format_row)).to eq(
|
89
|
+
tsv_format.parse_rows(tsv_example, &format_row))
|
90
|
+
expect(D3.tsv_parse_rows(tsv_example, filter_row)).to eq(
|
91
|
+
tsv_format.parse_rows(tsv_example, filter_row))
|
92
|
+
expect(D3.tsv_parse_rows(tsv_example, &filter_row)).to eq(
|
93
|
+
tsv_format.parse_rows(tsv_example, &filter_row))
|
94
|
+
end
|
95
|
+
|
96
|
+
# It's awful practice not to include final \n,
|
97
|
+
# but it's not our place to workaround D3's bugs here
|
98
|
+
it "dsv_format.format_rows" do
|
99
|
+
expect(dsv_format.format_rows(rows_example)).to eq(dsv_example.chomp)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "d3.csv_format_rows" do
|
103
|
+
expect(csv_format.format_rows(rows_example)).to eq(csv_example.chomp)
|
104
|
+
expect(D3.csv_format_rows(rows_example)).to eq(csv_example.chomp)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "d3.tsv_format_rows" do
|
108
|
+
expect(tsv_format.format_rows(rows_example)).to eq(tsv_example.chomp)
|
109
|
+
expect(D3.tsv_format_rows(rows_example)).to eq(tsv_example.chomp)
|
110
|
+
end
|
111
|
+
|
112
|
+
# We have ways to enforce proper Hash order, maybe it's a good idea
|
113
|
+
it "dsv_format.parse" do
|
114
|
+
expect(dsv_format.parse(dsv_example)).to eq(objs_example)
|
115
|
+
expect(dsv_format.parse(dsv_example, format_obj)).to eq(
|
116
|
+
dsv_format.parse(dsv_example, &format_obj))
|
117
|
+
expect(dsv_format.parse(dsv_example, &format_obj)).to eq([
|
118
|
+
{"y"=>1997, "f"=>"Ford", "m"=>"E350", "l"=>2.34},
|
119
|
+
{"y"=>2000, "f"=>"Mercury", "m"=>"Cougar", "l"=>2.38},
|
120
|
+
])
|
121
|
+
end
|
122
|
+
|
123
|
+
it "dsv_format.parse - filtering" do
|
124
|
+
expect(dsv_format.parse(dsv_example, &filter_obj)).to eq(
|
125
|
+
dsv_format.parse(dsv_example, filter_obj))
|
126
|
+
expect(dsv_format.parse(dsv_example, &filter_obj)).to eq([
|
127
|
+
{"y"=>2000, "f"=>"Mercury", "m"=>"Cougar", "l"=>2.38},
|
128
|
+
])
|
129
|
+
end
|
130
|
+
|
131
|
+
it "d3.csv_parse" do
|
132
|
+
expect(D3.csv_parse(csv_example)).to eq(
|
133
|
+
csv_format.parse(csv_example))
|
134
|
+
expect(dsv_format.parse(dsv_example)).to eq(
|
135
|
+
csv_format.parse(csv_example))
|
136
|
+
expect(D3.csv_parse(csv_example, format_obj)).to eq(
|
137
|
+
csv_format.parse(csv_example, format_obj))
|
138
|
+
expect(D3.csv_parse(csv_example, &format_obj)).to eq(
|
139
|
+
csv_format.parse(csv_example, &format_obj))
|
140
|
+
expect(D3.csv_parse(csv_example, filter_obj)).to eq(
|
141
|
+
csv_format.parse(csv_example, filter_obj))
|
142
|
+
expect(D3.csv_parse(csv_example, &filter_obj)).to eq(
|
143
|
+
csv_format.parse(csv_example, &filter_obj))
|
144
|
+
end
|
145
|
+
|
146
|
+
it "d3.tsv_parse" do
|
147
|
+
expect(D3.tsv_parse(tsv_example)).to eq(
|
148
|
+
tsv_format.parse(tsv_example))
|
149
|
+
expect(dsv_format.parse(dsv_example)).to eq(
|
150
|
+
tsv_format.parse(tsv_example))
|
151
|
+
expect(D3.tsv_parse(tsv_example, format_obj)).to eq(
|
152
|
+
tsv_format.parse(tsv_example, format_obj))
|
153
|
+
expect(D3.tsv_parse(tsv_example, &format_obj)).to eq(
|
154
|
+
tsv_format.parse(tsv_example, &format_obj))
|
155
|
+
expect(D3.tsv_parse(tsv_example, filter_obj)).to eq(
|
156
|
+
tsv_format.parse(tsv_example, filter_obj))
|
157
|
+
expect(D3.tsv_parse(tsv_example, &filter_obj)).to eq(
|
158
|
+
tsv_format.parse(tsv_example, &filter_obj))
|
159
|
+
end
|
160
|
+
|
161
|
+
# Same awful idea of not including final \n
|
162
|
+
it "dsv_format.format" do
|
163
|
+
expect(dsv_format.format(objs_example)).to eq(dsv_example.chomp)
|
164
|
+
expect(dsv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
|
165
|
+
"Year;Make;Speed\n"+
|
166
|
+
"1997;Ford;\n"+
|
167
|
+
"2000;Mercury;"
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "d3.tsv_format" do
|
172
|
+
expect(tsv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
|
173
|
+
"Year\tMake\tSpeed\n"+
|
174
|
+
"1997\tFord\t\n"+
|
175
|
+
"2000\tMercury\t"
|
176
|
+
)
|
177
|
+
expect(tsv_format.format(objs_example)).to eq(
|
178
|
+
D3.tsv_format(objs_example))
|
179
|
+
expect(tsv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
|
180
|
+
D3.tsv_format(objs_example, ["Year", "Make", "Speed"]))
|
181
|
+
end
|
182
|
+
|
183
|
+
it "d3.csv_format" do
|
184
|
+
expect(csv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
|
185
|
+
"Year,Make,Speed\n"+
|
186
|
+
"1997,Ford,\n"+
|
187
|
+
"2000,Mercury,"
|
188
|
+
)
|
189
|
+
expect(csv_format.format(objs_example)).to eq(
|
190
|
+
D3.csv_format(objs_example))
|
191
|
+
expect(csv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
|
192
|
+
D3.csv_format(objs_example, ["Year", "Make", "Speed"]))
|
193
|
+
end
|
194
|
+
end
|