@live-change/flatten-interval-tree 0.8.26

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 (65) hide show
  1. package/.babelrc +8 -0
  2. package/.travis.yml +14 -0
  3. package/LICENSE +21 -0
  4. package/README.md +172 -0
  5. package/dist/main.cjs.js +799 -0
  6. package/dist/main.esm.js +794 -0
  7. package/dist/main.umd.js +805 -0
  8. package/docs/Interval.html +1609 -0
  9. package/docs/IntervalTree.html +1506 -0
  10. package/docs/classes_interval.js.html +173 -0
  11. package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  12. package/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
  13. package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  14. package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  15. package/docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  16. package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  17. package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  18. package/docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
  19. package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  20. package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
  21. package/docs/fonts/OpenSans-Light-webfont.svg +1831 -0
  22. package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
  23. package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  24. package/docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  25. package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  26. package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  27. package/docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
  28. package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  29. package/docs/fonts/OpenSans-Semibold-webfont.eot +0 -0
  30. package/docs/fonts/OpenSans-Semibold-webfont.svg +1830 -0
  31. package/docs/fonts/OpenSans-Semibold-webfont.ttf +0 -0
  32. package/docs/fonts/OpenSans-Semibold-webfont.woff +0 -0
  33. package/docs/fonts/OpenSans-SemiboldItalic-webfont.eot +0 -0
  34. package/docs/fonts/OpenSans-SemiboldItalic-webfont.svg +1830 -0
  35. package/docs/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
  36. package/docs/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
  37. package/docs/index.html +197 -0
  38. package/docs/index.js.html +624 -0
  39. package/docs/interval.js.html +184 -0
  40. package/docs/intervalTree.js.html +624 -0
  41. package/docs/scripts/linenumber.js +25 -0
  42. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  43. package/docs/scripts/prettify/lang-css.js +2 -0
  44. package/docs/scripts/prettify/prettify.js +28 -0
  45. package/docs/styles/jsdoc-default.css +692 -0
  46. package/docs/styles/prettify-jsdoc.css +111 -0
  47. package/docs/styles/prettify-tomorrow.css +132 -0
  48. package/examples/browser/index.html +49 -0
  49. package/examples/create-react-app/package.json +15 -0
  50. package/examples/create-react-app/public/index.html +11 -0
  51. package/examples/create-react-app/src/App.js +38 -0
  52. package/examples/create-react-app/src/ComposersList.js +15 -0
  53. package/examples/create-react-app/src/index.js +5 -0
  54. package/examples/es6-module/index.html +50 -0
  55. package/examples/nodejs/index.js +23 -0
  56. package/index.d.ts +65 -0
  57. package/index.js +6 -0
  58. package/package.json +52 -0
  59. package/rollup.config.js +21 -0
  60. package/src/classes/interval.js +131 -0
  61. package/src/classes/intervalTree.js +564 -0
  62. package/src/classes/node.js +97 -0
  63. package/src/utils/constants.js +16 -0
  64. package/test/intervalTree.js +232 -0
  65. package/test/node.js +64 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Created by Alex Bol on 4/1/2017.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ import Interval from './interval.js';
