d3_rails 2.8.0 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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);