d3_rails 2.8.0 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.DS_Store +0 -0
  2. data/README.md +27 -5
  3. data/lib/d3_rails/version.rb +1 -1
  4. data/vendor/.DS_Store +0 -0
  5. data/vendor/assets/.DS_Store +0 -0
  6. data/vendor/assets/javascripts/.DS_Store +0 -0
  7. data/vendor/assets/javascripts/d3.v2.js +99 -80
  8. data/vendor/assets/javascripts/morris.js +1 -0
  9. data/vendor/assets/javascripts/morris/.DS_Store +0 -0
  10. data/vendor/assets/javascripts/morris/Makefile +10 -0
  11. data/vendor/assets/javascripts/morris/README.md +87 -0
  12. data/vendor/assets/javascripts/morris/examples/_template.html +18 -0
  13. data/vendor/assets/javascripts/morris/examples/days.html +36 -0
  14. data/vendor/assets/javascripts/morris/examples/decimal.html +31 -0
  15. data/vendor/assets/javascripts/morris/examples/lib/example.css +13 -0
  16. data/vendor/assets/javascripts/morris/examples/lib/example.js +4 -0
  17. data/vendor/assets/javascripts/morris/examples/lib/prettify.css +1 -0
  18. data/vendor/assets/javascripts/morris/examples/lib/prettify.js +28 -0
  19. data/vendor/assets/javascripts/morris/examples/months-no-smooth.html +37 -0
  20. data/vendor/assets/javascripts/morris/examples/negative.html +35 -0
  21. data/vendor/assets/javascripts/morris/examples/non-date.html +36 -0
  22. data/vendor/assets/javascripts/morris/examples/quarters.html +53 -0
  23. data/vendor/assets/javascripts/morris/examples/timestamps.html +37 -0
  24. data/vendor/assets/javascripts/morris/examples/weeks.html +52 -0
  25. data/vendor/assets/javascripts/morris/morris.coffee +444 -0
  26. data/vendor/assets/javascripts/morris/morris.js +493 -0
  27. data/vendor/assets/javascripts/morris/morris.min.js +1 -0
  28. data/vendor/assets/javascripts/tesseract.js +1 -0
  29. data/vendor/assets/javascripts/tesseract/.gitignore +2 -0
  30. data/vendor/assets/javascripts/tesseract/LICENSE +12 -0
  31. data/vendor/assets/javascripts/tesseract/Makefile +48 -0
  32. data/vendor/assets/javascripts/tesseract/README.md +11 -0
  33. data/vendor/assets/javascripts/tesseract/index.js +1 -0
  34. data/vendor/assets/javascripts/tesseract/lib/dart/AUTHORS +9 -0
  35. data/vendor/assets/javascripts/tesseract/lib/dart/LICENSE +25 -0
  36. data/vendor/assets/javascripts/tesseract/lib/dart/dual_pivot_quicksort.dart +342 -0
  37. data/vendor/assets/javascripts/tesseract/package.json +11 -0
  38. data/vendor/assets/javascripts/tesseract/src/array.js +32 -0
  39. data/vendor/assets/javascripts/tesseract/src/bisect.js +44 -0
  40. data/vendor/assets/javascripts/tesseract/src/filter.js +19 -0
  41. data/vendor/assets/javascripts/tesseract/src/heap.js +44 -0
  42. data/vendor/assets/javascripts/tesseract/src/heapselect.js +36 -0
  43. data/vendor/assets/javascripts/tesseract/src/identity.js +3 -0
  44. data/vendor/assets/javascripts/tesseract/src/insertionsort.js +18 -0
  45. data/vendor/assets/javascripts/tesseract/src/null.js +3 -0
  46. data/vendor/assets/javascripts/tesseract/src/package.js +14 -0
  47. data/vendor/assets/javascripts/tesseract/src/permute.js +8 -0
  48. data/vendor/assets/javascripts/tesseract/src/quicksort.js +282 -0
  49. data/vendor/assets/javascripts/tesseract/src/reduce.js +19 -0
  50. data/vendor/assets/javascripts/tesseract/src/tesseract.js +663 -0
  51. data/vendor/assets/javascripts/tesseract/src/version.js +1 -0
  52. data/vendor/assets/javascripts/tesseract/src/zero.js +3 -0
  53. data/vendor/assets/javascripts/tesseract/tesseract.js +1177 -0
  54. data/vendor/assets/javascripts/tesseract/tesseract.min.js +1 -0
  55. data/vendor/assets/javascripts/tesseract/test/benchmark.js +177 -0
  56. data/vendor/assets/javascripts/tesseract/test/bisect-test.js +206 -0
  57. data/vendor/assets/javascripts/tesseract/test/heap-test.js +44 -0
  58. data/vendor/assets/javascripts/tesseract/test/permute-test.js +51 -0
  59. data/vendor/assets/javascripts/tesseract/test/select-test.js +63 -0
  60. data/vendor/assets/javascripts/tesseract/test/sort-test.js +83 -0
  61. data/vendor/assets/javascripts/tesseract/test/tesseract-test.js +655 -0
  62. data/vendor/assets/javascripts/tesseract/test/version-test.js +16 -0
  63. metadata +63 -8