8
+ import {RB_TREE_COLOR_RED, RB_TREE_COLOR_BLACK} from '../utils/constants.js';
9
+
10
+ function min(a,b) {
11
+ return a < b ? a : b
12
+ }
13
+ function max(a,b) {
14
+ return a > b ? a : b
15
+ }
16
+
17
+ class Node {
18
+ constructor(key = undefined, value = undefined,
19
+ left = null, right = null, parent = null, color = RB_TREE_COLOR_BLACK) {
20
+ this.left = left; // reference to left child node
21
+ this.right = right; // reference to right child node
22
+ this.parent = parent; // reference to parent node
23
+ this.color = color;
24
+
25
+ this.item = {key: key, value: value}; // key is supposed to be instance of Interval
26
+
27
+ /* If not, this should by an array of two numbers */
28
+ if (key && key instanceof Array && key.length == 2) {
29
+ this.item.key = new Interval(min(key[0], key[1]), max(key[0], key[1]));
30
+ }
31
+ this.max = this.item.key ? this.item.key.max : undefined;
32
+ }
33
+
34
+ isNil() {
35
+ return (this.item.key === undefined && this.item.value === undefined &&
36
+ this.left === null && this.right === null && this.color === RB_TREE_COLOR_BLACK);
37
+ }
38
+
39
+ less_than(other_node) {
40
+ if (this.item.value && other_node.item.value) {
41
+ let item_less_than = this.item.value.less_than ? this.item.value.less_than(other_node.item.value) :
42
+ this.item.value < other_node.item.value;
43
+ return this.item.key.less_than(other_node.item.key) ||
44
+ this.item.key.equal_to((other_node.item.key)) && item_less_than;
45
+ }
46
+ else {
47
+ return this.item.key.less_than(other_node.item.key);
48
+ }
49
+ }
50
+
51
+ equal_to(other_node) {
52
+ let value_equal = true;
53
+ if (this.item.value && other_node.item.value) {
54
+ value_equal = this.item.value.equal_to ? this.item.value.equal_to(other_node.item.value) :
55
+ this.item.value == other_node.item.value;
56
+ }
57
+ return this.item.key.equal_to(other_node.item.key) && value_equal;
58
+ }
59
+
60
+ intersect(other_node) {
61
+ return this.item.key.intersect(other_node.item.key);
62
+ }
63
+
64
+ copy_data(other_node) {
65
+ this.item.key = other_node.item.key.clone();
66
+ this.item.value = other_node.item.value;
67
+ }
68
+
69
+ update_max() {
70
+ // use key (Interval) max property instead of key.high
71
+ this.max = this.item.key ? this.item.key.max : undefined;
72
+ if (this.right && this.right.max) {
73
+ const comparable_max = this.item.key.constructor.comparable_max; // static method
74
+ this.max = comparable_max(this.max, this.right.max);
75
+ }
76
+ if (this.left && this.left.max) {
77
+ const comparable_max = this.item.key.constructor.comparable_max; // static method
78
+ this.max = comparable_max(this.max, this.left.max);
79
+ }
80
+ }
81
+
82
+ // Other_node does not intersect any node of left subtree, if this.left.max < other_node.item.key.low
83
+ not_intersect_left_subtree(search_node) {
84
+ const comparable_less_than = this.item.key.constructor.comparable_less_than; // static method
85
+ let high = this.left.max.high !== undefined ? this.left.max.high : this.left.max;
86
+ return comparable_less_than(high, search_node.item.key.low);
87
+ }
88
+
89
+ // Other_node does not intersect right subtree if other_node.item.key.high < this.right.key.low
90
+ not_intersect_right_subtree(search_node) {
91
+ const comparable_less_than = this.item.key.constructor.comparable_less_than; // static method
92
+ let low = this.right.max.low !== undefined ? this.right.max.low : this.right.item.key.low;
93
+ return comparable_less_than(search_node.item.key.high, low);
94
+ }
95
+ };
96
+
97
+ export default Node;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Created by Alex Bol on 3/28/2017.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ // module.exports = {
8
+ // RB_TREE_COLOR_RED: 0,
9
+ // RB_TREE_COLOR_BLACK: 1
10
+ // };
11
+
12
+ const RB_TREE_COLOR_RED = 0;
13
+ const RB_TREE_COLOR_BLACK = 1;
14
+
15
+ export { RB_TREE_COLOR_RED, RB_TREE_COLOR_BLACK }
16
+
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Created by Alex Bol on 3/31/2017.
3
+ */
4
+
5
+ import { expect } from 'chai';
6
+ import IntervalTree from '../index';
7
+ import {Interval} from "../index";
8
+
9
+ // import IntervalTree from '../dist/interval-tree.esm';
10
+
11
+ describe('#IntervalTree', function() {
12
+ it('Create new instanse of IntervalTree ', function () {
13
+ let tree = new IntervalTree();
14
+ expect(tree).to.be.an.instanceof(IntervalTree);
15
+ });
16
+ it('Size of empty tree will be 0', function () {
17
+ let tree = new IntervalTree();
18
+ expect(tree.size).to.equal(0);
19
+ });
20
+ it('May insert one entry with key - array of numbers', function () {
21
+ let tree = new IntervalTree();
22
+ tree.insert([1,2]);
23
+ expect(tree.size).to.equal(1);
24
+ });
25
+ it('May insert many entries with key - array of numbers', function () {
26
+ let tree = new IntervalTree();
27
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
28
+ for (let int of ints) tree.insert(int);
29
+ expect(tree.size).to.equal(5);
30
+ });
31
+ it('May insert entries while transforming numeric pair into Interval', function () {
32
+ let tree = new IntervalTree();
33
+ let pairs = [[6,8],[1,4],[5,12],[1,1],[5,7]];
34
+ for (let pair of pairs) tree.insert(new Interval(pair[0], pair[1]));
35
+ expect(tree.size).to.equal(5);
36
+ expect(tree.keys).to.deep.equal([[1,1],[1,4],[5,7],[5,12],[6,8]]);
37
+ });
38
+ it('May return array of keys sorted', function () {
39
+ let tree = new IntervalTree();
40
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
41
+ for (let int of ints) tree.insert(int);
42
+ expect(tree.keys).to.deep.equal([[1,1],[1,4],[5,7],[5,12],[6,8]]);
43
+ });
44
+ it('May test if node entry exist after insertion', function () {
45
+ let tree = new IntervalTree();
46
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
47
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
48
+ expect(tree.keys).to.deep.equal([[1,1],[1,4],[5,7],[5,12],[6,8]]);
49
+ for (let i=0; i < ints.length; i++) {
50
+ expect(tree.exist(ints[i], "val"+i)).to.equal(true);
51
+ }
52
+ });
53
+ it('May not find value when key was not inserted', function () {
54
+ let tree = new IntervalTree();
55
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
56
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
57
+ expect(tree.exist([2,4],"val")).to.be.false; // wrong interval
58
+ expect(tree.exist([1,4],"val2")).to.be.false; // wrong value
59
+ });
60
+ it('May not find entry after key was deleted', function () {
61
+ let tree = new IntervalTree();
62
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
63
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
64
+ tree.remove([1,4],"val1");
65
+
66
+ expect(tree.size).to.equal(4);
67
+ expect(tree.keys).to.deep.equal([[1,1],[5,7],[5,12],[6,8]]);
68
+ expect(tree.exist([1,4])).to.be.false;
69
+ });
70
+ it('May become empty after all entries will be deleted', function () {
71
+ let tree = new IntervalTree();
72
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
73
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
74
+ tree.remove([6,8],"val0");
75
+ tree.remove([1,4],"val1");
76
+ tree.remove([5,12],"val2");
77
+ tree.remove([1,1],"val3");
78
+ tree.remove([5,7],"val4");
79
+
80
+ expect(tree.size).to.equal(0);
81
+ expect(tree.isEmpty()).to.be.true;
82
+ });
83
+ it('May return array of items', function () {
84
+ let tree = new IntervalTree();
85
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
86
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
87
+
88
+ let items = tree.items;
89
+ let keys = [];
90
+ for (let item of items) {
91
+ keys.push(item)
92
+ }
93
+ expect(items.length).to.equal(5);
94
+ expect(keys.length).to.equal(5);
95
+ expect(tree.keys).to.deep.equal([[1,1],[1,4],[5,7],[5,12],[6,8]]);
96
+ });
97
+ it('May transform tree to another tree using map', function () {
98
+ let tree1 = new IntervalTree();
99
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
100
+ for (let i=0; i < ints.length; i++) tree1.insert(ints[i],"val"+i);
101
+
102
+ let tree2 = tree1.map( (value, key) => (key.high-key.low) );
103
+
104
+ expect(tree2.size).to.equal(5);
105
+ expect(tree2.keys).to.deep.equal([[1,1],[1,4],[5,7],[5,12],[6,8]]);
106
+ expect(tree2.values).to.deep.equal([0,3,2,7,2]);
107
+ });
108
+
109
+ it('May search interval and return array of values', function () {
110
+ let tree = new IntervalTree();
111
+ let ints = [[6,8],[1,4],[5,12],[1,1],[5,7]];
112
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
113
+ expect(tree.search([2,3])).to.deep.equal(['val1']);
114
+ });
115
+ it('May search interval and return array of custom transformed objects', function () {
116
+ const composers = [
117
+ {name: "Ludwig van Beethoven", period: [1770,1827]},
118
+ {name: "Johann Sebastian Bach", period: [1685, 1750]},
119
+ {name: "Wolfgang Amadeus Mozart", period: [1756, 1791]},
120
+ {name: "Johannes Brahms", period: [1833, 1897]},
121
+ {name: "Richard Wagner", period: [1813, 1883]},
122
+ {name: "Claude Debussy", period: [1862, 1918]},
123
+ {name: "Pyotr Ilyich Tchaikovsky", period: [1840, 1893]},
124
+ {name: "Frédéric Chopin", period: [1810, 1849]},
125
+ {name: "Joseph Haydn", period: [1732, 1809]},
126
+ {name: "Antonio Vivaldi", period: [1678, 1741]}
127
+ ];
128
+ const tree = new IntervalTree();
129
+ for (let composer of composers)
130
+ tree.insert(composer.period, composer.name);
131
+
132
+ const searchRes = tree.search( [1600,1700],
133
+ (name, period) => {return `${name} (${period.low}-${period.high})`});
134
+ expect(searchRes.length).to.equal(2);
135
+ expect(searchRes[0]).to.equal("Antonio Vivaldi (1678-1741)");
136
+ expect(searchRes[1]).to.equal("Johann Sebastian Bach (1685-1750)");
137
+ });
138
+ it('May return empty array when search interval does not intersect any', function () {
139
+ let tree = new IntervalTree();
140
+ let ints = [[6,8],[1,2],[7,12],[1,1],[5,7]];
141
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
142
+ expect(tree.search([3,4])).to.deep.equal([]);
143
+ });
144
+ it('Each red node has exactly two black child nodes', function () {
145
+ let tree = new IntervalTree();
146
+ let ints = [[6,8],[1,2],[7,12],[1,1],[5,7]];
147
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
148
+ expect(tree.testRedBlackProperty()).to.equal(true);
149
+ });
150
+ it('Each path from root to nil node has same black height', function () {
151
+ let tree = new IntervalTree();
152
+ let ints = [[6,8],[1,2],[7,12],[1,1],[5,7]];
153
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
154
+ let height = (tree) => {
155
+ return tree.testBlackHeightProperty(tree.root);
156
+ };
157
+ expect(height(tree)).to.equal(3);
158
+ });
159
+ it('Same black height property preserved while nodes deleted', function () {
160
+ let tree = new IntervalTree();
161
+ let ints = [[6,8],[1,2],[7,12],[1,1],[5,7]];
162
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
163
+ let height = (tree) => {
164
+ return tree.testBlackHeightProperty(tree.root);
165
+ };
166
+ let h;
167
+ tree.remove([1,1],"val3");
168
+ // h = height(tree);
169
+ expect(height(tree)).to.equal(3);
170
+ expect(tree.testRedBlackProperty()).to.equal(true);
171
+
172
+ tree.remove([5,7],"val4");
173
+ expect(height(tree)).to.equal(3);
174
+ expect(tree.testRedBlackProperty()).to.equal(true);
175
+
176
+ tree.remove([1,2],"val1");
177
+ expect(tree.testRedBlackProperty()).to.equal(true);
178
+ expect(height(tree)).to.equal(2);
179
+
180
+ tree.remove([6,8],"val0");
181
+ expect(tree.testRedBlackProperty()).to.equal(true);
182
+ expect(height(tree)).to.equal(2);
183
+
184
+ tree.remove([7,12],"val2");
185
+ expect(tree.testRedBlackProperty()).to.equal(true);
186
+ });
187
+ it("Fix issue #9", function() {
188
+ function setupTreeAndSearch(intervals, searchInterval) {
189
+ let tree = new IntervalTree();
190
+
191
+ for (let i=0; i < intervals.length; i++) {
192
+ tree.insert(intervals[i],"val"+i);
193
+ }
194
+
195
+ return tree.search(searchInterval);
196
+ }
197
+
198
+ let resp1 = setupTreeAndSearch(
199
+ [[1,1], [1,4], [5,6], [5.5,7], [7,8]],
200
+ [5.5, 5.7]
201
+ );
202
+ expect(resp1).to.be.deep.equal(["val2", "val3"]);
203
+
204
+ let resp2 = setupTreeAndSearch(
205
+ [[1,1], [1,4], [5,6], [6,7], [7,8]],
206
+ [5.5, 5.7]
207
+ );
208
+ expect(resp2).to.be.deep.equal(["val2"]);
209
+ });
210
+ it('Low or high can be 0', function () {
211
+ let tree = new IntervalTree();
212
+ let ints = [[0,0],[0,0],[1,1],[0,0]];
213
+ for (let i=0; i < ints.length; i++) tree.insert(ints[i],"val"+i);
214
+ expect(tree.search([0,0])).to.deep.equal(['val0','val1','val3']);
215
+ });
216
+ it("Fix issue #15 Unable to remove/find some of the nodes", function() {
217
+ const intervalTree3 = new IntervalTree();
218
+
219
+ intervalTree3.insert([2, 5], 10);
220
+ intervalTree3.insert([2, 5], 20);
221
+ intervalTree3.insert([2, 5], 30);
222
+ intervalTree3.insert([2, 5], 40);
223
+ intervalTree3.insert([2, 5], 50);
224
+
225
+ expect(intervalTree3.exist([2, 5], 10)).to.be.true;
226
+ expect(intervalTree3.exist([2, 5], 20)).to.be.true;
227
+ expect(intervalTree3.exist([2, 5], 30)).to.be.true;
228
+ expect(intervalTree3.exist([2, 5], 40)).to.be.true;
229
+ expect(intervalTree3.exist([2, 5], 50)).to.be.true;
230
+ expect(intervalTree3.exist([2, 5], 25)).to.be.false;
231
+ });
232
+ });
package/test/node.js ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Created by Alex Bol on 3/30/2017.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ import { expect } from 'chai';
8
+ import Node from '../src/classes/node';
9
+
10
+ describe('#RedBlackTree Node', function() {
11
+ it('Node class exist when required', function () {
12
+ expect(Node).to.exist;
13
+ });
14
+ it('Node class required without traits has default traits defined', function () {
15
+ expect(Node.prototype.less_than).to.be.a('function');
16
+ expect(Node.prototype.equal_to).to.be.a('function');
17
+ expect(Node.prototype.copy_data).to.be.a('function');
18
+ expect(Node.prototype.update_max).to.be.a('function');
19
+ });
20
+ it('May create new default instance of Node', function () {
21
+ let node = new Node();
22
+ expect(node).to.be.an.instanceof(Node);
23
+ });
24
+ it('May create new instance of Node', function () {
25
+ let node = new Node([1,3], "1");
26
+ expect(node.item).to.be.deep.equal({key:{low:1, high:3}, value:"1"});
27
+ });
28
+ it('May compare intervals: [0,1] less than [1,3]', function () {
29
+ let node1 = new Node([0,1]);
30
+ let node2 = new Node([1,3]);
31
+ expect(node1.less_than(node2)).to.equal(true);
32
+ });
33
+ it('May compare intervals: [0,5] less than [1,3]', function () {
34
+ let node1 = new Node([0,5]);
35
+ let node2 = new Node([1,3]);
36
+ expect(node1.less_than(node2)).to.equal(true);
37
+ });
38
+ it('May compare intervals: [0,2] less than [0,3]', function () {
39
+ let node1 = new Node([0,2]);
40
+ let node2 = new Node([0,3]);
41
+ expect(node1.less_than(node2)).to.equal(true);
42
+ });
43
+ it('May compare intervals: [1,4] is not less than [0,3]', function () {
44
+ let node1 = new Node([1,4]);
45
+ let node2 = new Node([0,3]);
46
+ expect(node1.less_than(node2)).to.equal(false);
47
+ });
48
+ it('May compare intervals: [1,4] is not equal to [0,3]', function () {
49
+ let node1 = new Node([1,4]);
50
+ let node2 = new Node([0,3]);
51
+ expect(node1.equal_to(node2)).to.equal(false);
52
+ });
53
+ it('May compare intervals: [0,3] equal to [0,3]', function () {
54
+ let node1 = new Node([0,3]);
55
+ let node2 = new Node([0,3]);
56
+ expect(node1.equal_to(node2)).to.equal(true);
57
+ });
58
+ it('May compare {key, value}: {[0,3], "1"} is not equal to {[0,3], "2"', function () {
59
+ let node1 = new Node([0,3],"1");
60
+ let node2 = new Node([0,3], "2");
61
+ expect(node1.equal_to(node2)).to.equal(false);
62
+ });
63
+ });
64
+