@teselagen/range-utils 0.1.21 → 0.1.23

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 (90) hide show
  1. package/index.js +6542 -18010
  2. package/index.mjs +6593 -18007
  3. package/index.umd.js +6836 -18306
  4. package/package.json +3 -2
  5. package/src/adjustRangeToDeletionOfAnotherRange.js +53 -0
  6. package/src/adjustRangeToDeletionOfAnotherRange.test.js +107 -0
  7. package/src/adjustRangeToInsert.js +28 -0
  8. package/src/adjustRangeToInsert.test.js +111 -0
  9. package/src/adjustRangeToRotation.js +24 -0
  10. package/src/adjustRangeToRotation.test.js +123 -0
  11. package/src/checkIfNonCircularRangesOverlap.js +30 -0
  12. package/src/checkIfNonCircularRangesOverlap.test.js +45 -0
  13. package/src/checkIfPotentiallyCircularRangesOverlap.js +16 -0
  14. package/src/checkIfPotentiallyCircularRangesOverlap.test.js +73 -0
  15. package/src/collapseOverlapsGeneratedFromRangeComparisonIfPossible.js +47 -0
  16. package/src/collapseOverlapsGeneratedFromRangeComparisonIfPossible.test.js +124 -0
  17. package/src/convertRangeIndices.js +22 -0
  18. package/src/convertRangeIndices.test.js +22 -0
  19. package/src/convertRangeTo0Based.js +5 -0
  20. package/src/convertRangeTo1Based.js +5 -0
  21. package/src/doesRangeSpanEntireSequence.js +7 -0
  22. package/src/doesRangeSpanOrigin.js +3 -0
  23. package/src/expandOrContractCircularRangeToPosition.js +41 -0
  24. package/src/expandOrContractNonCircularRangeToPosition.js +25 -0
  25. package/src/expandOrContractRangeByLength.js +12 -0
  26. package/src/expandOrContractRangeByLength.test.js +77 -0
  27. package/src/expandOrContractRangeToPosition.js +10 -0
  28. package/src/flipContainedRange.js +85 -0
  29. package/src/flipContainedRange.test.js +124 -0
  30. package/src/generateRandomRange.js +20 -0
  31. package/src/generateRandomRange.test.js +24 -0
  32. package/src/getAnnotationRangeType.js +24 -0
  33. package/src/getAnnotationRangeType.test.js +59 -0
  34. package/src/getEachPositionInRangeAsArray.js +15 -0
  35. package/src/getEachPositionInRangeAsArray.test.js +9 -0
  36. package/src/getLengthOfOverlappingRegionsBetweenTwoRanges.js +9 -0
  37. package/src/getLengthOfOverlappingRegionsBetweenTwoRanges.test.js +24 -0
  38. package/src/getMiddleOfRange.js +10 -0
  39. package/src/getMiddleOfRange.test.js +44 -0
  40. package/src/getOverlapOfNonCircularRanges.js +35 -0
  41. package/src/getOverlapsOfPotentiallyCircularRanges.js +54 -0
  42. package/src/getOverlapsOfPotentiallyCircularRanges.test.js +199 -0
  43. package/src/getPositionFromAngle.js +7 -0
  44. package/src/getRangeAngles.js +33 -0
  45. package/src/getRangeAngles.test.js +77 -0
  46. package/src/getRangeLength.js +14 -0
  47. package/src/getRangeLength.test.js +30 -0
  48. package/src/getRangesBetweenTwoRanges.js +28 -0
  49. package/src/getSequenceWithinRange.js +17 -0
  50. package/src/getSequenceWithinRange.test.js +49 -0
  51. package/src/getShortestDistanceBetweenTwoPositions.js +12 -0
  52. package/src/getShortestDistanceBetweenTwoPositions.test.js +14 -0
  53. package/src/getYOffsetForPotentiallyCircularRange.js +24 -0
  54. package/src/getYOffsetsForPotentiallyCircularRanges.js +20 -0
  55. package/src/getYOffsetsForPotentiallyCircularRanges.test.js +29 -0
  56. package/src/getZeroedRangeOverlaps.js +17 -0
  57. package/src/getZeroedRangeOverlaps.test.js +36 -0
  58. package/src/index.js +51 -0
  59. package/src/index.test.js +33 -0
  60. package/src/invertRange.js +21 -0
  61. package/src/invertRange.test.js +96 -0
  62. package/src/isPositionCloserToRangeStartThanRangeEnd.js +8 -0
  63. package/src/isPositionCloserToRangeStartThanRangeEnd.test.js +17 -0
  64. package/src/isPositionWithinRange.js +31 -0
  65. package/src/isRangeOrPositionWithinRange.js +29 -0
  66. package/src/isRangeOrPositionWithinRange.test.js +150 -0
  67. package/src/isRangeWithinRange.js +17 -0
  68. package/src/loopEachPositionInRange.js +5 -0
  69. package/src/modulatePositionByRange.js +10 -0
  70. package/src/modulatePositionByRange.test.js +12 -0
  71. package/src/modulateRangeBySequenceLength.js +11 -0
  72. package/src/modulateRangeBySequenceLength.test.js +16 -0
  73. package/src/normalizePositionByRangeLength.js +20 -0
  74. package/src/normalizePositionByRangeLength.test.js +23 -0
  75. package/src/normalizePositionByRangeLength1Based.js +5 -0
  76. package/src/normalizePositionByRangeLength1Based.test.js +9 -0
  77. package/src/normalizeRange.js +11 -0
  78. package/src/normalizeRange.test.js +9 -0
  79. package/src/provideInclusiveOptions.js +26 -0
  80. package/src/reversePositionInRange.js +13 -0
  81. package/src/splitRangeIntoTwoPartsIfItIsCircular.js +31 -0
  82. package/src/splitRangeIntoTwoPartsIfItIsCircular.test.js +33 -0
  83. package/src/translateRange.js +9 -0
  84. package/src/translateRange.test.js +20 -0
  85. package/src/trimNonCicularRangeByAnotherNonCircularRange.js +57 -0
  86. package/src/trimNumberToFitWithin0ToAnotherNumber.js +12 -0
  87. package/src/trimRangeByAnotherRange.js +102 -0
  88. package/src/trimRangeByAnotherRange.test.js +314 -0
  89. package/src/zeroSubrangeByContainerRange.js +36 -0
  90. package/src/zeroSubrangeByContainerRange.test.js +51 -0
