opal-d3 0.0.20170205

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +3 -0
  4. data/README.md +7 -0
  5. data/Rakefile +31 -0
  6. data/d3.js +16393 -0
  7. data/demo/Gemfile +4 -0
  8. data/demo/README.md +7 -0
  9. data/demo/app/data/elections_2016.rb +10 -0
  10. data/demo/app/data/harry_potter.rb +19 -0
  11. data/demo/app/data/iphones.rb +29 -0
  12. data/demo/app/data/london_population.rb +26 -0
  13. data/demo/app/data/man_vs_horse.rb +55 -0
  14. data/demo/app/data/mtg_modern_colors.rb +96 -0
  15. data/demo/app/data/mtg_modern_creatures.rb +116 -0
  16. data/demo/app/data/olympics_2016_medals.rb +100 -0
  17. data/demo/app/data/paradox.rb +60 -0
  18. data/demo/app/data/polish_pms.rb +28 -0
  19. data/demo/app/data/star_trek_voyager.rb +183 -0
  20. data/demo/app/data/weather_in_london.rb +381 -0
  21. data/demo/app/elections_2016.rb +19 -0
  22. data/demo/app/harry_potter.rb +35 -0
  23. data/demo/app/iphones.rb +47 -0
  24. data/demo/app/london_population.rb +46 -0
  25. data/demo/app/london_population_area.rb +42 -0
  26. data/demo/app/man_vs_horse.rb +53 -0
  27. data/demo/app/mtg_modern_colors.rb +49 -0
  28. data/demo/app/mtg_modern_creatures.rb +63 -0
  29. data/demo/app/olympics_2016_medals.rb +54 -0
  30. data/demo/app/paradox.rb +57 -0
  31. data/demo/app/polish_pms.rb +53 -0
  32. data/demo/app/star_trek_voyager.rb +39 -0
  33. data/demo/app/weather_in_london.rb +62 -0
  34. data/demo/assets/d3.js +16393 -0
  35. data/demo/assets/style.css +0 -0
  36. data/demo/config.ru +39 -0
  37. data/demo/views/index.erb +21 -0
  38. data/demo/views/visualization.erb +29 -0
  39. data/lib/opal/d3/arc.rb +21 -0
  40. data/lib/opal/d3/area.rb +49 -0
  41. data/lib/opal/d3/axis.rb +77 -0
  42. data/lib/opal/d3/band_scale.rb +29 -0
  43. data/lib/opal/d3/collections.rb +10 -0
  44. data/lib/opal/d3/color.rb +78 -0
  45. data/lib/opal/d3/continuous_scale.rb +64 -0
  46. data/lib/opal/d3/creator.rb +11 -0
  47. data/lib/opal/d3/curve.rb +74 -0
  48. data/lib/opal/d3/dsv.rb +103 -0
  49. data/lib/opal/d3/ease.rb +319 -0
  50. data/lib/opal/d3/format.rb +97 -0
  51. data/lib/opal/d3/histograms.rb +44 -0
  52. data/lib/opal/d3/interpolate.rb +125 -0
  53. data/lib/opal/d3/line.rb +29 -0
  54. data/lib/opal/d3/map.rb +52 -0
  55. data/lib/opal/d3/misc.rb +15 -0
  56. data/lib/opal/d3/native.rb +84 -0
  57. data/lib/opal/d3/nest.rb +100 -0
  58. data/lib/opal/d3/ordinal_scale.rb +56 -0
  59. data/lib/opal/d3/path.rb +22 -0
  60. data/lib/opal/d3/pie.rb +23 -0
  61. data/lib/opal/d3/point_scale.rb +26 -0
  62. data/lib/opal/d3/polygon.rb +16 -0
  63. data/lib/opal/d3/quadtree.rb +95 -0
  64. data/lib/opal/d3/quantile_scale.rb +21 -0
  65. data/lib/opal/d3/quantize_scale.rb +23 -0
  66. data/lib/opal/d3/radial_area.rb +49 -0
  67. data/lib/opal/d3/radial_line.rb +29 -0
  68. data/lib/opal/d3/random.rb +12 -0
  69. data/lib/opal/d3/search.rb +28 -0
  70. data/lib/opal/d3/selection.rb +149 -0
  71. data/lib/opal/d3/sequential_scale.rb +96 -0
  72. data/lib/opal/d3/set.rb +33 -0
  73. data/lib/opal/d3/stack.rb +11 -0
  74. data/lib/opal/d3/statistics.rb +81 -0
  75. data/lib/opal/d3/symbol.rb +70 -0
  76. data/lib/opal/d3/threshold_scale.rb +23 -0
  77. data/lib/opal/d3/time_format.rb +48 -0
  78. data/lib/opal/d3/time_interval.rb +81 -0
  79. data/lib/opal/d3/transformations.rb +13 -0
  80. data/lib/opal/d3/version.rb +5 -0
  81. data/lib/opal/d3.rb +62 -0
  82. data/lib/opal-d3.rb +9 -0
  83. data/opal-d3.gemspec +20 -0
  84. data/spec/arc_spec.rb +86 -0
  85. data/spec/area_spec.rb +102 -0
  86. data/spec/axis_spec.rb +174 -0
  87. data/spec/band_scale_spec.rb +73 -0
  88. data/spec/color_spec.rb +74 -0
  89. data/spec/continuous_scale_spec.rb +217 -0
  90. data/spec/coverage_spec.rb +23 -0
  91. data/spec/creator_spec.rb +15 -0
  92. data/spec/curve_spec.rb +214 -0
  93. data/spec/dsv_spec.rb +194 -0
  94. data/spec/ease_spec.rb +370 -0
  95. data/spec/format_spec.rb +87 -0
  96. data/spec/histograms_spec.rb +61 -0
  97. data/spec/html/d3.js +16393 -0
  98. data/spec/html/index.html.erb +12 -0
  99. data/spec/interpolate_spec.rb +152 -0
  100. data/spec/line_spec.rb +58 -0
  101. data/spec/map_spec.rb +80 -0
  102. data/spec/misc_spec.rb +19 -0
  103. data/spec/nest_spec.rb +89 -0
  104. data/spec/objects_spec.rb +22 -0
  105. data/spec/ordinal_scale_spec.rb +59 -0
  106. data/spec/path_spec.rb +65 -0
  107. data/spec/pie_spec.rb +114 -0
  108. data/spec/point_scale_spec.rb +58 -0
  109. data/spec/polygon_spec.rb +51 -0
  110. data/spec/quadtree_spec.rb +128 -0
  111. data/spec/quantile_scale_spec.rb +24 -0
  112. data/spec/quantize_scale_spec.rb +40 -0
  113. data/spec/radial_area_spec.rb +127 -0
  114. data/spec/radial_line_spec.rb +54 -0
  115. data/spec/random_spec.rb +34 -0
  116. data/spec/search_spec.rb +69 -0
  117. data/spec/selection_data_spec.rb +71 -0
  118. data/spec/selection_manipulation_spec.rb +179 -0
  119. data/spec/selection_spec.rb +214 -0
  120. data/spec/sequential_scale_spec.rb +90 -0
  121. data/spec/set_spec.rb +57 -0
  122. data/spec/spec_helper.rb +2 -0
  123. data/spec/stack_spec.rb +23 -0
  124. data/spec/statistics_spec.rb +65 -0
  125. data/spec/symbol_spec.rb +121 -0
  126. data/spec/threshold_scale_spec.rb +28 -0
  127. data/spec/time_format_spec.rb +99 -0
  128. data/spec/time_interval_spec.rb +304 -0
  129. data/spec/transformations_spec.rb +51 -0
  130. metadata +258 -0