@@ -0,0 +1 @@
1
+ (function(a){function b(a){return a}function c(a,b){for(var c=0,d=b.length,e=new Array(d);c<d;++c)e[c]=a[b[c]];return e}function e(a){function b(b,c,d,e){while(d<e){var f=d+e>>1;a(b[f])<c?d=f+1:e=f}return d}function c(b,c,d,e){while(d<e){var f=d+e>>1;c<a(b[f])?e=f:d=f+1}return d}return c.right=c,c.left=b,c}function h(a){function b(a,b,c){var e=c-b,f=(e>>>1)+1;while(--f>0)d(a,f,e,b);return a}function c(a,b,c){var e=c-b,f;while(--e>0)f=a[b],a[b]=a[b+e],a[b+e]=f,d(a,1,e,b);return a}function d(b,c,d,e){var f=b[--e+c],g=a(f),h;while((h=c<<1)<=d){h<d&&a(b[e+h])>a(b[e+h+1])&&h++;if(g<=a(b[e+h]))break;b[e+c]=b[e+h],c=h}b[e+c]=f}return b.sort=c,b}function j(a){function c(c,d,e,f){var g=new Array(f=Math.min(e-d,f)),h,i,j,k;for(i=0;i<f;++i)g[i]=c[d++];b(g,0,f);if(d<e){h=a(g[0]);do if(j=a(k=c[d])>h)g[0]=k,h=a(b(g,0,f)[0]);while(++d<e)}return g}var b=h(a);return c}function l(a){function b(b,c,d){for(var e=c+1;e<d;++e){for(var f=e,g=b[e],h=a(g);f>c&&a(b[f-1])>h;--f)b[f]=b[f-1];b[f]=g}return b}return b}function n(a){function c(a,c,e){return(e-c<o?b:d)(a,c,e)}function d(b,d,e){var f=(e-d)/6|0,g=d+f,h=e-1-f,i=d+e-1>>1,j=i-f,k=i+f,l=b[g],m=a(l),n=b[j],o=a(n),p=b[i],q=a(p),r=b[k],s=a(r),u=b[h],v=a(u);m>o&&(t=l,l=n,n=t,t=m,m=o,o=t),s>v&&(t=r,r=u,u=t,t=s,s=v,v=t),m>q&&(t=l,l=p,p=t,t=m,m=q,q=t),o>q&&(t=n,n=p,p=t,t=o,o=q,q=t),m>s&&(t=l,l=r,r=t,t=m,m=s,s=t),q>s&&(t=p,p=r,r=t,t=q,q=s,s=t),o>v&&(t=n,n=u,u=t,t=o,o=v,v=t),o>q&&(t=n,n=p,p=t,t=o,o=q,q=t),s>v&&(t=r,r=u,u=t,t=s,s=v,v=t);var w=n,x=o,y=r,z=s;b[g]=l,b[j]=b[d],b[i]=p,b[k]=b[e-1],b[h]=u;var A=d+1,B=e-2,C=x<=z&&x>=z;if(C)for(var D=A;D<=B;++D){var E=b[D],F=a(E);if(F<x)D!==A&&(b[D]=b[A],b[A]=E),++A;else if(F>x)for(;;){var G=a(b[B]);if(G>x){B--;continue}if(G<x){b[D]=b[A],b[A++]=b[B],b[B--]=E;break}b[D]=b[B],b[B--]=E;break}}else for(var D=A;D<=B;D++){var E=b[D],F=a(E);if(F<x)D!==A&&(b[D]=b[A],b[A]=E),++A;else if(F>z)for(;;){var G=a(b[B]);if(G>z){B--;if(B<D)break;continue}G<x?(b[D]=b[A],b[A++]=b[B],b[B--]=E):(b[D]=b[B],b[B--]=E);break}}b[d]=b[A-1],b[A-1]=w,b[e-1]=b[B+1],b[B+1]=y,c(b,d,A-1),c(b,B+2,e);if(C)return b;if(A<g&&B>h){var H,G;while((H=a(b[A]))<=x&&H>=x)++A;while((G=a(b[B]))<=z&&G>=z)--B;for(var D=A;D<=B;D++){var E=b[D],F=a(E);if(F<=x&&F>=x)D!==A&&(b[D]=b[A],b[A]=E),A++;else if(F<=z&&F>=z)for(;;){var G=a(b[B]);if(G<=z&&G>=z){B--;if(B<D)break;continue}G<x?(b[D]=b[A],b[A++]=b[B],b[B--]=E):(b[D]=b[B],b[B--]=E);break}}}return c(b,A,B+1)}var b=l(a);return c}function v(a){return new Array(a)}function w(a,b){return function(c){var d=c.length;return[a.left(c,b,0,d),a.right(c,b,0,d)]}}function x(a,b){var c=b[0],d=b[1];return function(b){var e=b.length;return[a.left(b,c,0,e),a.left(b,d,0,e)]}}function y(a){return[0,a.length]}function z(){return null}function A(){return 0}function B(a){return a+1}function C(a){return a-1}function D(a){return function(b,c){return b+ +a(c)}}function E(a){return function(b,c){return b-a(c)}}function F(){function q(b){var c=f,d=b.length;return d&&(e=e.concat(b),l=s(l,f+=d),o.forEach(function(a){a(b,c,d)})),a}function r(a){function Q(b,d,e){F=b.map(a),J=K(H(e),0,e),F=c(F,J);var g=L(F),h=g[0],i=g[1],j;for(j=0;j<h;++j)l[J[j]+d]|=q;for(j=i;j<e;++j)l[J[j]+d]|=q;if(!d){t=F,v=J,O=h,P=i;return}var k=t,m=v,n=0,o=0;t=new Array(f),v=G(f,f);for(j=0;n<d&&o<e;++j)k[n]<F[o]?(t[j]=k[n],v[j]=m[n++]):(t[j]=F[o],v[j]=J[o++]+d);for(;n<d;++n,++j)t[j]=k[n],v[j]=m[n];for(;o<e;++o,++j)t[j]=F[o],v[j]=J[o]+d;g=L(t),O=g[0],P=g[1]}function R(a,b,c){N.forEach(function(a){a(F,J,b,c)}),F=J=null}function S(a){var b,c,d,e=a[0],f=a[1],g=[],h=[];if(e<O)for(b=e,c=Math.min(O,f);b<c;++b)l[d=v[b]]^=q,g.push(d);else if(e>O)for(b=O,c=Math.min(e,P);b<c;++b)l[d=v[b]]^=q,h.push(d);if(f>P)for(b=Math.max(e,P),c=f;b<c;++b)l[d=v[b]]^=q,g.push(d);else if(f<P)for(b=Math.max(O,f),c=P;b<c;++b)l[d=v[b]]^=q,h.push(d);return O=e,P=f,m.forEach(function(a){a(q,g,h)}),p}function T(a){return a==null?W():Array.isArray(a)?V(a):U(a)}function U(a){return S((L=w(d,a))(t))}function V(a){return S((L=x(d,a))(t))}function W(){return S((L=y)(t))}function X(a){var b=[],c=P,d;while(--c>=O&&a>0)l[d=v[c]]||(b.push(e[d]),--a);return b}function Y(a){function L(b,c,g,h){function N(){++o===n&&(p=u(p,k<<=1),i=u(i,k),n=I(k))}var j=d,p=G(o,n),q=x,t=F,v=o,w=0,y=0,A,B,C,D,E,L;K&&(q=t=z),d=new Array(o),o=0,i=v>1?s(i,f):G(f,n),v&&(C=(B=j[0]).key);while(y<h&&!((D=a(b[y]))>=D))++y;while(y<h){if(B&&C<=D){E=B,L=C,p[w]=o;if(B=j[++w])C=B.key}else E={key:D,value:t()},L=D;d[o]=E;while(!(D>L)){i[A=c[y]+g]=o,l[A]&r||(E.value=q(E.value,e[A]));if(++y>=h)break;D=a(b[y])}N()}while(w<v)d[p[w]=o]=j[w++],N();if(o>w)for(w=0;w<g;++w)i[w]=p[i[w]];A=m.indexOf(H),o>1?(H=M,J=P):(o===1?(H=O,J=Q):(H=z,J=z),i=null),m[A]=H}function M(a,b,c){if(a===q||K)return;var f,h,j;for(f=0,j=b.length;f<j;++f)l[h=b[f]]&r||(g=d[i[h]],g.value=x(g.value,e[h]));for(f=0,j=c.length;f<j;++f)(l[h=c[f]]&r)===a&&(g=d[i[h]],g.value=y(g.value,e[h]))}function O(a,b,c){if(a===q||K)return;var f,g,h,i=d[0];for(f=0,h=b.length;f<h;++f)l[g=b[f]]&r||(i.value=x(i.value,e[g]));for(f=0,h=c.length;f<h;++f)(l[g=c[f]]&r)===a&&(i.value=y(i.value,e[g]))}function P(){var a,b;for(a=0;a<o;++a)d[a].value=F();for(a=0;a<f;++a)l[a]&r||(b=d[i[a]],b.value=x(b.value,e[a]))}function Q(){var a,b=d[0];b.value=F();for(a=0;a<f;++a)l[a]&r||(b.value=x(b.value,e[a]))}function R(){return K&&(J(),K=!1),d}function S(a){var b=p(R(),0,d.length,a);return w.sort(b,0,b.length)}function T(a,b,d){return x=a,y=b,F=d,K=!0,c}function U(){return T(B,C,A)}function V(a){return T(D(a),E(a),A)}function W(a){function b(b){return a(b.value)}return p=j(b),w=h(b),c}function X(){return W(b)}function Y(){return o}var c={top:S,all:R,reduce:T,reduceCount:U,reduceSum:V,order:W,orderNatural:X,size:Y},d,i,k=8,n=I(k),o=0,p,w,x,y,F,H=z,J=z,K=!0;return arguments.length<1&&(a=b),m.push(H),N.push(L),L(t,v,0,f),U().orderNatural()}function Z(){var a=Y(z),b=a.all;return delete a.all,delete a.top,delete a.order,delete a.orderNatural,delete a.size,a.value=function(){return b()[0].value},a}var p={filter:T,filterExact:U,filterRange:V,filterAll:W,top:X,group:Y,groupAll:Z},q=1<<i++,r=~q,t,v,F,J,K=n(function(a){return F[a]}),L=y,N=[],O=0,P=0;return o.unshift(Q),o.push(R),i>k&&(l=u(l,k<<=1)),Q(e,0,f),R(e,0,f),p}function t(){function i(a,d,g){var i;if(h)return;for(i=d;i<f;++i)l[i]||(b=c(b,e[i]))}function j(a,f,g){var i,j,k;if(h)return;for(i=0,k=f.length;i<k;++i)l[j=f[i]]||(b=c(b,e[j]));for(i=0,k=g.length;i<k;++i)l[j=g[i]]===a&&(b=d(b,e[j]))}function k(){var a;b=g();for(a=0;a<f;++a)l[a]||(b=c(b,e[a]))}function n(b,e,f){return c=b,d=e,g=f,h=!0,a}function p(){return n(B,C,A)}function q(a){return n(D(a),E(a),A)}function r(){return h&&(k(),h=!1),b}var a={reduce:n,reduceCount:p,reduceSum:q,value:r},b,c,d,g,h=!0;return m.push(j),o.push(i),i(e,0,f),p()}function v(){return f}var a={add:q,dimension:r,groupAll:t,size:v},e=[],f=0,i=0,k=8,l=p(0),m=[],o=[];return arguments.length?q(arguments[0]):a}function G(a,b){return(b<257?p:b<65537?q:r)(a)}function H(a){var b=G(a,a);for(var c=-1;++c<a;)b[c]=c;return b}function I(a){return a===8?256:a===16?65536:4294967296}F.version="1.0.1",F.permute=c;var d=F.bisect=e(b);d.by=e;var f=F.heap=h(b);f.by=h;var i=F.heapselect=j(b);i.by=j;var k=F.insertionsort=l(b);k.by=l;var m=F.quicksort=n(b);m.by=n;var o=32,p=v,q=v,r=v,s=b,u=b;typeof Uint8Array!="undefined"&&(p=function(a){return new Uint8Array(a)},q=function(a){return new Uint16Array(a)},r=function(a){return new Uint32Array(a)},s=function(a,b){var c=new a.constructor(b);return c.set(a),c},u=function(a,b){var c;switch(b){case 16:c=q(a.length);break;case 32:c=r(a.length);break;default:throw new Error("invalid array width!")}return c.set(a),c}),a.tesseract=F})(this);
@@ -0,0 +1,177 @@
1
+ var tesseract = require("../"),
2
+ d3 = require("d3");
3
+
4
+ var then,
5
+ then2;
6
+
7
+ // Various generators for our synthetic dataset.
8
+ var firstSize = 9e4,
9
+ secondSize = 1e4,
10
+ totalSize = firstSize + secondSize,
11
+ randomDayOfWeek = randomIndex([0, .6, .7, .75, .8, .76, 0]),
12
+ randomHourOfDay = randomIndex([0, 0, 0, 0, 0, 0, 0, .2, .5, .7, .85, .9, .8, .69, .72, .8, .78, .7, .3, 0, 0, 0, 0, 0]),
13
+ randomDate = randomRecentDate(randomDayOfWeek, randomHourOfDay, 13),
14
+ randomAmount = randomLogNormal(2.5, .5),
15
+ randomPayment = function() { return {date: randomDate(), amount: randomAmount()}; };
16
+
17
+ // Various formatters to show our synthetic distributions.
18
+ var x = d3.scale.linear().rangeRound([0, 20]),
19
+ dayNames = ["S", "M", "T", "W", "T", "F", "S"],
20
+ formatNumber = d3.format(",.02r"),
21
+ formatInteger = d3.format("8d"),
22
+ formatDate = d3.time.format("%x"),
23
+ formatDay = function(i) { return dayNames[i]; };
24
+
25
+ // Create the synthetic records.
26
+ then = Date.now();
27
+ var paymentRecords = d3.range(totalSize).map(randomPayment);
28
+ console.log("Synthesizing " + formatNumber(totalSize) + " records: " + formatNumber(Date.now() - then) + "ms.");
29
+
30
+ // Slice the records into batches so we can measure incremental add.
31
+ var firstBatch = paymentRecords.slice(0, firstSize),
32
+ secondBatch = paymentRecords.slice(firstSize);
33
+
34
+ // Create the tesseract and relevant dimensions and groups.
35
+ then = then2 = Date.now();
36
+ var payments = tesseract(firstBatch),
37
+ all = payments.groupAll(),
38
+ amount = payments.dimension(function(d) { return d.amount; }),
39
+ amounts = amount.group(Math.floor),
40
+ date = payments.dimension(function(d) { return d.date; }),
41
+ dates = date.group(d3.time.day),
42
+ day = payments.dimension(function(d) { return d.date.getDay(); }),
43
+ days = day.group(),
44
+ hour = payments.dimension(function(d) { return d.date.getHours(); }),
45
+ hours = hour.group();
46
+ console.log("Indexing " + formatNumber(firstSize) + " records: " + formatNumber(Date.now() - then) + "ms.");
47
+
48
+ // Add the second batch incrementally.
49
+ then = Date.now();
50
+ payments.add(secondBatch);
51
+ console.log("Indexing " + formatNumber(secondSize) + " records: " + formatNumber(Date.now() - then) + "ms.");
52
+ console.log("Total indexing time: " + formatNumber(Date.now() - then2) + "ms.");
53
+ console.log("");
54
+
55
+ // Simulate filtering by dates.
56
+ then = Date.now();
57
+ var today = d3.time.day(new Date());
58
+ for (var i = 0, n = 90, k = 0; i < n; ++i) {
59
+ var ti = d3.time.day.offset(today, -i);
60
+ for (var j = 0; j < i; ++j) {
61
+ var tj = d3.time.day.offset(today, -j);
62
+ date.filterRange([ti, tj]);
63
+ updateDisplay();
64
+ }
65
+ }
66
+ console.log("Filtering by date: " + formatNumber((Date.now() - then) / k) + "ms/op.");
67
+ date.filterAll();
68
+
69
+ // Simulate filtering by day.
70
+ then = Date.now();
71
+ for (var i = 0, n = 7, k = 0; i < n; ++i) {
72
+ for (var j = i; j < n; ++j) {
73
+ day.filterRange([i, j]);
74
+ updateDisplay();
75
+ }
76
+ }
77
+ console.log("Filtering by day: " + formatNumber((Date.now() - then) / k) + "ms/op.");
78
+ day.filterAll();
79
+
80
+ // Simulate filtering by hour.
81
+ then = Date.now();
82
+ for (var i = 0, n = 24, k = 0; i < n; ++i) {
83
+ for (var j = i; j < n; ++j) {
84
+ hour.filterRange([i, j]);
85
+ updateDisplay();
86
+ }
87
+ }
88
+ console.log("Filtering by hour: " + formatNumber((Date.now() - then) / k) + "ms/op.");
89
+ hour.filterAll();
90
+
91
+ // Simulate filtering by amount.
92
+ then = Date.now();
93
+ for (var i = 0, n = 35, k = 0; i < n; ++i) {
94
+ for (var j = i; j < n; ++j) {
95
+ amount.filterRange([i, j]);
96
+ updateDisplay();
97
+ }
98
+ }
99
+ console.log("Filtering by amount: " + formatNumber((Date.now() - then) / k) + "ms/op.");
100
+ amount.filterAll();
101
+
102
+ console.log("");
103
+ console.log("Day of Week:");
104
+ x.domain([0, days.top(1)[0].value]);
105
+ days.all().forEach(function(g) {
106
+ console.log(" " + formatDay(g.key) + ": " + new Array(x(g.value) + 1).join("▇"));
107
+ });
108
+ console.log("");
109
+
110
+ console.log("Hour of Day:");
111
+ x.domain([0, hours.top(1)[0].value]);
112
+ hours.all().forEach(function(g) {
113
+ console.log(formatInteger(g.key) + ": " + new Array(x(g.value) + 1).join("▇"));
114
+ });
115
+ console.log("");
116
+
117
+ console.log("Date:");
118
+ x.domain([0, dates.top(1)[0].value]);
119
+ dates.all().forEach(function(g) {
120
+ console.log(formatDate(g.key) + ": " + new Array(x(g.value) + 1).join("▇"));
121
+ });
122
+ console.log("");
123
+
124
+ console.log("Amount:");
125
+ x.domain([0, amounts.top(1)[0].value]);
126
+ amounts.all().filter(function(g) { return x(g.value); }).forEach(function(g) {
127
+ console.log(formatInteger(g.key) + ": " + new Array(x(g.value) + 1).join("▇"));
128
+ });
129
+ console.log("");
130
+
131
+ // Simulates updating the display whenever the filters change.
132
+ function updateDisplay() {
133
+ dates.all(); // update the date chart
134
+ days.all(); // update the day-of-week chart
135
+ hours.all(); // update the hour-of-day chart
136
+ amounts.all(); // update the amount histogram
137
+ all.value(); // update the summary totals
138
+ date.top(40); // update the payment list
139
+ ++k; // count frame rate
140
+ }
141
+
142
+ // Returns a function that returns random index in [0, distribution.length -
143
+ // 1], based on the relative values in the specified distribution. Internally,
144
+ // the distribution is converted to a normalized cumulative distribution in
145
+ // [0, 1], and then a uniform random value is used with bisection.
146
+ function randomIndex(distribution) {
147
+ var k = 1 / d3.sum(distribution), s = 0;
148
+ for (var i = 0, n = distribution.length; i < n; ++i) {
149
+ s = (distribution[i] = distribution[i] * k + s);
150
+ }
151
+ return function() {
152
+ return d3.bisectLeft(distribution, Math.random());
153
+ };
154
+ }
155
+
156
+ // Returns a function that returns random values with a log-normal
157
+ // distribution, with the specified mean and deviation.
158
+ function randomLogNormal(µ, σ) {
159
+ var random = d3.random.normal();
160
+ return function() {
161
+ return Math.exp(µ + σ * random());
162
+ };
163
+ }
164
+
165
+ // Returns a function that returns random dates, built on top of the specified
166
+ // random day-of-week and hour-of-day generators. The minutes, seconds, and
167
+ // milliseconds of the return dates are uniform random; as is the week of the
168
+ // returned date, which is between now and some *weeks* ago.
169
+ function randomRecentDate(randomDayOfWeek, randomHourOfDay, weeks) {
170
+ var now = Date.now();
171
+ return function() {
172
+ var d = d3.time.week.offset(new Date(), -Math.floor(Math.random() * weeks));
173
+ d.setDate(d.getDate() + randomDayOfWeek() - d.getDay());
174
+ d.setHours(randomHourOfDay(), Math.random() * 60, Math.random() * 60, Math.random() * 1000);
175
+ return d;
176
+ };
177
+ }
@@ -0,0 +1,206 @@
1
+ var vows = require("vows"),
2
+ assert = require("assert"),
3
+ tesseract = require("../");
4
+
5
+ var suite = vows.describe("bisect");
6
+
7
+ suite.addBatch({
8
+ "bisect": {
9
+ topic: function() {
10
+ return tesseract.bisect;
11
+ },
12
+ "is the same as bisect.right": function(bisect) {
13
+ assert.strictEqual(bisect, bisect.right);
14
+ }
15
+ }
16
+ });
17
+
18
+ suite.addBatch({
19
+ "bisect.left": {
20
+ topic: function() {
21
+ return tesseract.bisect.left;
22
+ },
23
+ "finds the index of an exact match": function(bisect) {
24
+ var array = [1, 2, 3];
25
+ assert.equal(bisect(array, 1, 0, 3), 0);
26
+ assert.equal(bisect(array, 2, 0, 3), 1);
27
+ assert.equal(bisect(array, 3, 0, 3), 2);
28
+ },
29
+ "finds the index of the first match": function(bisect) {
30
+ var array = [1, 2, 2, 3];
31
+ assert.equal(bisect(array, 1, 0, 4), 0);
32
+ assert.equal(bisect(array, 2, 0, 4), 1);
33
+ assert.equal(bisect(array, 3, 0, 4), 3);
34
+ },
35
+ "finds the insertion point of a non-exact match": function(bisect) {
36
+ var array = [1, 2, 3];
37
+ assert.equal(bisect(array, 0.5, 0, 3), 0);
38
+ assert.equal(bisect(array, 1.5, 0, 3), 1);
39
+ assert.equal(bisect(array, 2.5, 0, 3), 2);
40
+ assert.equal(bisect(array, 3.5, 0, 3), 3);
41
+ },
42
+ "observes the lower bound": function(bisect) {
43
+ var array = [1, 2, 3, 4, 5];
44
+ assert.equal(bisect(array, 0, 2, 5), 2);
45
+ assert.equal(bisect(array, 1, 2, 5), 2);
46
+ assert.equal(bisect(array, 2, 2, 5), 2);
47
+ assert.equal(bisect(array, 3, 2, 5), 2);
48
+ assert.equal(bisect(array, 4, 2, 5), 3);
49
+ assert.equal(bisect(array, 5, 2, 5), 4);
50
+ assert.equal(bisect(array, 6, 2, 5), 5);
51
+ },
52
+ "observes the lower and upper bounds": function(bisect) {
53
+ var array = [1, 2, 3, 4, 5];
54
+ assert.equal(bisect(array, 0, 2, 3), 2);
55
+ assert.equal(bisect(array, 1, 2, 3), 2);
56
+ assert.equal(bisect(array, 2, 2, 3), 2);
57
+ assert.equal(bisect(array, 3, 2, 3), 2);
58
+ assert.equal(bisect(array, 4, 2, 3), 3);
59
+ assert.equal(bisect(array, 5, 2, 3), 3);
60
+ assert.equal(bisect(array, 6, 2, 3), 3);
61
+ }
62
+ }
63
+ });
64
+
65
+ suite.addBatch({
66
+ "bisect.by(value).left": {
67
+ topic: function() {
68
+ return tesseract.bisect.by(function(d) { return d.value; }).left;
69
+ },
70
+ "finds the index of an exact match": function(bisect) {
71
+ var array = [{value: 1}, {value: 2}, {value: 3}];
72
+ assert.equal(bisect(array, 1, 0, 3), 0);
73
+ assert.equal(bisect(array, 2, 0, 3), 1);
74
+ assert.equal(bisect(array, 3, 0, 3), 2);
75
+ },
76
+ "finds the index of the first match": function(bisect) {
77
+ var array = [{value: 1}, {value: 2}, {value: 2}, {value: 3}];
78
+ assert.equal(bisect(array, 1, 0, 4), 0);
79
+ assert.equal(bisect(array, 2, 0, 4), 1);
80
+ assert.equal(bisect(array, 3, 0, 4), 3);
81
+ },
82
+ "finds the insertion point of a non-exact match": function(bisect) {
83
+ var array = [{value: 1}, {value: 2}, {value: 3}];
84
+ assert.equal(bisect(array, 0.5, 0, 3), 0);
85
+ assert.equal(bisect(array, 1.5, 0, 3), 1);
86
+ assert.equal(bisect(array, 2.5, 0, 3), 2);
87
+ assert.equal(bisect(array, 3.5, 0, 3), 3);
88
+ },
89
+ "observes the lower bound": function(bisect) {
90
+ var array = [{value: 1}, {value: 2}, {value: 3}, {value: 4}, {value: 5}];
91
+ assert.equal(bisect(array, 0, 2, 5), 2);
92
+ assert.equal(bisect(array, 1, 2, 5), 2);
93
+ assert.equal(bisect(array, 2, 2, 5), 2);
94
+ assert.equal(bisect(array, 3, 2, 5), 2);
95
+ assert.equal(bisect(array, 4, 2, 5), 3);
96
+ assert.equal(bisect(array, 5, 2, 5), 4);
97
+ assert.equal(bisect(array, 6, 2, 5), 5);
98
+ },
99
+ "observes the lower and upper bounds": function(bisect) {
100
+ var array = [{value: 1}, {value: 2}, {value: 3}, {value: 4}, {value: 5}];
101
+ assert.equal(bisect(array, 0, 2, 3), 2);
102
+ assert.equal(bisect(array, 1, 2, 3), 2);
103
+ assert.equal(bisect(array, 2, 2, 3), 2);
104
+ assert.equal(bisect(array, 3, 2, 3), 2);
105
+ assert.equal(bisect(array, 4, 2, 3), 3);
106
+ assert.equal(bisect(array, 5, 2, 3), 3);
107
+ assert.equal(bisect(array, 6, 2, 3), 3);
108
+ }
109
+ }
110
+ });
111
+
112
+ suite.addBatch({
113
+ "bisect.right": {
114
+ topic: function() {
115
+ return tesseract.bisect.right;
116
+ },
117
+ "finds the index after an exact match": function(bisect) {
118
+ var array = [1, 2, 3];
119
+ assert.equal(bisect(array, 1, 0, 3), 1);
120
+ assert.equal(bisect(array, 2, 0, 3), 2);
121
+ assert.equal(bisect(array, 3, 0, 3), 3);
122
+ },
123
+ "finds the index after the last match": function(bisect) {
124
+ var array = [1, 2, 2, 3];
125
+ assert.equal(bisect(array, 1, 0, 4), 1);
126
+ assert.equal(bisect(array, 2, 0, 4), 3);
127
+ assert.equal(bisect(array, 3, 0, 4), 4);
128
+ },
129
+ "finds the insertion point of a non-exact match": function(bisect) {
130
+ var array = [1, 2, 3];
131
+ assert.equal(bisect(array, 0.5, 0, 3), 0);
132
+ assert.equal(bisect(array, 1.5, 0, 3), 1);
133
+ assert.equal(bisect(array, 2.5, 0, 3), 2);
134
+ assert.equal(bisect(array, 3.5, 0, 3), 3);
135
+ },
136
+ "observes the lower bound": function(bisect) {
137
+ var array = [1, 2, 3, 4, 5];
138
+ assert.equal(bisect(array, 0, 2, 5), 2);
139
+ assert.equal(bisect(array, 1, 2, 5), 2);
140
+ assert.equal(bisect(array, 2, 2, 5), 2);
141
+ assert.equal(bisect(array, 3, 2, 5), 3);
142
+ assert.equal(bisect(array, 4, 2, 5), 4);
143
+ assert.equal(bisect(array, 5, 2, 5), 5);
144
+ assert.equal(bisect(array, 6, 2, 5), 5);
145
+ },
146
+ "observes the lower and upper bounds": function(bisect) {
147
+ var array = [1, 2, 3, 4, 5];
148
+ assert.equal(bisect(array, 0, 2, 3), 2);
149
+ assert.equal(bisect(array, 1, 2, 3), 2);
150
+ assert.equal(bisect(array, 2, 2, 3), 2);
151
+ assert.equal(bisect(array, 3, 2, 3), 3);
152
+ assert.equal(bisect(array, 4, 2, 3), 3);
153
+ assert.equal(bisect(array, 5, 2, 3), 3);
154
+ assert.equal(bisect(array, 6, 2, 3), 3);
155
+ }
156
+ }
157
+ });
158
+
159
+ suite.addBatch({
160
+ "bisect.by(value).right": {
161
+ topic: function() {
162
+ return tesseract.bisect.by(function(d) { return d.value; }).right;
163
+ },
164
+ "finds the index after an exact match": function(bisect) {
165
+ var array = [{value: 1}, {value: 2}, {value: 3}];
166
+ assert.equal(bisect(array, 1, 0, 3), 1);
167
+ assert.equal(bisect(array, 2, 0, 3), 2);
168
+ assert.equal(bisect(array, 3, 0, 3), 3);
169
+ },
170
+ "finds the index after the last match": function(bisect) {
171
+ var array = [{value: 1}, {value: 2}, {value: 2}, {value: 3}];
172
+ assert.equal(bisect(array, 1, 0, 4), 1);
173
+ assert.equal(bisect(array, 2, 0, 4), 3);
174
+ assert.equal(bisect(array, 3, 0, 4), 4);
175
+ },
176
+ "finds the insertion point of a non-exact match": function(bisect) {
177
+ var array = [{value: 1}, {value: 2}, {value: 3}];
178
+ assert.equal(bisect(array, 0.5, 0, 3), 0);
179
+ assert.equal(bisect(array, 1.5, 0, 3), 1);
180
+ assert.equal(bisect(array, 2.5, 0, 3), 2);
181
+ assert.equal(bisect(array, 3.5, 0, 3), 3);
182
+ },
183
+ "observes the lower bound": function(bisect) {
184
+ var array = [{value: 1}, {value: 2}, {value: 3}, {value: 4}, {value: 5}];
185
+ assert.equal(bisect(array, 0, 2, 5), 2);
186
+ assert.equal(bisect(array, 1, 2, 5), 2);
187
+ assert.equal(bisect(array, 2, 2, 5), 2);
188
+ assert.equal(bisect(array, 3, 2, 5), 3);
189
+ assert.equal(bisect(array, 4, 2, 5), 4);
190
+ assert.equal(bisect(array, 5, 2, 5), 5);
191
+ assert.equal(bisect(array, 6, 2, 5), 5);
192
+ },
193
+ "observes the lower and upper bounds": function(bisect) {
194
+ var array = [{value: 1}, {value: 2}, {value: 3}, {value: 4}, {value: 5}];
195
+ assert.equal(bisect(array, 0, 2, 3), 2);
196
+ assert.equal(bisect(array, 1, 2, 3), 2);
197
+ assert.equal(bisect(array, 2, 2, 3), 2);
198
+ assert.equal(bisect(array, 3, 2, 3), 3);
199
+ assert.equal(bisect(array, 4, 2, 3), 3);
200
+ assert.equal(bisect(array, 5, 2, 3), 3);
201
+ assert.equal(bisect(array, 6, 2, 3), 3);
202
+ }
203
+ }
204
+ });
205
+
206
+ suite.export(module);
@@ -0,0 +1,44 @@
1
+ var vows = require("vows"),
2
+ assert = require("assert"),
3
+ tesseract = require("../");
4
+
5
+ var suite = vows.describe("heap");
6
+
7
+ suite.addBatch({
8
+ "heap": {
9
+ topic: function() {
10
+ return tesseract.heap;
11
+ },
12
+ "children are greater than or equal to parents": function(heap) {
13
+ var array = [6, 5, 3, 1, 8, 7, 2, 4]
14
+ n = array.length;
15
+ assert.strictEqual(heap(array, 0, n), array);
16
+ assert.equal(array[0], 1);
17
+ for (var i = 1; i < n; ++i) assert(array[i] >= array[i - 1 >> 1]);
18
+ },
19
+ "creates a heap from a subset of the array": function(heap) {
20
+ var array = [6, 5, 3, 1, 8, 7, 2, 4]
21
+ n = 6;
22
+ assert.strictEqual(heap(array, 0, n), array);
23
+ assert.equal(array[0], 1);
24
+ for (var i = 1; i < n; ++i) assert(array[i] >= array[i - 1 >> 1]);
25
+ },
26
+
27
+ "sort": {
28
+ "sorts an existing heap in descending order": function(heap) {
29
+ var array = [1, 4, 2, 5, 8, 7, 3, 6],
30
+ n = array.length;
31
+ heap.sort(array, 0, n);
32
+ assert.deepEqual(array, [8, 7, 6, 5, 4, 3, 2, 1]);
33
+ },
34
+ "sorts a two-element heap in descending order": function(heap) {
35
+ var array = [1, 4],
36
+ n = array.length;
37
+ heap.sort(array, 0, n);
38
+ assert.deepEqual(array, [4, 1]);
39
+ }
40
+ }
41
+ }
42
+ });
43
+
44
+ suite.export(module);
@@ -0,0 +1,51 @@
1
+ var vows = require("vows"),
2
+ assert = require("assert"),
3
+ tesseract = require("../");
4
+
5
+ var suite = vows.describe("permute");
6
+
7
+ suite.addBatch({
8
+ "permute": {
9
+ topic: function() {
10
+ return tesseract.permute;
11
+ },
12
+ "permutes according to the specified index": function(permute) {
13
+ assert.deepEqual(permute([3, 4, 5], [2, 1, 0]), [5, 4, 3]);
14
+ assert.deepEqual(permute([3, 4, 5], [2, 0, 1]), [5, 3, 4]);
15
+ assert.deepEqual(permute([3, 4, 5], [0, 1, 2]), [3, 4, 5]);
16
+ },
17
+ "does not modify the input array": function(permute) {
18
+ var input = [3, 4, 5];
19
+ permute(input, [2, 1, 0]);
20
+ assert.deepEqual(input, [3, 4, 5]);
21
+ },
22
+ "can duplicate input values": function(permute) {
23
+ assert.deepEqual(permute([3, 4, 5], [0, 1, 0]), [3, 4, 3]);
24
+ assert.deepEqual(permute([3, 4, 5], [2, 2, 2]), [5, 5, 5]);
25
+ assert.deepEqual(permute([3, 4, 5], [0, 1, 1]), [3, 4, 4]);
26
+ },
27
+ "can return more elements": function(permute) {
28
+ assert.deepEqual(permute([3, 4, 5], [0, 0, 1, 2]), [3, 3, 4, 5]);
29
+ assert.deepEqual(permute([3, 4, 5], [0, 1, 1, 1]), [3, 4, 4, 4]);
30
+ },
31
+ "can return fewer elements": function(permute) {
32
+ assert.deepEqual(permute([3, 4, 5], [0]), [3]);
33
+ assert.deepEqual(permute([3, 4, 5], [1, 2]), [4, 5]);
34
+ assert.deepEqual(permute([3, 4, 5], []), []);
35
+ },
36
+ "can return undefined elements": function(permute) {
37
+ var v1 = permute([3, 4, 5], [10]);
38
+ assert.equal(v1.length, 1);
39
+ assert.isUndefined(v1[0]);
40
+ var v2 = permute([3, 4, 5], [-1]);
41
+ assert.equal(v2.length, 1);
42
+ assert.isUndefined(v2[0]);
43
+ var v3 = permute([3, 4, 5], [0, -1]);
44
+ assert.equal(v3.length, 2);
45
+ assert.equal(v3[0], 3);
46
+ assert.isUndefined(v3[1]);
47
+ }
48
+ }
49
+ });
50
+
51
+ suite.export(module);