@@ -0,0 +1,124 @@
1
+ import getOverlapsOfPotentiallyCircularRanges from './getOverlapsOfPotentiallyCircularRanges.js';
2
+
3
+ import collapseOverlapsGeneratedFromRangeComparisonIfPossible from './collapseOverlapsGeneratedFromRangeComparisonIfPossible.js';
4
+ import assert from 'assert';
5
+
6
+
7
+ ;
8
+ describe('collapseOverlapsGeneratedFromRangeComparisonIfPossible', function() {
9
+ it('returns an empty array if passed an empty array of overlaps', function() {
10
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible([], 1000), []);
11
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible(getOverlapsOfPotentiallyCircularRanges({
12
+ start: 900,
13
+ end: 100
14
+ }, {
15
+ start: 900,
16
+ end: 100
17
+ }, 1000), 1000), [{
18
+ start: 900,
19
+ end: 100
20
+ }]);
21
+ });
22
+ it('collapses a split circular range', function() {
23
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible([{
24
+ start: 0,
25
+ end: 100
26
+ }, {
27
+ start: 105,
28
+ end: 999
29
+ }], 1000), [{
30
+ start: 105,
31
+ end: 100
32
+ }]);
33
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible(getOverlapsOfPotentiallyCircularRanges({
34
+ start: 900,
35
+ end: 100
36
+ }, {
37
+ start: 900,
38
+ end: 100
39
+ }, 1000), 1000), [{
40
+ start: 900,
41
+ end: 100
42
+ }]);
43
+ });
44
+ it('doesnt collapses a split range that could be circular if the originalRangeIsNotCircular', function() {
45
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible([{
46
+ start: 0,
47
+ end: 100
48
+ }, {
49
+ start: 105,
50
+ end: 999
51
+ }], 1000, {
52
+ start: 0,
53
+ end: 999
54
+ }), [{
55
+ start: 0,
56
+ end: 100
57
+ }, {
58
+ start: 105,
59
+ end: 999
60
+ }]);
61
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible(getOverlapsOfPotentiallyCircularRanges({
62
+ start: 900,
63
+ end: 100
64
+ }, {
65
+ start: 900,
66
+ end: 100
67
+ }, 1000), 1000), [{
68
+ start: 900,
69
+ end: 100
70
+ }]);
71
+ });
72
+ it('doesnt collapses a split range that doesnt line up correctly', function() {
73
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible([{
74
+ start: 0,
75
+ end: 100
76
+ }, {
77
+ start: 105,
78
+ end: 998
79
+ }], 1000),[{
80
+ start: 0,
81
+ end: 100
82
+ }, {
83
+ start: 105,
84
+ end: 998
85
+ }]);
86
+ });
87
+ it('collapses a split circular range with a third part', function() {
88
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible([{
89
+ start: 200,
90
+ end: 300
91
+ },{
92
+ start: 0,
93
+ end: 100
94
+ }, {
95
+ start: 500,
96
+ end: 999
97
+ }], 1000), [{
98
+ start: 500,
99
+ end: 100
100
+ },{
101
+ start: 200,
102
+ end: 300
103
+ }]);
104
+ });
105
+
106
+ it('collapses a split circular range with a third part in a different order', function() {
107
+ assert.deepEqual(collapseOverlapsGeneratedFromRangeComparisonIfPossible([{
108
+ start: 0,
109
+ end: 100
110
+ },{
111
+ start: 200,
112
+ end: 300
113
+ }, {
114
+ start: 500,
115
+ end: 999
116
+ }], 1000), [{
117
+ start: 500,
118
+ end: 100
119
+ },{
120
+ start: 200,
121
+ end: 300
122
+ }]);
123
+ });
124
+ });
@@ -0,0 +1,22 @@
1
+ import {assign} from "lodash";
2
+
3
+ export default function convertRangeIndices(range, inputType, outputType) {
4
+ inputType = inputType || {}
5
+ outputType = outputType || {}
6
+ return assign({},range,{
7
+ start: Number(range.start) + (inputType.inclusive1BasedStart
8
+ ? outputType.inclusive1BasedStart
9
+ ? 0
10
+ : -1
11
+ : outputType.inclusive1BasedStart
12
+ ? 1
13
+ : 0),
14
+ end: Number(range.end) + (inputType.inclusive1BasedEnd
15
+ ? outputType.inclusive1BasedEnd
16
+ ? 0
17
+ : -1
18
+ : outputType.inclusive1BasedEnd
19
+ ? 1
20
+ : 0)
21
+ })
22
+ };
@@ -0,0 +1,22 @@
1
+ import convertRangeIndices from './convertRangeIndices';
2
+ import chai from 'chai';
3
+ chai.should();
4
+ describe('convertRangeIndices', function () {
5
+ it('should correctly convert various types of ranges', function () {
6
+ convertRangeIndices({start: 9,end:0},{inclusive1BasedStart: true}).should.deep.equal({start: 8,end: 0})
7
+ convertRangeIndices({start: 9,end:0},{inclusive1BasedStart: true}, {inclusive1BasedEnd: true}).should.deep.equal({start: 8,end: 1})
8
+ convertRangeIndices({start: 9,end:0},{inclusive1BasedEnd: true}, {inclusive1BasedEnd: true}).should.deep.equal({start: 9,end: 0})
9
+ convertRangeIndices({start: 4,end:5},{inclusive1BasedEnd: true}, {inclusive1BasedStart: true}).should.deep.equal({start: 5,end: 4})
10
+ convertRangeIndices({
11
+ start: '1',
12
+ end: '28',
13
+ },
14
+ {inclusive1BasedStart: true, inclusive1BasedEnd: true},
15
+ {})
16
+ .should.deep.equal({start: 0,end: 27})
17
+ });
18
+ it('should not remove other attributes on the range object', function () {
19
+ convertRangeIndices({start: 4,end:5, someOtherAttribute: 'yay'},{inclusive1BasedEnd: true}, {inclusive1BasedStart: true})
20
+ .should.deep.equal({start: 5,end: 4, someOtherAttribute: 'yay'})
21
+ });
22
+ })
@@ -0,0 +1,5 @@
1
+ import convertRangeIndices from './convertRangeIndices';
2
+
3
+ export default function convertRangeTo0Based (range) {
4
+ return convertRangeIndices(range, {inclusive1BasedStart: true, inclusive1BasedEnd: true})
5
+ };
@@ -0,0 +1,5 @@
1
+ import convertRangeIndices from './convertRangeIndices';
2
+
3
+ export default function convertRangeTo1Based (range) {
4
+ return convertRangeIndices(range, {}, {inclusive1BasedStart: true, inclusive1BasedEnd: true})
5
+ };
@@ -0,0 +1,7 @@
1
+ import getRangeLength from './getRangeLength';
2
+
3
+ export default function doesRangeSpanEntireSequence (range, sequenceLength) {
4
+ if (getRangeLength(range) === sequenceLength) {
5
+ return true
6
+ }
7
+ };
@@ -0,0 +1,3 @@
1
+ export default function doesRangeSpanOrigin (range) {
2
+ return range.start > range.end
3
+ };
@@ -0,0 +1,41 @@
1
+ import normalizePositionByRangeLength from './normalizePositionByRangeLength';
2
+ import {assign} from "lodash";
3
+
4
+ export default function expandOrContractCircularRangeToPosition(range, position, maxLength) {
5
+
6
+ // 0 1 2 3 4 5 6 7 8 9
7
+ // r r r r r - - r r r
8
+ //0 1 2 3 4 5 6 7 8 9 10
9
+ // |
10
+ const newRange = assign({}, range);
11
+ let endMoved = true;
12
+ if (range.end >= position) {
13
+ if (position + maxLength - range.start > range.end - position) {
14
+ newRange.end = normalizePositionByRangeLength(position - 1, maxLength, false);
15
+ } else {
16
+ newRange.start = position;
17
+ endMoved = false;
18
+ }
19
+ } else {
20
+ if (range.start < position) {
21
+ if (range.end + maxLength - position > position - range.start) {
22
+ newRange.start = position;
23
+ endMoved = false;
24
+ } else {
25
+ newRange.end = position - 1;
26
+ }
27
+ } else {
28
+ //position somewhere between end and start
29
+ if (range.start - position > position - range.end) {
30
+ newRange.end = position - 1;
31
+ } else {
32
+ endMoved = false;
33
+ newRange.start = position;
34
+ }
35
+ }
36
+ }
37
+ return ({
38
+ newRange: newRange,
39
+ endMoved: endMoved
40
+ })
41
+ };
@@ -0,0 +1,25 @@
1
+ import {assign} from "lodash";
2
+
3
+ export default function expandOrContractNonCircularRangeToPosition (range, position) {
4
+ const newRange = assign({},range);
5
+ let endMoved = true;
6
+ if (range.start > position) {
7
+ newRange.start = position;
8
+ endMoved = false;
9
+ } else {
10
+ if (range.end < position) {
11
+ newRange.end = position - 1;
12
+ } else {
13
+ if (position - range.start > range.end - position) {
14
+ newRange.end = position - 1;
15
+ } else {
16
+ newRange.start = position;
17
+ endMoved = false;
18
+ }
19
+ }
20
+ }
21
+ return ({
22
+ newRange: newRange,
23
+ endMoved: endMoved
24
+ })
25
+ };
@@ -0,0 +1,12 @@
1
+ import {clone} from 'lodash';
2
+ import normalizeRange from './normalizeRange';
3
+
4
+ export default function expandOrContractRangeByLength(range, shiftBy, shiftStart, sequenceLength) {
5
+ const rangeToReturn = clone(range);
6
+ if (shiftStart) {
7
+ rangeToReturn.start -=shiftBy
8
+ } else {
9
+ rangeToReturn.end +=shiftBy
10
+ }
11
+ return normalizeRange(rangeToReturn,sequenceLength)
12
+ };
@@ -0,0 +1,77 @@
1
+ import expandOrContractRangeByLength from './expandOrContractRangeByLength';
2
+ import chai from 'chai';
3
+ const expect = chai.expect;
4
+ chai.should();
5
+
6
+ describe('expandOrContractRangeByLength', function () {
7
+ it('shift start by 1 ', function () {
8
+ const expandedRange = expandOrContractRangeByLength({start: 3,end:4}, 1, true, 10);
9
+ expandedRange.should.deep.equal({
10
+ start: 2,
11
+ end: 4
12
+ })
13
+ });
14
+ it('shift end by 1 ', function () {
15
+ const expandedRange = expandOrContractRangeByLength({start: 3,end:4}, 1, false, 10);
16
+ expandedRange.should.deep.equal({
17
+ start: 3,
18
+ end: 5
19
+ })
20
+ });
21
+ it('shift end by 6 ', function () {
22
+ const expandedRange = expandOrContractRangeByLength({start: 3,end:4}, 6, false, 10);
23
+ expandedRange.should.deep.equal({
24
+ start: 3,
25
+ end: 0
26
+ })
27
+ });
28
+
29
+ it('circular range', function () {
30
+ const expandedRange = expandOrContractRangeByLength({start: 6,end:4}, 1, false, 10);
31
+ expandedRange.should.deep.equal({
32
+ start: 6,
33
+ end: 5
34
+ })
35
+ });
36
+ it('circular range', function () {
37
+ const expandedRange = expandOrContractRangeByLength({start: 6,end:4}, 1, true, 10);
38
+ expandedRange.should.deep.equal({
39
+ start: 5,
40
+ end: 4
41
+ })
42
+ });
43
+ it('circular range', function () {
44
+ const expandedRange = expandOrContractRangeByLength({start: 6,end:4}, 1, true, 10);
45
+ expandedRange.should.deep.equal({
46
+ start: 5,
47
+ end: 4
48
+ })
49
+ });
50
+
51
+ it('negative shiftBy', function () {
52
+ const expandedRange = expandOrContractRangeByLength({start: 6,end:4}, -1, true, 10);
53
+ expandedRange.should.deep.equal({
54
+ start: 7,
55
+ end: 4
56
+ })
57
+ });
58
+ it('negative shiftBy', function () {
59
+ const expandedRange = expandOrContractRangeByLength({start: 6,end:4}, -1, false, 10);
60
+ expandedRange.should.deep.equal({
61
+ start: 6,
62
+ end: 3
63
+ })
64
+ });
65
+
66
+ // it('should error if trying to expand more than possible', function () {
67
+ // var error = false;
68
+ // try {
69
+ // var range = expandOrContractRangeByLength({start: 6,end:4}, 10, false, 10)
70
+ // console.log('range:', range)
71
+ // } catch (e) {
72
+ // error = true;
73
+ // }
74
+ // expect(error).to.be.true;
75
+ // });
76
+ });
77
+
@@ -0,0 +1,10 @@
1
+ import expandOrContractCircularRangeToPosition from './expandOrContractCircularRangeToPosition';
2
+ import expandOrContractNonCircularRangeToPosition from './expandOrContractNonCircularRangeToPosition';
3
+
4
+ export default function expandOrContractRangeToPosition(range, position, maxLength) {
5
+ if (range.start > range.end) {
6
+ return expandOrContractCircularRangeToPosition(range, position, maxLength)
7
+ } else {
8
+ return expandOrContractNonCircularRangeToPosition(range, position, maxLength)
9
+ }
10
+ };
@@ -0,0 +1,85 @@
1
+ import expandOrContractRangeByLength from './expandOrContractRangeByLength';
2
+ import isRangeWithinRange from './isRangeWithinRange';
3
+ import getOverlapsOfPotentiallyCircularRanges from './getOverlapsOfPotentiallyCircularRanges';
4
+ import translateRange from './translateRange';
5
+ import getRangeLength from './getRangeLength';
6
+
7
+ export default function flipRelativeRange(innerRange, outerRange, sequenceLength, options) {
8
+ const isFullyContained = isRangeWithinRange(innerRange,outerRange,sequenceLength);
9
+ if (isFullyContained) {
10
+ return flipFullyContainedRange(innerRange,outerRange,sequenceLength)
11
+ }
12
+ else {
13
+ // flip not fully contained range
14
+ return flipNonFullyContainedRange(innerRange,outerRange,sequenceLength)
15
+ }
16
+ };
17
+
18
+ function flipNonFullyContainedRange(innerRange, outerRange, sequenceLength, options) {
19
+ const outerFullyContained = isRangeWithinRange(outerRange, innerRange,sequenceLength);
20
+ let flippedInnerRange;
21
+ if (outerFullyContained) {
22
+ //special logic
23
+ // flipFullyContainedRange(outerRange, outerRange, sequenceLength)
24
+ const expandBy1 = getRangeLength({
25
+ start: innerRange.start,
26
+ end: outerRange.start
27
+ },sequenceLength) - 1;
28
+ flippedInnerRange = expandOrContractRangeByLength(outerRange, expandBy1, false, sequenceLength)
29
+
30
+ const expandBy2 = getRangeLength({
31
+ end: innerRange.end,
32
+ start: outerRange.end
33
+ },sequenceLength) - 1;
34
+ flippedInnerRange = expandOrContractRangeByLength(flippedInnerRange, expandBy2, true, sequenceLength)
35
+ } else {
36
+ //find overlaps of ranges
37
+ const overlaps = getOverlapsOfPotentiallyCircularRanges(innerRange, outerRange, sequenceLength);
38
+ //take first overlap and determine which end of outer range it overlaps
39
+ if (overlaps.length >= 1) {
40
+ let overlapExtendsForward;
41
+ const firstOverlap = overlaps[0];
42
+ overlapExtendsForward = firstOverlap.start !== outerRange.start
43
+ //flip using fully contained logic
44
+ const flippedTruncatedInner = flipFullyContainedRange(firstOverlap, outerRange, sequenceLength);
45
+ //extend in the opposite direction
46
+ const lengthToExtend = getRangeLength(innerRange,sequenceLength) - getRangeLength(flippedTruncatedInner, sequenceLength);
47
+ flippedInnerRange = expandOrContractRangeByLength(flippedTruncatedInner, lengthToExtend, overlapExtendsForward, sequenceLength)
48
+ } else {
49
+ throw new Error('This case (relative ranges that do not overlap) is unsupported! ')
50
+ }
51
+ }
52
+ return flippedInnerRange
53
+ }
54
+
55
+ function flipFullyContainedRange(innerRange, outerRange, sequenceLength, options) {
56
+ //translate both ranges by offset such that outer range start = 0
57
+ const translateBy = -outerRange.start;
58
+ const translatedOuterRange = translateRange(outerRange, translateBy, sequenceLength);
59
+ const translatedInnerRange = translateRange(innerRange, translateBy, sequenceLength);
60
+
61
+ //flip like non origin spanning range
62
+ const translatedFlippedInnerRange = flipNonOriginSpanningContainedRange(translatedInnerRange, translatedOuterRange, sequenceLength);
63
+
64
+ //translate inner range back by negative offset
65
+ const flippedInnerRange = translateRange(translatedFlippedInnerRange, -translateBy, sequenceLength);
66
+ return flippedInnerRange
67
+ }
68
+
69
+ function flipNonOriginSpanningContainedRange(innerRange, outerRange, sequenceLength) {
70
+ //non origin spanning, fully contained inner
71
+ const offsetFromStart = innerRange.start - outerRange.start;
72
+ const newInnerEnd = outerRange.end - offsetFromStart;
73
+ const innerRangeLength = getRangeLength(innerRange, sequenceLength);
74
+
75
+ return {
76
+ end: newInnerEnd,
77
+ start: newInnerEnd - (innerRangeLength -1)
78
+ }
79
+ }
80
+
81
+
82
+
83
+
84
+ //take 2
85
+
@@ -0,0 +1,124 @@
1
+ /* eslint-disable no-var*/
2
+ import flipContainedRange from './flipContainedRange';
3
+
4
+ import chai from 'chai';
5
+ chai.should();
6
+
7
+ describe('flipContainedRange', function () {
8
+ it('non origin spanning, fully contained inner', function () {
9
+ const innerRange ={
10
+ start: 5,
11
+ end: 13
12
+ };
13
+ const outerRange = {
14
+ start: 0,
15
+ end:20
16
+ };
17
+ const sequenceLength = 40;
18
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
19
+ flippedInnerRange.should.deep.equal({
20
+ start: 7,
21
+ end:15
22
+ })
23
+ });
24
+ it('non origin spanning outer, origin spanning fully contained inner', function () {
25
+ const innerRange ={
26
+ start: 3,
27
+ end: 1
28
+ };
29
+ const outerRange = {
30
+ start: 0,
31
+ end:3
32
+ };
33
+ const sequenceLength = 4;
34
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
35
+ flippedInnerRange.should.deep.equal({
36
+ start: 2,
37
+ end:0
38
+ })
39
+ });
40
+ it('origin spanning outer, non-origin spanning, fully contained inner', function () {
41
+ const innerRange ={
42
+ start: 1,
43
+ end: 3
44
+ };
45
+ const outerRange = {
46
+ start: 8,
47
+ end:5
48
+ };
49
+ const sequenceLength = 10;
50
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
51
+ flippedInnerRange.should.deep.equal({
52
+ start: 0,
53
+ end:2
54
+ })
55
+ });
56
+ it('non-origin spanning outer, non-origin spanning, non-fully contained inner', function () {
57
+ const innerRange ={
58
+ start: 1,
59
+ end: 4
60
+ };
61
+ const outerRange = {
62
+ start: 3,
63
+ end:6
64
+ };
65
+ const sequenceLength = 10;
66
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
67
+ flippedInnerRange.should.deep.equal({
68
+ start: 5,
69
+ end:8
70
+ })
71
+ });
72
+ it('non-origin spanning outer, non-origin spanning, non-fully contained inner', function () {
73
+ const innerRange ={
74
+ start: 4,
75
+ end: 2
76
+ };
77
+ const outerRange = {
78
+ start: 2,
79
+ end:5
80
+ };
81
+ const sequenceLength = 10;
82
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
83
+ flippedInnerRange.should.deep.equal({
84
+ start: 5,
85
+ end:3
86
+ })
87
+ });
88
+
89
+ it('inner fully spans outer, does not wrap origin', function () {
90
+ const innerRange ={
91
+ start: 1,
92
+ end: 7
93
+ };
94
+ const outerRange = {
95
+ start: 2,
96
+ end:5
97
+ };
98
+ const sequenceLength = 10;
99
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
100
+ flippedInnerRange.should.deep.equal({
101
+ start: 0,
102
+ end:6
103
+ })
104
+ });
105
+
106
+ it('inner fully spans outer, does wrap origin', function () {
107
+ const innerRange ={
108
+ start: 4,
109
+ end: 2
110
+ };
111
+ const outerRange = {
112
+ start: 5,
113
+ end:2
114
+ };
115
+ const sequenceLength = 10;
116
+ const flippedInnerRange = flipContainedRange(innerRange, outerRange, sequenceLength);
117
+ flippedInnerRange.should.deep.equal({
118
+ start: 5,
119
+ end:3
120
+ })
121
+ });
122
+
123
+ });
124
+
@@ -0,0 +1,20 @@
1
+ import normalizePositionByRangeLength from './normalizePositionByRangeLength';
2
+
3
+ export default function generateRandomRange(minStart, maxEnd, maxLength) {
4
+ const start = getRandomInt(minStart, maxEnd);
5
+ let end;
6
+ if (maxLength) {
7
+ end = normalizePositionByRangeLength(getRandomInt(start, start + maxLength), maxEnd)
8
+ } else {
9
+ end = getRandomInt(minStart, maxEnd);
10
+ }
11
+ return {
12
+ start: start,
13
+ end: end,
14
+ }
15
+ };
16
+
17
+
18
+ function getRandomInt(min, max) {
19
+ return Math.floor(Math.random() * (max - min)) + min;
20
+ }
@@ -0,0 +1,24 @@
1
+ import getRangeLength from './getRangeLength';
2
+ import generateRandomRange from './generateRandomRange';
3
+ import chai from 'chai';
4
+ chai.should();
5
+
6
+ describe('generateRandomRange', function () {
7
+ it('should generate random ranges between a start and end', function () {
8
+ for (let i = 0; i < 1000; i++) {
9
+ const range = generateRandomRange(0,10);
10
+ range.start.should.be.below(11)
11
+ range.end.should.be.below(11)
12
+ }
13
+ });
14
+
15
+ it('should generate random ranges between a start and end and with length less than maxLength', function () {
16
+ for (let i = 0; i < 1000; i++) {
17
+ const range = generateRandomRange(0,10,5);
18
+ const length = getRangeLength(range);
19
+ if (length > -1) {
20
+ length.should.be.below(6)
21
+ }
22
+ }
23
+ });
24
+ });
@@ -0,0 +1,24 @@
1
+ //function that returns the annotation range type
2
+ export default function getAnnotationRangeType(annotationRange, enclosingRangeType, forward) {
3
+ if (annotationRange.start === enclosingRangeType.start) {
4
+ if (annotationRange.end === enclosingRangeType.end) {
5
+ return 'beginningAndEnd';
6
+ } else {
7
+ if (forward) {
8
+ return 'start';
9
+ } else {
10
+ return 'end';
11
+ }
12
+ }
13
+ } else {
14
+ if (annotationRange.end === enclosingRangeType.end) {
15
+ if (forward) {
16
+ return 'end';
17
+ } else {
18
+ return 'start';
19
+ }
20
+ } else {
21
+ return 'middle';
22
+ }
23
+ }
24
+ };