@@ -0,0 +1,58 @@
1
+ describe "d3 - point scale" do
2
+ it "d3.scale_point" do
3
+ expect(D3.scale_point).to be_instance_of(D3::PointScale)
4
+ end
5
+
6
+ let(:d) { ("a".."f").to_a }
7
+ it "basics" do
8
+ scale = D3.scale_point.domain(d)
9
+ expect(d.map{|v| scale.(v).round(2)}).to eq([0, 0.2, 0.4, 0.6, 0.8, 1])
10
+ expect(scale.bandwidth).to eq(0)
11
+ expect(scale.step).to eq(0.2)
12
+ expect(scale.("z")).to eq(nil)
13
+ end
14
+
15
+ it "copy" do
16
+ scale = D3.scale_point.domain(d)
17
+ sc = scale.copy.range([10,20])
18
+ expect(scale.domain).to eq(d)
19
+ expect(sc.domain).to eq(d)
20
+ expect(scale.range).to eq([0,1])
21
+ expect(sc.range).to eq([10,20])
22
+ end
23
+
24
+ it "padding" do
25
+ scale = D3.scale_point.domain(d).range([0,100])
26
+ expect(scale.padding).to eq(0)
27
+
28
+ scale.padding(0.5)
29
+ expect(scale.padding).to eq(0.5)
30
+ expect(d.map{|v| scale.(v).round(2)}).to eq([8.33, 25, 41.67, 58.33, 75, 91.67])
31
+ end
32
+
33
+ it "align" do
34
+ scale = D3.scale_point.domain(d).range([0,100])
35
+ scale.padding(0.5)
36
+
37
+ expect(scale.align).to eq(0.5)
38
+ expect(d.map{|v| scale.(v).round(2)}).to eq([8.33, 25, 41.67, 58.33, 75, 91.67])
39
+
40
+ scale.align(0)
41
+ expect(scale.align).to eq(0)
42
+ expect(d.map{|v| scale.(v).round(2)}).to eq([0, 16.67, 33.33, 50, 66.67, 83.33])
43
+
44
+ scale.align(1)
45
+ expect(scale.align).to eq(1)
46
+ expect(d.map{|v| scale.(v).round(2)}).to eq([16.67, 33.33, 50, 66.67, 83.33, 100])
47
+ end
48
+
49
+ it "round" do
50
+ scale = D3.scale_point.domain(d).range([0,100])
51
+ expect(scale.round).to eq(false)
52
+ scale.range_round([0,1000]).padding(1)
53
+ expect(scale.range).to eq([0,1000])
54
+ expect(scale.round).to eq(true)
55
+ # This rounding is somewhat weird
56
+ expect(d.map{|v| scale.(v)}).to eq([145, 287, 429, 571, 713, 855])
57
+ end
58
+ end
@@ -0,0 +1,51 @@
1
+ describe "d3 - polygon" do
2
+ let(:square) {
3
+ [[10,10], [40,10], [40,40], [10,40]]
4
+ }
5
+ let(:triangle) {
6
+ [[100,0], [160,0], [130, 40]]
7
+ }
8
+ let(:random_points) {[
9
+ [6, 39], [59, 86], [96, 20], [56, 5], [96, 98],
10
+ [70, 4], [47, 48], [77, 15], [2, 60], [41, 28],
11
+ [56, 59], [10, 15], [79, 12], [82, 97], [71, 14],
12
+ [18, 30], [64, 86], [35, 83], [49, 73], [78, 12],
13
+ ]}
14
+
15
+ # signed area
16
+ it "d3.polygon_area" do
17
+ expect(D3.polygon_area(square)).to eq(-900)
18
+ expect(D3.polygon_area(triangle)).to eq(-1200)
19
+ end
20
+
21
+ it "d3.polygon_centroid" do
22
+ expect(D3.polygon_centroid(square)).to eq([25, 25])
23
+ expect(D3.polygon_centroid(triangle)).to eq([130, 13.333333333333334])
24
+ end
25
+
26
+ it "d3.polygon_length" do
27
+ expect(D3.polygon_length(square)).to eq(120)
28
+ expect(D3.polygon_length(triangle)).to eq(160)
29
+ end
30
+
31
+ it "d3.polygon_contains?" do
32
+ expect(D3.polygon_contains?(square, [20, 20])).to eq(true)
33
+ expect(D3.polygon_contains?(square, [50, 20])).to eq(false)
34
+ # Sometimes corners considered "inside"
35
+ expect(D3.polygon_contains?(square, [10, 10])).to eq(true)
36
+ end
37
+
38
+ it "d3.polygon_hull" do
39
+ hull = D3.polygon_hull(random_points)
40
+ hull.each do |pt|
41
+ expect(random_points).to include(pt)
42
+ end
43
+
44
+ random_points.each do |pt|
45
+ # Sometimes corners not considered "inside"
46
+ expect(D3.polygon_contains?(hull, pt) || hull.include?(pt)).to eq(true)
47
+ end
48
+
49
+ expect(D3.polygon_hull([[10,10], [20,20]])).to eq(nil)
50
+ end
51
+ end
@@ -0,0 +1,128 @@
1
+ describe "d3 - quadtree" do
2
+ let(:a) { [1,2,"a"] }
3
+ let(:a2) { [1,2,"a"] }
4
+ let(:b) { [3,4,"b"] }
5
+ let(:c) { [5,6,"c"] }
6
+ let(:d) { [7,8,"c"] }
7
+ let(:e) { [3,4,"e"] }
8
+
9
+ it "d3.quadtree" do
10
+ expect(D3.quadtree).to be_instance_of(D3::QuadTree)
11
+ end
12
+
13
+ it "quadtree.size" do
14
+ q = D3.quadtree
15
+ expect(q.size).to eq(0)
16
+ expect(q.add(a).size).to eq(1)
17
+ expect(q.add(b).size).to eq(2)
18
+ end
19
+
20
+ it "quadtree.remove" do
21
+ q = D3.quadtree
22
+ expect(q.size).to eq(0)
23
+ expect(q.add(a).add(b).size).to eq(2)
24
+ expect(q.remove(a2).size).to eq(2)
25
+ expect(q.remove(a).size).to eq(1)
26
+ expect(q.remove(c).size).to eq(1)
27
+ end
28
+
29
+ it "quadtree.remove_all" do
30
+ q = D3.quadtree([a,b,c])
31
+ expect(q.remove_all([b,d]).data).to eq([a,c])
32
+ end
33
+
34
+ it "quadtree.data" do
35
+ q = D3.quadtree
36
+ expect(q.data).to eq([])
37
+ expect(q.add(a).data).to eq([a])
38
+ expect(q.add_all([b,c]).data).to eq([a,b,c])
39
+ end
40
+
41
+ it "quadtree.find" do
42
+ q = D3.quadtree
43
+ expect(q.find(1,1)).to eq(nil)
44
+ q.add([1,2,"foo"])
45
+ expect(q.find(3,3)).to eq([1,2,"foo"])
46
+ expect(q.find(3,3,1)).to eq(nil)
47
+ end
48
+
49
+ it "quadtree.copy" do
50
+ q1 = D3.quadtree.add(a)
51
+ q2 = q1.copy.add(b)
52
+ q1.add(c)
53
+ expect(q1.data).to eq([a,c])
54
+ expect(q2.data).to eq([a,b])
55
+ end
56
+
57
+ it "quadtree.visit" do
58
+ q = D3.quadtree([a,b,c,e])
59
+ called = []
60
+ q.visit do |node, x0, y0, x1, y1|
61
+ called << [x0, y0, x1, y1, node.internal?, node.leaf?, node.data, !!node.next, node.children && node.children.map{|x| !!x}]
62
+ false
63
+ end
64
+ expect(called).to eq([
65
+ [1, 2, 5, 6, true, false, nil, false, [true, false, false, true]],
66
+ [1, 2, 3, 4, false, true, [1, 2, "a"], false, nil],
67
+ [3, 4, 5, 6, true, false, nil, false, [true, false, false, true]],
68
+ [3, 4, 4, 5, false, true, [3, 4, "e"], true, nil],
69
+ [4, 5, 5, 6, false, true, [5, 6, "c"], false, nil],
70
+ ])
71
+ end
72
+
73
+ it "quadtree.visit_after" do
74
+ q = D3.quadtree([a,b,c,e])
75
+ called = []
76
+ q.visit_after do |node, x0, y0, x1, y1|
77
+ called << [x0, y0, x1, y1, node.internal?, node.leaf?, node.data, !!node.next, node.children && node.children.map{|x| !!x}]
78
+ false
79
+ end
80
+ expect(called).to eq([
81
+ [1, 2, 3, 4, false, true, [1, 2, "a"], false, nil],
82
+ [3, 4, 4, 5, false, true, [3, 4, "e"], true, nil],
83
+ [4, 5, 5, 6, false, true, [5, 6, "c"], false, nil],
84
+ [3, 4, 5, 6, true, false, nil, false, [true, false, false, true]],
85
+ [1, 2, 5, 6, true, false, nil, false, [true, false, false, true]],
86
+ ])
87
+ end
88
+
89
+ it "quadtree.root" do
90
+ q = D3.quadtree([a,b,c])
91
+ root = q.root
92
+ expect(root).to be_instance_of(D3::Quad)
93
+ expect(root).to be_internal
94
+ end
95
+
96
+ it "quadtree.extent" do
97
+ q = D3.quadtree([a,b,c])
98
+ expect(q.extent).to eq([[1, 2], [5, 6]])
99
+ expect(q.extent([[0,0],[10,1]]).extent([[-1,-1],[1,1]]).extent).to eq([[-3, -10], [13, 6]])
100
+ end
101
+
102
+ it "quadtree.cover" do
103
+ q = D3.quadtree([a,b,c])
104
+ expect(q.extent).to eq([[1, 2], [5, 6]])
105
+ expect(q.cover(0,0).cover(-2,10).extent).to eq([[-11, -2], [5, 14]])
106
+ end
107
+
108
+ it "quadtree.x/y defaults" do
109
+ q = D3.quadtree([a,b,c])
110
+ expect(q.x.(c)).to eq(5)
111
+ expect(q.y.(c)).to eq(6)
112
+ end
113
+
114
+ it "quadtree.x/y constructor" do
115
+ q = D3.quadtree([a,b,c], proc{|(x,y,n)| x*10}, proc{|(x,y,n)| y*10})
116
+ expect(q.x.(c)).to eq(50)
117
+ expect(q.y.(c)).to eq(60)
118
+ expect(q.extent).to eq([[10, 20], [74, 84]])
119
+ end
120
+
121
+ it "quadtree.x/y" do
122
+ q = D3.quadtree
123
+ q.x{|(x,y,n)| y*100}.y{|(x,y,n)| x*100}.add_all([a,b,c])
124
+ expect(q.x.(c)).to eq(600)
125
+ expect(q.y.(c)).to eq(500)
126
+ expect(q.extent).to eq([[200, 100], [712, 612]])
127
+ end
128
+ end
@@ -0,0 +1,24 @@
1
+ describe "d3 - quantile scale" do
2
+ it "d3.scale_quantile" do
3
+ expect(D3.scale_quantile).to be_instance_of(D3::QuantileScale)
4
+ end
5
+
6
+ it "basics" do
7
+ q = D3.scale_quantile.domain([0,10]).range(("a".."f").to_a)
8
+ expect(q.(4)).to eq("c")
9
+
10
+ expect(q.domain).to eq([0,10])
11
+ expect(q.range).to eq(("a".."f").to_a)
12
+ expect(q.quantiles).to eq([1.6666666666666665, 3.333333333333333, 5, 6.666666666666666, 8.333333333333334])
13
+ expect(q.invert_extent("e")).to eq([6.666666666666666, 8.333333333333334])
14
+ end
15
+
16
+ it "copy" do
17
+ q = D3.scale_quantile.domain([1,5]).range(["x", "y"])
18
+ qc = q.copy.domain([0,20])
19
+ expect(qc.domain).to eq([0,20])
20
+ expect(qc.range).to eq(["x", "y"])
21
+ expect(q.domain).to eq([1,5])
22
+ expect(q.range).to eq(["x", "y"])
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ describe "d3 - quantize scale" do
2
+ let(:color) { D3.scale_quantize.domain([0, 1]).range(["brown", "steelblue"]) }
3
+ let(:width) { D3.scale_quantize.domain([10, 100]).range([1, 2, 4]) }
4
+
5
+ it "d3.quantize_scale" do
6
+ expect(D3.scale_quantize).to be_instance_of(D3::QuantizeScale)
7
+ end
8
+
9
+ it "basics - color" do
10
+ expect(color.(0.49)).to eq("brown")
11
+ expect(color.(0.51)).to eq("steelblue")
12
+ expect(color.domain).to eq([0,1])
13
+ expect(color.range).to eq(["brown", "steelblue"])
14
+ end
15
+
16
+ it "basics - width" do
17
+ expect(width.(20)).to eq(1)
18
+ expect(width.(50)).to eq(2)
19
+ expect(width.(80)).to eq(4)
20
+ expect(width.invert_extent(2)).to eq([40, 70])
21
+ end
22
+
23
+ it ".nice / .copy" do
24
+ s = D3.scale_quantize.domain([7, 109]).range([1, 2, 4])
25
+ sc = s.copy
26
+ expect(s.nice().domain).to eq([0, 110])
27
+ expect(sc.domain).to eq([7, 109])
28
+ end
29
+
30
+ it ".ticks" do
31
+ expect(width.ticks).to eq([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
32
+ expect(width.ticks(5)).to eq([20, 40, 60, 80, 100])
33
+ end
34
+
35
+ it ".tick_format" do
36
+ expect(width.tick_format.(30)).to eq("30")
37
+ expect(width.tick_format(5).(30)).to eq("30")
38
+ expect(width.tick_format(5, "+%").(30)).to eq("+3000%")
39
+ end
40
+ end
@@ -0,0 +1,127 @@
1
+ describe "d3 - radial area" do
2
+ it "d3.radial_area" do
3
+ expect(D3.radial_area).to be_instance_of(D3::RadialAreaGenerator)
4
+ end
5
+
6
+ let(:simple_data) {[
7
+ {year: 2007, value: 93.24},
8
+ {year: 2008, value: 95.35},
9
+ {year: 2009, value: 98.84},
10
+ {year: 2010, value: 99.92},
11
+ {year: 2011, value: 99.80},
12
+ {year: 2014, value: 99.47},
13
+ ]}
14
+
15
+ describe "basics" do
16
+ let(:radial_area) {
17
+ D3.radial_area
18
+ .angle{|d| (d[:year]-2000)/10 }
19
+ .outer_radius{|d| d[:value] }
20
+ .inner_radius(50)
21
+ }
22
+ it "basics" do
23
+ expect(radial_area.(simple_data).gsub(/\d+\.\d+/){$&.to_f.round(2)}).to eq(%W[
24
+ M60.07,-71.31
25
+ L68.4,-66.43
26
+ L77.42,-61.44
27
+ L84.08,-53.99
28
+ L88.94,-45.27
29
+ L98.02,-16.91
30
+ L49.27,-8.5
31
+ L44.56,-22.68
32
+ L42.07,-27.02
33
+ L39.17,-31.08
34
+ L35.87,-34.84
35
+ L32.21,-38.24
36
+ Z
37
+ ].join)
38
+ end
39
+
40
+ it "curve" do
41
+ expect(radial_area.curve).to be_instance_of(D3::Curve)
42
+ expect(radial_area.curve(D3.curve_natural).(simple_data).gsub(/\d+\.\d+/){$&.to_f.round(2)}).to eq(%W[
43
+ M60.07,-71.31C62.74,-69.61,65.42,-67.91,68.4,-66.43
44
+ C71.38,-64.95,74.66,-63.68,77.42,-61.44
45
+ C80.19,-59.2,82.45,-55.98,84.08,-53.99
46
+ C85.71,-52,86.72,-51.24,88.94,-45.27
47
+ C91.16,-39.29,94.59,-28.1,98.02,-16.91
48
+ L49.27,-8.5
49
+ C47.49,-14.1,45.72,-19.7,44.56,-22.68
50
+ C43.4,-25.66,42.87,-26.01,42.07,-27.02
51
+ C41.28,-28.02,40.23,-29.66,39.17,-31.08
52
+ C38.1,-32.5,37.03,-33.68,35.87,-34.84
53
+ C34.71,-35.99,33.46,-37.12,32.21,-38.24
54
+ Z
55
+ ].join)
56
+ end
57
+
58
+
59
+ it ".defined" do
60
+ expect(radial_area.defined{|d| d[:year] != 2010}.(simple_data).gsub(/\d+\.\d+/){$&.to_f.round(2)}).to eq(%W[
61
+ M60.07,-71.31
62
+ L68.4,-66.43
63
+ L77.42,-61.44
64
+ L39.17,-31.08
65
+ L35.87,-34.84
66
+ L32.21,-38.24
67
+ Z
68
+ M88.94,-45.27
69
+ L98.02,-16.91
70
+ L49.27,-8.5
71
+ L44.56,-22.68
72
+ Z
73
+ ].join)
74
+ end
75
+ end
76
+
77
+ describe "line generators" do
78
+ let(:radial_area) {
79
+ D3.radial_area
80
+ .start_angle{|d| (d[:year]-2000)/20 }
81
+ .end_angle{|d| (d[:year]-2000)/10 }
82
+ .outer_radius{|d| d[:value] }
83
+ .inner_radius(50)
84
+ }
85
+ let(:point) { {year: 2042, value: 117 } }
86
+
87
+ it ".angle/.start_angle/.end_angle" do
88
+ expect(radial_area.start_angle.(point)).to eq(2.1)
89
+ expect(radial_area.end_angle.(point)).to eq(4.2)
90
+ expect(radial_area.angle.(point)).to eq(2.1)
91
+ end
92
+
93
+ it ".radius/.inner_radius/.outer_radius" do
94
+ expect(radial_area.inner_radius.(point)).to eq(50)
95
+ expect(radial_area.outer_radius.(point)).to eq(117)
96
+ expect(radial_area.radius.(point)).to eq(50)
97
+ end
98
+
99
+ it ".line_start_angle" do # start_angle inner_radius
100
+ expect(radial_area.line_start_angle).to be_instance_of(D3::RadialLineGenerator)
101
+ expect(radial_area.line_start_angle.angle.(point)).to eq(2.1)
102
+ expect(radial_area.line_start_angle.radius.(point)).to eq(50)
103
+ end
104
+
105
+ it ".line_end_angle" do # end_angle inner_radius
106
+ expect(radial_area.line_end_angle).to be_instance_of(D3::RadialLineGenerator)
107
+ expect(radial_area.line_end_angle.angle.(point)).to eq(4.2)
108
+ expect(radial_area.line_end_angle.radius.(point)).to eq(50)
109
+ end
110
+
111
+ it ".line_inner_radius" do # start_angle inner_radius
112
+ expect(radial_area.line_inner_radius).to be_instance_of(D3::RadialLineGenerator)
113
+ expect(radial_area.line_inner_radius.angle.(point)).to eq(2.1)
114
+ expect(radial_area.line_inner_radius.radius.(point)).to eq(50)
115
+ end
116
+
117
+ it ".line_outer_radius" do # start_angle outer_radius
118
+ expect(radial_area.line_outer_radius).to be_instance_of(D3::RadialLineGenerator)
119
+ expect(radial_area.line_outer_radius.angle.(point)).to eq(2.1)
120
+ expect(radial_area.line_outer_radius.radius.(point)).to eq(117)
121
+ end
122
+ end
123
+ end
124
+
125
+ __END__
126
+
127
+ radialArea.context - set the rendering context.
@@ -0,0 +1,54 @@
1
+ describe "d3 - radial line" do
2
+ it "d3.radial_line" do
3
+ expect(D3.radial_line).to be_instance_of(D3::RadialLineGenerator)
4
+ end
5
+
6
+ let(:simple_data) { [[0,2],[Math::PI*0.10,5],[Math::PI*0.20,3]] }
7
+
8
+ it "basics" do
9
+ expect(D3.radial_line.(simple_data)).to eq("M0,-2L1.545084971874737,-4.755282581475767L1.7633557568774194,-2.4270509831248424")
10
+ end
11
+
12
+ it "curve" do
13
+ expect(D3.radial_line.curve).to be_instance_of(D3::Curve)
14
+ expect(D3.radial_line.curve(D3.curve_natural).(simple_data)).to eq(%W[
15
+ M0,-2
16
+ C0.6255961728642502,-3.3420537088108135,1.2511923457285004,-4.684107417621627,1.545084971874737,-4.755282581475767
17
+ C1.8389775980209737,-4.826457745329908,1.8011666774491966,-3.626754364227375,1.7633557568774194,-2.4270509831248424
18
+ ].join)
19
+ end
20
+
21
+ it "angle/radius accessors" do
22
+ radial_line = D3.radial_line
23
+ radial_line.angle{|(a,r)| a*2}.radius{|(a,r)| r*100}
24
+ expect(radial_line.angle.([2,42])).to eq(4)
25
+ expect(radial_line.radius.([2,42])).to eq(4200)
26
+ expect(radial_line.(simple_data)).to eq("M0,-200L293.8926261462366,-404.5084971874737L285.31695488854604,-92.70509831248424")
27
+ end
28
+
29
+ it ".angle constant" do
30
+ radial_line = D3.radial_line.angle(Math::PI)
31
+ expect(radial_line.(simple_data)).to eq("M2.4492935982947064e-16,2L6.123233995736766e-16,5L3.6739403974420594e-16,3")
32
+ expect(radial_line.angle.(42)).to eq(Math::PI)
33
+ radial_line.angle = 20
34
+ expect(radial_line.angle.(42)).to eq(20)
35
+ end
36
+
37
+ it ".radius constant" do
38
+ radial_line = D3.radial_line.radius(10)
39
+ expect(radial_line.(simple_data)).to eq("M0,-10L3.090169943749474,-9.510565162951535L5.877852522924732,-8.090169943749475")
40
+ expect(radial_line.radius.(42)).to eq(10)
41
+ radial_line.radius = 20
42
+ expect(radial_line.radius.(42)).to eq(20)
43
+ end
44
+
45
+ it ".defined" do
46
+ radial_line = D3.radial_line.defined{|(a,r)| r.even?}
47
+ data = [[0,6], [0,10], [0,11], [0,14], [0,16], [0,19]]
48
+ expect(radial_line.(data)).to eq("M0,-6L0,-10M0,-14L0,-16")
49
+ end
50
+ end
51
+
52
+ __END__
53
+
54
+ radialLine.context - set the rendering context.
@@ -0,0 +1,34 @@
1
+ describe "d3-random" do
2
+ # Not really testing anything more meaningful,
3
+ # just that they return some numbers
4
+ # http://xkcd.com/221/
5
+ it "d3.random_uniform" do
6
+ expect(D3.random_uniform.call).to be_a(Numeric)
7
+ expect(D3.random_uniform(10).call).to be_a(Numeric)
8
+ expect(D3.random_uniform(10,20).call).to be_a(Numeric)
9
+ end
10
+
11
+ it "d3.random_normal" do
12
+ expect(D3.random_normal.call).to be_a(Numeric)
13
+ expect(D3.random_normal(10).call).to be_a(Numeric)
14
+ expect(D3.random_normal(10, 2).call).to be_a(Numeric)
15
+ end
16
+
17
+ it "d3.random_log_normal" do
18
+ expect(D3.random_log_normal.call).to be_a(Numeric)
19
+ expect(D3.random_log_normal(10).call).to be_a(Numeric)
20
+ expect(D3.random_log_normal(10, 2).call).to be_a(Numeric)
21
+ end
22
+
23
+ it "d3.random_bates" do
24
+ expect(D3.random_bates(5).call).to be_a(Numeric)
25
+ end
26
+
27
+ it "d3.random_irwin_hall" do
28
+ expect(D3.random_irwin_hall(5).call).to be_a(Numeric)
29
+ end
30
+
31
+ it "d3.random_exponential" do
32
+ expect(D3.random_exponential(3).call).to be_a(Numeric)
33
+ end
34
+ end
@@ -0,0 +1,69 @@
1
+ describe "d3-array - search" do
2
+ it "d3.ascending" do
3
+ expect(D3.ascending(2,1)).to eq(1)
4
+ expect(D3.ascending(1,1)).to eq(0)
5
+ expect(D3.ascending(1,2)).to eq(-1)
6
+ end
7
+
8
+ it "d3.descending" do
9
+ expect(D3.descending(2,1)).to eq(-1)
10
+ expect(D3.descending(1,1)).to eq(0)
11
+ expect(D3.descending(1,2)).to eq(1)
12
+ end
13
+
14
+ it "d3.scan" do
15
+ array = [13,5,11,26,32]
16
+ expect(D3.scan(array)).to eq(1)
17
+ expect(D3.scan(array){|a,b| (a%10) - (b%10)}).to eq(2)
18
+ expect(D3.scan(array){|a,b| (b%10) - (a%10)}).to eq(3)
19
+ end
20
+
21
+ it "d3.bisect_left" do
22
+ array = (100..200).to_a
23
+ expect(D3.bisect_left(array, 117)).to eq(17)
24
+ expect(D3.bisect_left(array, 130.5)).to eq(31)
25
+ end
26
+
27
+ it "d3.bisect_right" do
28
+ array = (100..200).to_a
29
+ expect(D3.bisect_right(array, 117)).to eq(18)
30
+ expect(D3.bisect_right(array, 130.5)).to eq(31)
31
+ end
32
+
33
+ it "d3.bisect" do
34
+ array = (100..200).to_a
35
+ expect(D3.bisect(array, 117)).to eq(18)
36
+ expect(D3.bisect(array, 130.5)).to eq(31)
37
+ end
38
+
39
+ it "d3.bisector" do
40
+ expect(D3.bisector{|x| x.abs}).to be_instance_of(D3::Bisector)
41
+ expect(D3.bisector{|x,y| x.abs - y.abs}).to be_instance_of(D3::Bisector)
42
+ end
43
+
44
+ describe "D3::Bisector" do
45
+ let(:array) { (100..200).map{|i| i * (-1)**i} }
46
+ let(:a) { D3.bisector{|x| x.abs} }
47
+ let(:c) { D3.bisector{|x,y| x.abs - y.abs} }
48
+
49
+ it "A.left" do
50
+ expect(a.left(array, 117)).to eq(17)
51
+ expect(a.left(array, 130.5)).to eq(31)
52
+ end
53
+
54
+ it "C.left" do
55
+ expect(c.left(array, 117)).to eq(17)
56
+ expect(c.left(array, 130.5)).to eq(31)
57
+ end
58
+
59
+ it "A.right" do
60
+ expect(a.right(array, 117)).to eq(18)
61
+ expect(a.right(array, 130.5)).to eq(31)
62
+ end
63
+
64
+ it "C.right" do
65
+ expect(c.right(array, 117)).to eq(18)
66
+ expect(c.right(array, 130.5)).to eq(31)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,71 @@
1
+ describe "d3 - selection - data" 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
+ describe "list" do
9
+ let(:data) {[
10
+ {name: "A", value: 10},
11
+ {name: "B", value: 20},
12
+ {name: "C", value: 30},
13
+ ]}
14
+ it "enter" do
15
+ root
16
+ .append("ul")
17
+ .select_all("li")
18
+ .data(data)
19
+ .enter
20
+ .append("li")
21
+ .html{|d| "<b>#{d[:name]}</b>"}
22
+ .style("font-size"){|d| "#{d[:value]}px"}
23
+ expect(html).to eq([
24
+ %Q[<ul>],
25
+ %Q[<li style="font-size: 10px;"><b>A</b></li>],
26
+ %Q[<li style="font-size: 20px;"><b>B</b></li>],
27
+ %Q[<li style="font-size: 30px;"><b>C</b></li>],
28
+ %Q[</ul>],
29
+ ].join)
30
+ end
31
+ end
32
+
33
+ describe "matrix" do
34
+ let(:data) {
35
+ [
36
+ [11975, 5871, 8916, 2868],
37
+ [ 1951, 10048, 2060, 6171],
38
+ [ 8010, 16145, 8090, 8045],
39
+ [ 1013, 990, 940, 6907],
40
+ ]
41
+ }
42
+ it do
43
+ tr = root
44
+ .append("table")
45
+ .select_all("tr")
46
+ .data(data)
47
+ .enter
48
+ .append("tr")
49
+ tr.select_all("td")
50
+ .data{|d| d}
51
+ .enter
52
+ .append("td")
53
+ .text{|d| d}
54
+ expect(html).to eq([
55
+ %Q[<table>],
56
+ %Q[<tr><td>11975</td><td>5871</td><td>8916</td><td>2868</td></tr>],
57
+ %Q[<tr><td>1951</td><td>10048</td><td>2060</td><td>6171</td></tr>],
58
+ %Q[<tr><td>8010</td><td>16145</td><td>8090</td><td>8045</td></tr>],
59
+ %Q[<tr><td>1013</td><td>990</td><td>940</td><td>6907</td></tr>],
60
+ %Q[</table>],
61
+ ].join)
62
+ end
63
+ end
64
+ end
65
+
66
+ __END__
67
+
68
+ .data key
69
+
70
+ selection.exit - get the exit selection (elements missing data).
71
+ selection.datum - get or set element data (without joining).