collect-your-stuff 1.4.0 → 2.0.0
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.
- package/dist/collections/queue/Queue.d.ts +35 -42
- package/dist/collections/queue/Queue.js +64 -80
- package/dist/collections/queue/Queue.min.js +1 -1
- package/dist/collections/queue/TaskQueue.d.ts +68 -0
- package/dist/collections/queue/TaskQueue.js +137 -0
- package/dist/collections/queue/TaskQueue.min.js +1 -0
- package/dist/collections/stack/Stack.d.ts +40 -40
- package/dist/collections/stack/Stack.js +73 -52
- package/dist/collections/stack/Stack.min.js +1 -1
- package/dist/collections/stack/TaskStack.d.ts +65 -0
- package/dist/collections/stack/TaskStack.js +107 -0
- package/dist/collections/stack/TaskStack.min.js +1 -0
- package/dist/main.d.ts +7 -1
- package/dist/main.js +16 -0
- package/dist/main.min.js +1 -1
- package/dist/recipes/IsQueue.d.ts +37 -0
- package/dist/recipes/IsQueue.js +5 -0
- package/dist/recipes/IsQueue.min.js +1 -0
- package/dist/recipes/IsStack.d.ts +36 -0
- package/dist/recipes/IsStack.js +5 -0
- package/dist/recipes/IsStack.min.js +1 -0
- package/package.json +1 -1
|
@@ -1,66 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
* @file queue
|
|
3
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
-
* @version 1.1.0
|
|
5
|
-
* @memberOf module:collect-your-stuff
|
|
6
|
-
*/
|
|
7
|
-
import { Queueable } from './Queueable';
|
|
1
|
+
import { Linker } from '../linked-list/Linker';
|
|
8
2
|
import { IsArrayable } from '../../recipes/IsArrayable';
|
|
9
|
-
import {
|
|
10
|
-
import { completeResponse } from '../../recipes/Runnable';
|
|
3
|
+
import { IsQueue } from '../../recipes/IsQueue';
|
|
11
4
|
/**
|
|
12
|
-
*
|
|
5
|
+
* A first-in-first-out collection: items are added to the back with enqueue and taken from the front with dequeue.
|
|
6
|
+
* Any value can be queued (it is stored as it is, whether it is a function, an object or null), and adding and taking
|
|
7
|
+
* are constant time. To queue tasks which are run as they are taken use TaskQueue.
|
|
13
8
|
*/
|
|
14
|
-
export declare class Queue {
|
|
15
|
-
/** The list which stores the
|
|
9
|
+
export declare class Queue<T = any> implements IsQueue<T>, Iterable<T> {
|
|
10
|
+
/** The list which stores the queued items, the first is next to be dequeued. */
|
|
16
11
|
queuedList: IsArrayable<any>;
|
|
17
|
-
private
|
|
18
|
-
private queueableClass;
|
|
12
|
+
private readonly linkerClass;
|
|
19
13
|
/**
|
|
20
|
-
* Instantiate the queue with
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
23
|
-
* @param {
|
|
14
|
+
* Instantiate the queue, optionally with a list of items to start from.
|
|
15
|
+
* @param {IsArrayable|null} [queuedList=null] The list of linkers to start in this queue (the first is the front)
|
|
16
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
17
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
24
18
|
*/
|
|
25
|
-
constructor(queuedList?: IsArrayable<any
|
|
19
|
+
constructor(queuedList?: IsArrayable<any> | null, listClass?: any, linkerClass?: typeof Linker);
|
|
26
20
|
/**
|
|
27
|
-
* Take
|
|
28
|
-
*
|
|
29
|
-
* completed tasks are discarded.
|
|
30
|
-
* @return {completeResponse|*}
|
|
21
|
+
* Take the item from the front of the queue.
|
|
22
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
31
23
|
*/
|
|
32
|
-
dequeue():
|
|
24
|
+
dequeue(): T | null;
|
|
33
25
|
/**
|
|
34
|
-
*
|
|
26
|
+
* Check whether the queue has no items.
|
|
35
27
|
* @return {boolean}
|
|
36
28
|
*/
|
|
37
29
|
empty(): boolean;
|
|
38
30
|
/**
|
|
39
|
-
* Add
|
|
40
|
-
* @param {
|
|
41
|
-
|
|
42
|
-
enqueue(queueable: Queueable): void;
|
|
43
|
-
/**
|
|
44
|
-
* Take a look at the next queued task
|
|
45
|
-
* @return {Queueable}
|
|
31
|
+
* Add an item to the back of the queue.
|
|
32
|
+
* @param {*} data The item to add
|
|
33
|
+
* @return {Queue} This queue, so that adding can be chained
|
|
46
34
|
*/
|
|
47
|
-
|
|
35
|
+
enqueue(data: T): this;
|
|
48
36
|
/**
|
|
49
|
-
*
|
|
50
|
-
* @return {
|
|
37
|
+
* Look at the item at the front of the queue, without removing it.
|
|
38
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
51
39
|
*/
|
|
52
|
-
|
|
40
|
+
peek(): T | null;
|
|
53
41
|
/**
|
|
54
|
-
*
|
|
42
|
+
* Count the items in the queue.
|
|
55
43
|
* @return {number}
|
|
56
44
|
*/
|
|
57
45
|
size(): number;
|
|
58
46
|
/**
|
|
59
|
-
*
|
|
60
|
-
* @
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
* Iterate over the items from the front of the queue to the back, without removing them.
|
|
48
|
+
* @return {Iterator}
|
|
49
|
+
*/
|
|
50
|
+
[Symbol.iterator](): Iterator<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Convert an array to a Queue, the first value is at the front.
|
|
53
|
+
* @param {Array} [values=[]] The items to queue
|
|
54
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
|
|
55
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
63
56
|
* @returns {Queue}
|
|
64
57
|
*/
|
|
65
|
-
static fromArray: (values?: Array<
|
|
58
|
+
static fromArray: <T_1 = any>(values?: Array<T_1>, listClass?: any, linkerClass?: typeof Linker) => Queue<T_1>;
|
|
66
59
|
}
|
|
@@ -4,81 +4,49 @@ Object.defineProperty(exports, '__esModule', {
|
|
|
4
4
|
value: true
|
|
5
5
|
})
|
|
6
6
|
exports.Queue = void 0
|
|
7
|
-
|
|
7
|
+
require('core-js/modules/esnext.iterator.constructor.js')
|
|
8
|
+
require('core-js/modules/esnext.iterator.for-each.js')
|
|
8
9
|
var _LinkedList = require('../linked-list/LinkedList')
|
|
10
|
+
var _Linker = require('../linked-list/Linker')
|
|
9
11
|
/**
|
|
10
12
|
* @file queue
|
|
11
13
|
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
12
|
-
* @version
|
|
14
|
+
* @version 2.0.0
|
|
13
15
|
* @memberOf module:collect-your-stuff
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* A first-in-first-out collection: items are added to the back with enqueue and taken from the front with dequeue.
|
|
20
|
+
* Any value can be queued (it is stored as it is, whether it is a function, an object or null), and adding and taking
|
|
21
|
+
* are constant time. To queue tasks which are run as they are taken use TaskQueue.
|
|
18
22
|
*/
|
|
19
23
|
class Queue {
|
|
20
24
|
/**
|
|
21
|
-
* Instantiate the queue with
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
24
|
-
* @param {
|
|
25
|
+
* Instantiate the queue, optionally with a list of items to start from.
|
|
26
|
+
* @param {IsArrayable|null} [queuedList=null] The list of linkers to start in this queue (the first is the front)
|
|
27
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given
|
|
28
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
25
29
|
*/
|
|
26
|
-
constructor (queuedList = null, listClass = _LinkedList.LinkedList,
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
if (queuedList === null) {
|
|
30
|
-
queuedList = new listClass(queueableClass)
|
|
31
|
-
}
|
|
32
|
-
this.queuedList = queuedList
|
|
30
|
+
constructor (queuedList = null, listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) {
|
|
31
|
+
this.linkerClass = linkerClass
|
|
32
|
+
this.queuedList = queuedList === null ? new listClass(linkerClass) : queuedList
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* Take
|
|
37
|
-
*
|
|
38
|
-
* completed tasks are discarded.
|
|
39
|
-
* @return {completeResponse|*}
|
|
36
|
+
* Take the item from the front of the queue.
|
|
37
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
40
38
|
*/
|
|
41
39
|
dequeue () {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
next = this.remove()
|
|
46
|
-
}
|
|
47
|
-
if (!next) {
|
|
48
|
-
return {
|
|
49
|
-
success: 'No more queueable tasks in the queue',
|
|
50
|
-
error: false,
|
|
51
|
-
context: this.queuedList
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (next.running) {
|
|
55
|
-
// The unfinished task reports back through its own complete callback, so it is not kept in the queue
|
|
56
|
-
return {
|
|
57
|
-
success: false,
|
|
58
|
-
error: 'The queue has been blocked by an unfinished task.',
|
|
59
|
-
context: next
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (!next.isReady) {
|
|
63
|
-
// Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
|
|
64
|
-
this.enqueue(next)
|
|
65
|
-
// We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
|
|
66
|
-
// Also, we want the loop handled externally
|
|
67
|
-
return {
|
|
68
|
-
success: false,
|
|
69
|
-
error: 'Unable to find ready task.',
|
|
70
|
-
context: next
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (!this.empty()) {
|
|
74
|
-
// Place back in queue to be checked once again next time, only if the queue will not be empty
|
|
75
|
-
this.enqueue(next)
|
|
40
|
+
const front = this.queuedList.first
|
|
41
|
+
if (front === null || typeof front === 'undefined') {
|
|
42
|
+
return null
|
|
76
43
|
}
|
|
77
|
-
|
|
44
|
+
this.queuedList.remove(front)
|
|
45
|
+
return front.data
|
|
78
46
|
}
|
|
79
47
|
|
|
80
48
|
/**
|
|
81
|
-
*
|
|
49
|
+
* Check whether the queue has no items.
|
|
82
50
|
* @return {boolean}
|
|
83
51
|
*/
|
|
84
52
|
empty () {
|
|
@@ -86,50 +54,66 @@ class Queue {
|
|
|
86
54
|
}
|
|
87
55
|
|
|
88
56
|
/**
|
|
89
|
-
* Add
|
|
90
|
-
* @param {
|
|
57
|
+
* Add an item to the back of the queue.
|
|
58
|
+
* @param {*} data The item to add
|
|
59
|
+
* @return {Queue} This queue, so that adding can be chained
|
|
91
60
|
*/
|
|
92
|
-
enqueue (
|
|
93
|
-
|
|
61
|
+
enqueue (data) {
|
|
62
|
+
// The item is wrapped here rather than left to the list, since the list treats objects that look like a linker's
|
|
63
|
+
// settings (they have a data property) as such, and a queue must give back exactly what it was given
|
|
64
|
+
this.queuedList.append(new this.linkerClass({
|
|
65
|
+
data
|
|
66
|
+
}))
|
|
67
|
+
return this
|
|
94
68
|
}
|
|
95
69
|
|
|
96
70
|
/**
|
|
97
|
-
*
|
|
98
|
-
* @return {
|
|
71
|
+
* Look at the item at the front of the queue, without removing it.
|
|
72
|
+
* @return {*|null} The item, or null when the queue is empty
|
|
99
73
|
*/
|
|
100
74
|
peek () {
|
|
101
|
-
|
|
75
|
+
const front = this.queuedList.first
|
|
76
|
+
return front === null || typeof front === 'undefined' ? null : front.data
|
|
102
77
|
}
|
|
103
78
|
|
|
104
79
|
/**
|
|
105
|
-
*
|
|
106
|
-
* @return {
|
|
80
|
+
* Count the items in the queue.
|
|
81
|
+
* @return {number}
|
|
107
82
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return null
|
|
111
|
-
}
|
|
112
|
-
return this.queuedList.remove(this.queuedList.first)
|
|
83
|
+
size () {
|
|
84
|
+
return this.queuedList.length
|
|
113
85
|
}
|
|
114
86
|
|
|
115
87
|
/**
|
|
116
|
-
*
|
|
117
|
-
* @return {
|
|
88
|
+
* Iterate over the items from the front of the queue to the back, without removing them.
|
|
89
|
+
* @return {Iterator}
|
|
118
90
|
*/
|
|
119
|
-
|
|
120
|
-
|
|
91
|
+
[Symbol.iterator] () {
|
|
92
|
+
const linkers = this.queuedList[Symbol.iterator]()
|
|
93
|
+
return {
|
|
94
|
+
next: () => {
|
|
95
|
+
const result = linkers.next()
|
|
96
|
+
return result.done ? {
|
|
97
|
+
done: true,
|
|
98
|
+
value: undefined
|
|
99
|
+
} : {
|
|
100
|
+
done: false,
|
|
101
|
+
value: result.value.data
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
121
105
|
}
|
|
122
106
|
}
|
|
123
107
|
/**
|
|
124
|
-
* Convert an array to a Queue.
|
|
125
|
-
* @param {Array} values
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {
|
|
108
|
+
* Convert an array to a Queue, the first value is at the front.
|
|
109
|
+
* @param {Array} [values=[]] The items to queue
|
|
110
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
|
|
111
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each queued item
|
|
128
112
|
* @returns {Queue}
|
|
129
113
|
*/
|
|
130
114
|
exports.Queue = Queue
|
|
131
|
-
Queue.fromArray = (values = [],
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
return
|
|
115
|
+
Queue.fromArray = (values = [], listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) => {
|
|
116
|
+
const queue = new Queue(null, listClass, linkerClass)
|
|
117
|
+
values.forEach(value => queue.enqueue(value))
|
|
118
|
+
return queue
|
|
135
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0;var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _LinkedList=require("../linked-list/LinkedList"),_Linker=require("../linked-list/Linker");class Queue{constructor(e=null,t=_LinkedList.LinkedList,r=_Linker.Linker){this.linkerClass=r,this.queuedList=null===e?new t(r):e}dequeue(){const e=this.queuedList.first;return null==e?null:(this.queuedList.remove(e),e.data)}empty(){return this.size()<=0}enqueue(e){return this.queuedList.append(new this.linkerClass({data:e})),this}peek(){const e=this.queuedList.first;return null==e?null:e.data}size(){return this.queuedList.length}[Symbol.iterator](){const e=this.queuedList[Symbol.iterator]();return{next:()=>{const t=e.next();return t.done?{done:!0,value:void 0}:{done:!1,value:t.value.data}}}}}exports.Queue=Queue,Queue.fromArray=(e=[],t=_LinkedList.LinkedList,r=_Linker.Linker)=>{const u=new Queue(null,t,r);return e.forEach((e=>u.enqueue(e))),u};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file task queue
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.1.0
|
|
5
|
+
* @memberOf module:collect-your-stuff
|
|
6
|
+
*/
|
|
7
|
+
import { Queueable } from './Queueable';
|
|
8
|
+
import { IsArrayable } from '../../recipes/IsArrayable';
|
|
9
|
+
import { IsLinker } from '../../recipes/IsLinker';
|
|
10
|
+
import { completeResponse } from '../../recipes/Runnable';
|
|
11
|
+
/**
|
|
12
|
+
* Maintain a series of queued tasks (Queueables): dequeue() takes the next task from the front and RUNS it, giving each
|
|
13
|
+
* task in turn a chance to run (a task which is not ready, or which has not finished, is placed at the back again).
|
|
14
|
+
* This is a task scheduler, for a plain first-in-first-out collection of items use Queue.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TaskQueue {
|
|
17
|
+
/** The list which stores the queueables, the first is next to be dequeued. */
|
|
18
|
+
queuedList: IsArrayable<any>;
|
|
19
|
+
private listClass;
|
|
20
|
+
private queueableClass;
|
|
21
|
+
/**
|
|
22
|
+
* Instantiate the queue with the given queue list.
|
|
23
|
+
* @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
|
|
24
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
|
|
25
|
+
* @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
|
|
26
|
+
*/
|
|
27
|
+
constructor(queuedList?: IsArrayable<any>, listClass?: any, queueableClass?: typeof Queueable);
|
|
28
|
+
/**
|
|
29
|
+
* Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
|
|
30
|
+
* queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
|
|
31
|
+
* completed tasks are discarded.
|
|
32
|
+
* @return {completeResponse|*}
|
|
33
|
+
*/
|
|
34
|
+
dequeue(): completeResponse | any;
|
|
35
|
+
/**
|
|
36
|
+
* Return true if the queue is empty (there are no tasks in the queue list)
|
|
37
|
+
* @return {boolean}
|
|
38
|
+
*/
|
|
39
|
+
empty(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Add a queued task to the end of the queue
|
|
42
|
+
* @param {Queueable} queueable Add a new queueable to the end of the queue
|
|
43
|
+
*/
|
|
44
|
+
enqueue(queueable: Queueable): void;
|
|
45
|
+
/**
|
|
46
|
+
* Take a look at the next queued task
|
|
47
|
+
* @return {Queueable}
|
|
48
|
+
*/
|
|
49
|
+
peek(): IsLinker;
|
|
50
|
+
/**
|
|
51
|
+
* Remove the next queued item and return it.
|
|
52
|
+
* @return {Queueable|null}
|
|
53
|
+
*/
|
|
54
|
+
remove(): Queueable | null;
|
|
55
|
+
/**
|
|
56
|
+
* Get the length of the current queue.
|
|
57
|
+
* @return {number}
|
|
58
|
+
*/
|
|
59
|
+
size(): number;
|
|
60
|
+
/**
|
|
61
|
+
* Convert an array to a TaskQueue.
|
|
62
|
+
* @param {Array} values An array of values which will be converted to queueables in this queue
|
|
63
|
+
* @param {Queueable} queueableClass The class to use for each queueable
|
|
64
|
+
* @param {TaskQueue|Iterable} listClass The class to use to manage the queueables
|
|
65
|
+
* @returns {TaskQueue}
|
|
66
|
+
*/
|
|
67
|
+
static fromArray: (values?: Array<any>, queueableClass?: typeof Queueable, listClass?: any) => TaskQueue;
|
|
68
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
exports.TaskQueue = void 0
|
|
7
|
+
var _Queueable = require('./Queueable')
|
|
8
|
+
var _LinkedList = require('../linked-list/LinkedList')
|
|
9
|
+
/**
|
|
10
|
+
* @file task queue
|
|
11
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
12
|
+
* @version 1.1.0
|
|
13
|
+
* @memberOf module:collect-your-stuff
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Maintain a series of queued tasks (Queueables): dequeue() takes the next task from the front and RUNS it, giving each
|
|
18
|
+
* task in turn a chance to run (a task which is not ready, or which has not finished, is placed at the back again).
|
|
19
|
+
* This is a task scheduler, for a plain first-in-first-out collection of items use Queue.
|
|
20
|
+
*/
|
|
21
|
+
class TaskQueue {
|
|
22
|
+
/**
|
|
23
|
+
* Instantiate the queue with the given queue list.
|
|
24
|
+
* @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
|
|
25
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
|
|
26
|
+
* @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
|
|
27
|
+
*/
|
|
28
|
+
constructor (queuedList = null, listClass = _LinkedList.LinkedList, queueableClass = _Queueable.Queueable) {
|
|
29
|
+
this.listClass = listClass
|
|
30
|
+
this.queueableClass = queueableClass
|
|
31
|
+
if (queuedList === null) {
|
|
32
|
+
queuedList = new listClass(queueableClass)
|
|
33
|
+
}
|
|
34
|
+
this.queuedList = queuedList
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
|
|
39
|
+
* queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
|
|
40
|
+
* completed tasks are discarded.
|
|
41
|
+
* @return {completeResponse|*}
|
|
42
|
+
*/
|
|
43
|
+
dequeue () {
|
|
44
|
+
let next = this.remove()
|
|
45
|
+
// Tasks which already completed are discarded when they reach the front of the queue
|
|
46
|
+
while (next && next.complete) {
|
|
47
|
+
next = this.remove()
|
|
48
|
+
}
|
|
49
|
+
if (!next) {
|
|
50
|
+
return {
|
|
51
|
+
success: 'No more queueable tasks in the queue',
|
|
52
|
+
error: false,
|
|
53
|
+
context: this.queuedList
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (next.running) {
|
|
57
|
+
// The unfinished task reports back through its own complete callback, so it is not kept in the queue
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: 'The queue has been blocked by an unfinished task.',
|
|
61
|
+
context: next
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!next.isReady) {
|
|
65
|
+
// Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
|
|
66
|
+
this.enqueue(next)
|
|
67
|
+
// We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
|
|
68
|
+
// Also, we want the loop handled externally
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'Unable to find ready task.',
|
|
72
|
+
context: next
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!this.empty()) {
|
|
76
|
+
// Place back in queue to be checked once again next time, only if the queue will not be empty
|
|
77
|
+
this.enqueue(next)
|
|
78
|
+
}
|
|
79
|
+
return next.run.call(next)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Return true if the queue is empty (there are no tasks in the queue list)
|
|
84
|
+
* @return {boolean}
|
|
85
|
+
*/
|
|
86
|
+
empty () {
|
|
87
|
+
return this.size() <= 0
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Add a queued task to the end of the queue
|
|
92
|
+
* @param {Queueable} queueable Add a new queueable to the end of the queue
|
|
93
|
+
*/
|
|
94
|
+
enqueue (queueable) {
|
|
95
|
+
this.queuedList.append(queueable)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Take a look at the next queued task
|
|
100
|
+
* @return {Queueable}
|
|
101
|
+
*/
|
|
102
|
+
peek () {
|
|
103
|
+
return this.queuedList.first
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Remove the next queued item and return it.
|
|
108
|
+
* @return {Queueable|null}
|
|
109
|
+
*/
|
|
110
|
+
remove () {
|
|
111
|
+
if (this.empty()) {
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
return this.queuedList.remove(this.queuedList.first)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get the length of the current queue.
|
|
119
|
+
* @return {number}
|
|
120
|
+
*/
|
|
121
|
+
size () {
|
|
122
|
+
return this.queuedList.length
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Convert an array to a TaskQueue.
|
|
127
|
+
* @param {Array} values An array of values which will be converted to queueables in this queue
|
|
128
|
+
* @param {Queueable} queueableClass The class to use for each queueable
|
|
129
|
+
* @param {TaskQueue|Iterable} listClass The class to use to manage the queueables
|
|
130
|
+
* @returns {TaskQueue}
|
|
131
|
+
*/
|
|
132
|
+
exports.TaskQueue = TaskQueue
|
|
133
|
+
TaskQueue.fromArray = (values = [], queueableClass = _Queueable.Queueable, listClass = _LinkedList.LinkedList) => {
|
|
134
|
+
const list = new listClass(queueableClass)
|
|
135
|
+
list.initialize(queueableClass.fromArray(values, queueableClass).head)
|
|
136
|
+
return new TaskQueue(list, listClass, queueableClass)
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskQueue=void 0;var _Queueable=require("./Queueable"),_LinkedList=require("../linked-list/LinkedList");class TaskQueue{constructor(e=null,u=_LinkedList.LinkedList,s=_Queueable.Queueable){this.listClass=u,this.queueableClass=s,null===e&&(e=new u(s)),this.queuedList=e}dequeue(){let e=this.remove();for(;e&&e.complete;)e=this.remove();return e?e.running?{success:!1,error:"The queue has been blocked by an unfinished task.",context:e}:e.isReady?(this.empty()||this.enqueue(e),e.run.call(e)):(this.enqueue(e),{success:!1,error:"Unable to find ready task.",context:e}):{success:"No more queueable tasks in the queue",error:!1,context:this.queuedList}}empty(){return this.size()<=0}enqueue(e){this.queuedList.append(e)}peek(){return this.queuedList.first}remove(){return this.empty()?null:this.queuedList.remove(this.queuedList.first)}size(){return this.queuedList.length}}exports.TaskQueue=TaskQueue,TaskQueue.fromArray=(e=[],u=_Queueable.Queueable,s=_LinkedList.LinkedList)=>{const t=new s(u);return t.initialize(u.fromArray(e,u).head),new TaskQueue(t,s,u)};
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
* @file stack.
|
|
3
|
-
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
-
* @version 1.0.0
|
|
5
|
-
* @memberOf module:collect-your-stuff
|
|
6
|
-
*/
|
|
7
|
-
import { Stackable } from './Stackable';
|
|
1
|
+
import { Linker } from '../linked-list/Linker';
|
|
8
2
|
import { IsArrayable } from '../../recipes/IsArrayable';
|
|
9
|
-
import {
|
|
10
|
-
import { completeResponse } from '../../recipes/Runnable';
|
|
3
|
+
import { IsStack } from '../../recipes/IsStack';
|
|
11
4
|
/**
|
|
12
|
-
*
|
|
5
|
+
* A last-in-first-out collection: items are added to the top with push and taken from the top with pop. Any value can
|
|
6
|
+
* be stacked (it is stored as it is, whether it is a function, an object or null), and adding and taking are constant
|
|
7
|
+
* time. To stack tasks which are run as they are taken use TaskStack.
|
|
13
8
|
*/
|
|
14
|
-
export declare class Stack {
|
|
15
|
-
/** The list which stores the
|
|
9
|
+
export declare class Stack<T = any> implements IsStack<T>, Iterable<T> {
|
|
10
|
+
/** The list which stores the stacked items, the first is the top of the stack. */
|
|
16
11
|
stackedList: IsArrayable<any>;
|
|
17
|
-
private
|
|
18
|
-
private stackableClass;
|
|
12
|
+
private readonly linkerClass;
|
|
19
13
|
/**
|
|
20
|
-
* Instantiate the
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given
|
|
23
|
-
* @param {
|
|
14
|
+
* Instantiate the stack, optionally with a list of items to start from.
|
|
15
|
+
* @param {IsArrayable|null} [stackedList=null] The list of linkers to start in this stack (the first is the top)
|
|
16
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given
|
|
17
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each stacked item
|
|
24
18
|
*/
|
|
25
|
-
constructor(stackedList?: IsArrayable<any
|
|
19
|
+
constructor(stackedList?: IsArrayable<any> | null, listClass?: any, linkerClass?: typeof Linker);
|
|
26
20
|
/**
|
|
27
|
-
*
|
|
21
|
+
* Check whether the stack has no items.
|
|
28
22
|
* @return {boolean}
|
|
29
23
|
*/
|
|
30
24
|
empty(): boolean;
|
|
31
25
|
/**
|
|
32
|
-
*
|
|
33
|
-
* @return {
|
|
34
|
-
*/
|
|
35
|
-
top(): IsLinker;
|
|
36
|
-
/**
|
|
37
|
-
* Remove the next stacked task and return it.
|
|
38
|
-
* @return {Stackable|null}
|
|
26
|
+
* Look at the item on the top of the stack, without removing it.
|
|
27
|
+
* @return {*|null} The item, or null when the stack is empty
|
|
39
28
|
*/
|
|
40
|
-
|
|
29
|
+
peek(): T | null;
|
|
41
30
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @
|
|
31
|
+
* Take the item from the top of the stack.
|
|
32
|
+
* @return {*|null} The item, or null when the stack is empty
|
|
44
33
|
*/
|
|
45
|
-
|
|
34
|
+
pop(): T | null;
|
|
46
35
|
/**
|
|
47
|
-
*
|
|
48
|
-
* @
|
|
36
|
+
* Add an item to the top of the stack.
|
|
37
|
+
* @param {*} data The item to add
|
|
38
|
+
* @return {Stack} This stack, so that adding can be chained
|
|
49
39
|
*/
|
|
50
|
-
|
|
40
|
+
push(data: T): this;
|
|
51
41
|
/**
|
|
52
|
-
*
|
|
42
|
+
* Count the items in the stack.
|
|
53
43
|
* @return {number}
|
|
54
44
|
*/
|
|
55
45
|
size(): number;
|
|
56
46
|
/**
|
|
57
|
-
*
|
|
58
|
-
* @
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
* The item on the top of the stack (the same as peek).
|
|
48
|
+
* @return {*|null} The item, or null when the stack is empty
|
|
49
|
+
*/
|
|
50
|
+
top(): T | null;
|
|
51
|
+
/**
|
|
52
|
+
* Iterate over the items from the top of the stack to the bottom, without removing them.
|
|
53
|
+
* @return {Iterator}
|
|
54
|
+
*/
|
|
55
|
+
[Symbol.iterator](): Iterator<T>;
|
|
56
|
+
/**
|
|
57
|
+
* Convert an array to a Stack by pushing each value in turn, so the last value is on the top.
|
|
58
|
+
* @param {Array} [values=[]] The items to stack
|
|
59
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
|
|
60
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each stacked item
|
|
61
61
|
* @returns {Stack}
|
|
62
62
|
*/
|
|
63
|
-
static fromArray: (values?: Array<
|
|
63
|
+
static fromArray: <T_1 = any>(values?: Array<T_1>, listClass?: any, linkerClass?: typeof Linker) => Stack<T_1>;
|
|
64
64
|
}
|
|
@@ -4,36 +4,36 @@ Object.defineProperty(exports, '__esModule', {
|
|
|
4
4
|
value: true
|
|
5
5
|
})
|
|
6
6
|
exports.Stack = void 0
|
|
7
|
-
|
|
7
|
+
require('core-js/modules/esnext.iterator.constructor.js')
|
|
8
|
+
require('core-js/modules/esnext.iterator.for-each.js')
|
|
8
9
|
var _LinkedList = require('../linked-list/LinkedList')
|
|
10
|
+
var _Linker = require('../linked-list/Linker')
|
|
9
11
|
/**
|
|
10
12
|
* @file stack.
|
|
11
13
|
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
12
|
-
* @version
|
|
14
|
+
* @version 2.0.0
|
|
13
15
|
* @memberOf module:collect-your-stuff
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* A last-in-first-out collection: items are added to the top with push and taken from the top with pop. Any value can
|
|
20
|
+
* be stacked (it is stored as it is, whether it is a function, an object or null), and adding and taking are constant
|
|
21
|
+
* time. To stack tasks which are run as they are taken use TaskStack.
|
|
18
22
|
*/
|
|
19
23
|
class Stack {
|
|
20
24
|
/**
|
|
21
|
-
* Instantiate the
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given
|
|
24
|
-
* @param {
|
|
25
|
+
* Instantiate the stack, optionally with a list of items to start from.
|
|
26
|
+
* @param {IsArrayable|null} [stackedList=null] The list of linkers to start in this stack (the first is the top)
|
|
27
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given
|
|
28
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each stacked item
|
|
25
29
|
*/
|
|
26
|
-
constructor (stackedList = null, listClass = _LinkedList.LinkedList,
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
if (stackedList === null) {
|
|
30
|
-
stackedList = new listClass(stackableClass)
|
|
31
|
-
}
|
|
32
|
-
this.stackedList = stackedList
|
|
30
|
+
constructor (stackedList = null, listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) {
|
|
31
|
+
this.linkerClass = linkerClass
|
|
32
|
+
this.stackedList = stackedList === null ? new listClass(linkerClass) : stackedList
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Check whether the stack has no items.
|
|
37
37
|
* @return {boolean}
|
|
38
38
|
*/
|
|
39
39
|
empty () {
|
|
@@ -41,66 +41,87 @@ class Stack {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
* @return {
|
|
44
|
+
* Look at the item on the top of the stack, without removing it.
|
|
45
|
+
* @return {*|null} The item, or null when the stack is empty
|
|
46
46
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
peek () {
|
|
48
|
+
const top = this.stackedList.first
|
|
49
|
+
return top === null || typeof top === 'undefined' ? null : top.data
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
/**
|
|
52
|
-
*
|
|
53
|
-
* @return {
|
|
53
|
+
* Take the item from the top of the stack.
|
|
54
|
+
* @return {*|null} The item, or null when the stack is empty
|
|
54
55
|
*/
|
|
55
56
|
pop () {
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
58
|
-
return
|
|
59
|
-
success: 'No more stackable tasks in the stack',
|
|
60
|
-
error: false,
|
|
61
|
-
context: this.stackedList
|
|
62
|
-
}
|
|
57
|
+
const top = this.stackedList.first
|
|
58
|
+
if (top === null || typeof top === 'undefined') {
|
|
59
|
+
return null
|
|
63
60
|
}
|
|
64
|
-
|
|
61
|
+
this.stackedList.remove(top)
|
|
62
|
+
return top.data
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {
|
|
66
|
+
* Add an item to the top of the stack.
|
|
67
|
+
* @param {*} data The item to add
|
|
68
|
+
* @return {Stack} This stack, so that adding can be chained
|
|
70
69
|
*/
|
|
71
|
-
push (
|
|
72
|
-
|
|
70
|
+
push (data) {
|
|
71
|
+
// The item is wrapped here rather than left to the list, since the list treats objects that look like a linker's
|
|
72
|
+
// settings (they have a data property) as such, and a stack must give back exactly what it was given
|
|
73
|
+
this.stackedList.prepend(new this.linkerClass({
|
|
74
|
+
data
|
|
75
|
+
}))
|
|
76
|
+
return this
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
/**
|
|
76
|
-
*
|
|
77
|
-
* @return {
|
|
80
|
+
* Count the items in the stack.
|
|
81
|
+
* @return {number}
|
|
78
82
|
*/
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return null
|
|
82
|
-
}
|
|
83
|
-
return this.stackedList.remove(this.stackedList.first)
|
|
83
|
+
size () {
|
|
84
|
+
return this.stackedList.length
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
|
-
*
|
|
88
|
-
* @return {
|
|
88
|
+
* The item on the top of the stack (the same as peek).
|
|
89
|
+
* @return {*|null} The item, or null when the stack is empty
|
|
89
90
|
*/
|
|
90
|
-
|
|
91
|
-
return this.
|
|
91
|
+
top () {
|
|
92
|
+
return this.peek()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Iterate over the items from the top of the stack to the bottom, without removing them.
|
|
97
|
+
* @return {Iterator}
|
|
98
|
+
*/
|
|
99
|
+
[Symbol.iterator] () {
|
|
100
|
+
const linkers = this.stackedList[Symbol.iterator]()
|
|
101
|
+
return {
|
|
102
|
+
next: () => {
|
|
103
|
+
const result = linkers.next()
|
|
104
|
+
return result.done ? {
|
|
105
|
+
done: true,
|
|
106
|
+
value: undefined
|
|
107
|
+
} : {
|
|
108
|
+
done: false,
|
|
109
|
+
value: result.value.data
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
92
113
|
}
|
|
93
114
|
}
|
|
94
115
|
/**
|
|
95
|
-
* Convert an array to a Stack.
|
|
96
|
-
* @param {Array} values
|
|
97
|
-
* @param {
|
|
98
|
-
* @param {
|
|
116
|
+
* Convert an array to a Stack by pushing each value in turn, so the last value is on the top.
|
|
117
|
+
* @param {Array} [values=[]] The items to stack
|
|
118
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list used to store the items
|
|
119
|
+
* @param {Linker} [linkerClass=Linker] The class used to hold each stacked item
|
|
99
120
|
* @returns {Stack}
|
|
100
121
|
*/
|
|
101
122
|
exports.Stack = Stack
|
|
102
|
-
Stack.fromArray = (values = [],
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
return
|
|
123
|
+
Stack.fromArray = (values = [], listClass = _LinkedList.LinkedList, linkerClass = _Linker.Linker) => {
|
|
124
|
+
const stack = new Stack(null, listClass, linkerClass)
|
|
125
|
+
values.forEach(value => stack.push(value))
|
|
126
|
+
return stack
|
|
106
127
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Stack=void 0;var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Stack=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _LinkedList=require("../linked-list/LinkedList"),_Linker=require("../linked-list/Linker");class Stack{constructor(e=null,t=_LinkedList.LinkedList,s=_Linker.Linker){this.linkerClass=s,this.stackedList=null===e?new t(s):e}empty(){return this.size()<=0}peek(){const e=this.stackedList.first;return null==e?null:e.data}pop(){const e=this.stackedList.first;return null==e?null:(this.stackedList.remove(e),e.data)}push(e){return this.stackedList.prepend(new this.linkerClass({data:e})),this}size(){return this.stackedList.length}top(){return this.peek()}[Symbol.iterator](){const e=this.stackedList[Symbol.iterator]();return{next:()=>{const t=e.next();return t.done?{done:!0,value:void 0}:{done:!1,value:t.value.data}}}}}exports.Stack=Stack,Stack.fromArray=(e=[],t=_LinkedList.LinkedList,s=_Linker.Linker)=>{const r=new Stack(null,t,s);return e.forEach((e=>r.push(e))),r};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file task stack.
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
* @memberOf module:collect-your-stuff
|
|
6
|
+
*/
|
|
7
|
+
import { Stackable } from './Stackable';
|
|
8
|
+
import { IsArrayable } from '../../recipes/IsArrayable';
|
|
9
|
+
import { IsLinker } from '../../recipes/IsLinker';
|
|
10
|
+
import { completeResponse } from '../../recipes/Runnable';
|
|
11
|
+
/**
|
|
12
|
+
* Store a collection of tasks (Stackables) which can only be inserted and removed from the top: pop() takes the task from
|
|
13
|
+
* the top and RUNS it. For a plain last-in-first-out collection of items use Stack.
|
|
14
|
+
*/
|
|
15
|
+
export declare class TaskStack {
|
|
16
|
+
/** The list which stores the stackables, the first is the top of the stack. */
|
|
17
|
+
stackedList: IsArrayable<any>;
|
|
18
|
+
private listClass;
|
|
19
|
+
private stackableClass;
|
|
20
|
+
/**
|
|
21
|
+
* Instantiate the state with the starter stacked list.
|
|
22
|
+
* @param {Iterable|LinkedList} [stackedList=null] The list of stackables to start in this stack.
|
|
23
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given.
|
|
24
|
+
* @param {Stackable} [stackableClass=Stackable] The class used to wrap stacked items.
|
|
25
|
+
*/
|
|
26
|
+
constructor(stackedList?: IsArrayable<any>, listClass?: any, stackableClass?: typeof Stackable);
|
|
27
|
+
/**
|
|
28
|
+
* Return true if the stack is empty (there are no tasks in the stacked list)
|
|
29
|
+
* @return {boolean}
|
|
30
|
+
*/
|
|
31
|
+
empty(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Take a look at the next stacked task
|
|
34
|
+
* @return {Stackable}
|
|
35
|
+
*/
|
|
36
|
+
top(): IsLinker;
|
|
37
|
+
/**
|
|
38
|
+
* Remove the next stacked task and return it.
|
|
39
|
+
* @return {Stackable|null}
|
|
40
|
+
*/
|
|
41
|
+
pop(): Stackable | completeResponse | null;
|
|
42
|
+
/**
|
|
43
|
+
* Push a stackable task to the top of the stack.
|
|
44
|
+
* @param {Stackable|*} stackable Add a new stackable to the top of the stack
|
|
45
|
+
*/
|
|
46
|
+
push(stackable: any): void;
|
|
47
|
+
/**
|
|
48
|
+
* Remove the next stacked task and return it.
|
|
49
|
+
* @return {Stackable|null}
|
|
50
|
+
*/
|
|
51
|
+
remove(): Stackable | null;
|
|
52
|
+
/**
|
|
53
|
+
* Get the size of the current stack.
|
|
54
|
+
* @return {number}
|
|
55
|
+
*/
|
|
56
|
+
size(): number;
|
|
57
|
+
/**
|
|
58
|
+
* Convert an array to a TaskStack.
|
|
59
|
+
* @param {Array} values An array of values which will be converted to stackables in this queue
|
|
60
|
+
* @param {Stackable} stackableClass The class to use for each stackable
|
|
61
|
+
* @param {TaskStack|Iterable} listClass The class to use to manage the stackables
|
|
62
|
+
* @returns {TaskStack}
|
|
63
|
+
*/
|
|
64
|
+
static fromArray: (values?: Array<any>, stackableClass?: typeof Stackable, listClass?: any) => TaskStack;
|
|
65
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
exports.TaskStack = void 0
|
|
7
|
+
var _Stackable = require('./Stackable')
|
|
8
|
+
var _LinkedList = require('../linked-list/LinkedList')
|
|
9
|
+
/**
|
|
10
|
+
* @file task stack.
|
|
11
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
12
|
+
* @version 1.0.0
|
|
13
|
+
* @memberOf module:collect-your-stuff
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Store a collection of tasks (Stackables) which can only be inserted and removed from the top: pop() takes the task from
|
|
18
|
+
* the top and RUNS it. For a plain last-in-first-out collection of items use Stack.
|
|
19
|
+
*/
|
|
20
|
+
class TaskStack {
|
|
21
|
+
/**
|
|
22
|
+
* Instantiate the state with the starter stacked list.
|
|
23
|
+
* @param {Iterable|LinkedList} [stackedList=null] The list of stackables to start in this stack.
|
|
24
|
+
* @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given.
|
|
25
|
+
* @param {Stackable} [stackableClass=Stackable] The class used to wrap stacked items.
|
|
26
|
+
*/
|
|
27
|
+
constructor (stackedList = null, listClass = _LinkedList.LinkedList, stackableClass = _Stackable.Stackable) {
|
|
28
|
+
this.listClass = listClass
|
|
29
|
+
this.stackableClass = stackableClass
|
|
30
|
+
if (stackedList === null) {
|
|
31
|
+
stackedList = new listClass(stackableClass)
|
|
32
|
+
}
|
|
33
|
+
this.stackedList = stackedList
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Return true if the stack is empty (there are no tasks in the stacked list)
|
|
38
|
+
* @return {boolean}
|
|
39
|
+
*/
|
|
40
|
+
empty () {
|
|
41
|
+
return this.size() <= 0
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Take a look at the next stacked task
|
|
46
|
+
* @return {Stackable}
|
|
47
|
+
*/
|
|
48
|
+
top () {
|
|
49
|
+
return this.stackedList.first
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Remove the next stacked task and return it.
|
|
54
|
+
* @return {Stackable|null}
|
|
55
|
+
*/
|
|
56
|
+
pop () {
|
|
57
|
+
const next = this.remove()
|
|
58
|
+
if (!next) {
|
|
59
|
+
return {
|
|
60
|
+
success: 'No more stackable tasks in the stack',
|
|
61
|
+
error: false,
|
|
62
|
+
context: this.stackedList
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return next.run()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Push a stackable task to the top of the stack.
|
|
70
|
+
* @param {Stackable|*} stackable Add a new stackable to the top of the stack
|
|
71
|
+
*/
|
|
72
|
+
push (stackable) {
|
|
73
|
+
this.stackedList.prepend(stackable)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Remove the next stacked task and return it.
|
|
78
|
+
* @return {Stackable|null}
|
|
79
|
+
*/
|
|
80
|
+
remove () {
|
|
81
|
+
if (this.empty()) {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
return this.stackedList.remove(this.stackedList.first)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get the size of the current stack.
|
|
89
|
+
* @return {number}
|
|
90
|
+
*/
|
|
91
|
+
size () {
|
|
92
|
+
return this.stackedList.length
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Convert an array to a TaskStack.
|
|
97
|
+
* @param {Array} values An array of values which will be converted to stackables in this queue
|
|
98
|
+
* @param {Stackable} stackableClass The class to use for each stackable
|
|
99
|
+
* @param {TaskStack|Iterable} listClass The class to use to manage the stackables
|
|
100
|
+
* @returns {TaskStack}
|
|
101
|
+
*/
|
|
102
|
+
exports.TaskStack = TaskStack
|
|
103
|
+
TaskStack.fromArray = (values = [], stackableClass = _Stackable.Stackable, listClass = _LinkedList.LinkedList) => {
|
|
104
|
+
const list = new listClass(stackableClass)
|
|
105
|
+
list.initialize(stackableClass.fromArray(values, stackableClass).head)
|
|
106
|
+
return new TaskStack(list, listClass, stackableClass)
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TaskStack=void 0;var _Stackable=require("./Stackable"),_LinkedList=require("../linked-list/LinkedList");class TaskStack{constructor(t=null,s=_LinkedList.LinkedList,e=_Stackable.Stackable){this.listClass=s,this.stackableClass=e,null===t&&(t=new s(e)),this.stackedList=t}empty(){return this.size()<=0}top(){return this.stackedList.first}pop(){const t=this.remove();return t?t.run():{success:"No more stackable tasks in the stack",error:!1,context:this.stackedList}}push(t){this.stackedList.prepend(t)}remove(){return this.empty()?null:this.stackedList.remove(this.stackedList.first)}size(){return this.stackedList.length}}exports.TaskStack=TaskStack,TaskStack.fromArray=(t=[],s=_Stackable.Stackable,e=_LinkedList.LinkedList)=>{const i=new e(s);return i.initialize(s.fromArray(t,s).head),new TaskStack(i,e,s)};
|
package/dist/main.d.ts
CHANGED
|
@@ -16,8 +16,10 @@ import { TreeLinker } from './collections/linked-tree-list/TreeLinker';
|
|
|
16
16
|
import { LinkedTreeList } from './collections/linked-tree-list/LinkedTreeList';
|
|
17
17
|
import { Queueable } from './collections/queue/Queueable';
|
|
18
18
|
import { Queue } from './collections/queue/Queue';
|
|
19
|
+
import { TaskQueue } from './collections/queue/TaskQueue';
|
|
19
20
|
import { Stackable } from './collections/stack/Stackable';
|
|
20
21
|
import { Stack } from './collections/stack/Stack';
|
|
22
|
+
import { TaskStack } from './collections/stack/TaskStack';
|
|
21
23
|
import { recipes } from './recipes/recipes';
|
|
22
24
|
import { services } from './services/services';
|
|
23
25
|
/**
|
|
@@ -26,13 +28,15 @@ import { services } from './services/services';
|
|
|
26
28
|
* 2. Create a heap (both min and max heap variants) which is similar to binary tree in structure, but tree having its min / max value as root. and it must insert on the left-most lowest level, and removes from root. Be able to easily swap nodes to ensure min / max ordering.
|
|
27
29
|
* 3. Create a graph type which can have directional and undirectional variants for linking nodes
|
|
28
30
|
*/
|
|
29
|
-
export { ArrayElement, Arrayable, DoubleLinker, DoublyLinkedList, Linker, LinkedList, TreeLinker, LinkedTreeList, Queueable, Queue, Stackable, Stack, recipes, services };
|
|
31
|
+
export { ArrayElement, Arrayable, DoubleLinker, DoublyLinkedList, Linker, LinkedList, TreeLinker, LinkedTreeList, Queueable, Queue, TaskQueue, Stackable, Stack, TaskStack, recipes, services };
|
|
30
32
|
export type { IsArrayable, forEachCallback } from './recipes/IsArrayable';
|
|
31
33
|
export type { IsDoubleLinker } from './recipes/IsDoubleLinker';
|
|
32
34
|
export type { IsElement } from './recipes/IsElement';
|
|
33
35
|
export type { IsLinker } from './recipes/IsLinker';
|
|
34
36
|
export type { IsTree } from './recipes/IsTree';
|
|
35
37
|
export type { IsTreeNode } from './recipes/IsTreeNode';
|
|
38
|
+
export type { IsQueue } from './recipes/IsQueue';
|
|
39
|
+
export type { IsStack } from './recipes/IsStack';
|
|
36
40
|
export type { IsRunnable, completeResponse } from './recipes/Runnable';
|
|
37
41
|
/**
|
|
38
42
|
* All methods exported from this module are encapsulated within collect-your-stuff (this default export is the same
|
|
@@ -49,8 +53,10 @@ declare const collectYourStuff: {
|
|
|
49
53
|
LinkedTreeList: typeof LinkedTreeList;
|
|
50
54
|
Queueable: typeof Queueable;
|
|
51
55
|
Queue: typeof Queue;
|
|
56
|
+
TaskQueue: typeof TaskQueue;
|
|
52
57
|
Stackable: typeof Stackable;
|
|
53
58
|
Stack: typeof Stack;
|
|
59
|
+
TaskStack: typeof TaskStack;
|
|
54
60
|
recipes: {
|
|
55
61
|
ArrayIterator: typeof import("./recipes/ArrayIterator").ArrayIterator;
|
|
56
62
|
Runnable: typeof import("./recipes/Runnable").Runnable;
|
package/dist/main.js
CHANGED
|
@@ -69,6 +69,18 @@ Object.defineProperty(exports, 'Stackable', {
|
|
|
69
69
|
return _Stackable.Stackable
|
|
70
70
|
}
|
|
71
71
|
})
|
|
72
|
+
Object.defineProperty(exports, 'TaskQueue', {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return _TaskQueue.TaskQueue
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
Object.defineProperty(exports, 'TaskStack', {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () {
|
|
81
|
+
return _TaskStack.TaskStack
|
|
82
|
+
}
|
|
83
|
+
})
|
|
72
84
|
Object.defineProperty(exports, 'TreeLinker', {
|
|
73
85
|
enumerable: true,
|
|
74
86
|
get: function () {
|
|
@@ -99,8 +111,10 @@ var _TreeLinker = require('./collections/linked-tree-list/TreeLinker')
|
|
|
99
111
|
var _LinkedTreeList = require('./collections/linked-tree-list/LinkedTreeList')
|
|
100
112
|
var _Queueable = require('./collections/queue/Queueable')
|
|
101
113
|
var _Queue = require('./collections/queue/Queue')
|
|
114
|
+
var _TaskQueue = require('./collections/queue/TaskQueue')
|
|
102
115
|
var _Stackable = require('./collections/stack/Stackable')
|
|
103
116
|
var _Stack = require('./collections/stack/Stack')
|
|
117
|
+
var _TaskStack = require('./collections/stack/TaskStack')
|
|
104
118
|
var _recipes = require('./recipes/recipes')
|
|
105
119
|
var _services = require('./services/services')
|
|
106
120
|
/**
|
|
@@ -135,8 +149,10 @@ const collectYourStuff = {
|
|
|
135
149
|
LinkedTreeList: _LinkedTreeList.LinkedTreeList,
|
|
136
150
|
Queueable: _Queueable.Queueable,
|
|
137
151
|
Queue: _Queue.Queue,
|
|
152
|
+
TaskQueue: _TaskQueue.TaskQueue,
|
|
138
153
|
Stackable: _Stackable.Stackable,
|
|
139
154
|
Stack: _Stack.Stack,
|
|
155
|
+
TaskStack: _TaskStack.TaskStack,
|
|
140
156
|
recipes: _recipes.recipes,
|
|
141
157
|
services: _services.services
|
|
142
158
|
}
|
package/dist/main.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ArrayElement",{enumerable:!0,get:function(){return _ArrayElement.ArrayElement}}),Object.defineProperty(exports,"Arrayable",{enumerable:!0,get:function(){return _Arrayable.Arrayable}}),Object.defineProperty(exports,"DoubleLinker",{enumerable:!0,get:function(){return _DoubleLinker.DoubleLinker}}),Object.defineProperty(exports,"DoublyLinkedList",{enumerable:!0,get:function(){return _DoublyLinkedList.DoublyLinkedList}}),Object.defineProperty(exports,"LinkedList",{enumerable:!0,get:function(){return _LinkedList.LinkedList}}),Object.defineProperty(exports,"LinkedTreeList",{enumerable:!0,get:function(){return _LinkedTreeList.LinkedTreeList}}),Object.defineProperty(exports,"Linker",{enumerable:!0,get:function(){return _Linker.Linker}}),Object.defineProperty(exports,"Queue",{enumerable:!0,get:function(){return _Queue.Queue}}),Object.defineProperty(exports,"Queueable",{enumerable:!0,get:function(){return _Queueable.Queueable}}),Object.defineProperty(exports,"Stack",{enumerable:!0,get:function(){return _Stack.Stack}}),Object.defineProperty(exports,"Stackable",{enumerable:!0,get:function(){return _Stackable.Stackable}}),Object.defineProperty(exports,"TreeLinker",{enumerable:!0,get:function(){return _TreeLinker.TreeLinker}}),exports.default=void 0,Object.defineProperty(exports,"recipes",{enumerable:!0,get:function(){return _recipes.recipes}}),Object.defineProperty(exports,"services",{enumerable:!0,get:function(){return _services.services}}),require("core-js/stable");var _ArrayElement=require("./collections/arrayable/ArrayElement"),_Arrayable=require("./collections/arrayable/Arrayable"),_DoubleLinker=require("./collections/doubly-linked-list/DoubleLinker"),_DoublyLinkedList=require("./collections/doubly-linked-list/DoublyLinkedList"),_Linker=require("./collections/linked-list/Linker"),_LinkedList=require("./collections/linked-list/LinkedList"),_TreeLinker=require("./collections/linked-tree-list/TreeLinker"),_LinkedTreeList=require("./collections/linked-tree-list/LinkedTreeList"),_Queueable=require("./collections/queue/Queueable"),_Queue=require("./collections/queue/Queue"),_Stackable=require("./collections/stack/Stackable"),_Stack=require("./collections/stack/Stack"),_recipes=require("./recipes/recipes"),_services=require("./services/services");const collectYourStuff={ArrayElement:_ArrayElement.ArrayElement,Arrayable:_Arrayable.Arrayable,DoubleLinker:_DoubleLinker.DoubleLinker,DoublyLinkedList:_DoublyLinkedList.DoublyLinkedList,Linker:_Linker.Linker,LinkedList:_LinkedList.LinkedList,TreeLinker:_TreeLinker.TreeLinker,LinkedTreeList:_LinkedTreeList.LinkedTreeList,Queueable:_Queueable.Queueable,Queue:_Queue.Queue,Stackable:_Stackable.Stackable,Stack:_Stack.Stack,recipes:_recipes.recipes,services:_services.services};var _default=exports.default=collectYourStuff;"undefined"!=typeof window&&(window.collectYourStuff=collectYourStuff);
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ArrayElement",{enumerable:!0,get:function(){return _ArrayElement.ArrayElement}}),Object.defineProperty(exports,"Arrayable",{enumerable:!0,get:function(){return _Arrayable.Arrayable}}),Object.defineProperty(exports,"DoubleLinker",{enumerable:!0,get:function(){return _DoubleLinker.DoubleLinker}}),Object.defineProperty(exports,"DoublyLinkedList",{enumerable:!0,get:function(){return _DoublyLinkedList.DoublyLinkedList}}),Object.defineProperty(exports,"LinkedList",{enumerable:!0,get:function(){return _LinkedList.LinkedList}}),Object.defineProperty(exports,"LinkedTreeList",{enumerable:!0,get:function(){return _LinkedTreeList.LinkedTreeList}}),Object.defineProperty(exports,"Linker",{enumerable:!0,get:function(){return _Linker.Linker}}),Object.defineProperty(exports,"Queue",{enumerable:!0,get:function(){return _Queue.Queue}}),Object.defineProperty(exports,"Queueable",{enumerable:!0,get:function(){return _Queueable.Queueable}}),Object.defineProperty(exports,"Stack",{enumerable:!0,get:function(){return _Stack.Stack}}),Object.defineProperty(exports,"Stackable",{enumerable:!0,get:function(){return _Stackable.Stackable}}),Object.defineProperty(exports,"TaskQueue",{enumerable:!0,get:function(){return _TaskQueue.TaskQueue}}),Object.defineProperty(exports,"TaskStack",{enumerable:!0,get:function(){return _TaskStack.TaskStack}}),Object.defineProperty(exports,"TreeLinker",{enumerable:!0,get:function(){return _TreeLinker.TreeLinker}}),exports.default=void 0,Object.defineProperty(exports,"recipes",{enumerable:!0,get:function(){return _recipes.recipes}}),Object.defineProperty(exports,"services",{enumerable:!0,get:function(){return _services.services}}),require("core-js/stable");var _ArrayElement=require("./collections/arrayable/ArrayElement"),_Arrayable=require("./collections/arrayable/Arrayable"),_DoubleLinker=require("./collections/doubly-linked-list/DoubleLinker"),_DoublyLinkedList=require("./collections/doubly-linked-list/DoublyLinkedList"),_Linker=require("./collections/linked-list/Linker"),_LinkedList=require("./collections/linked-list/LinkedList"),_TreeLinker=require("./collections/linked-tree-list/TreeLinker"),_LinkedTreeList=require("./collections/linked-tree-list/LinkedTreeList"),_Queueable=require("./collections/queue/Queueable"),_Queue=require("./collections/queue/Queue"),_TaskQueue=require("./collections/queue/TaskQueue"),_Stackable=require("./collections/stack/Stackable"),_Stack=require("./collections/stack/Stack"),_TaskStack=require("./collections/stack/TaskStack"),_recipes=require("./recipes/recipes"),_services=require("./services/services");const collectYourStuff={ArrayElement:_ArrayElement.ArrayElement,Arrayable:_Arrayable.Arrayable,DoubleLinker:_DoubleLinker.DoubleLinker,DoublyLinkedList:_DoublyLinkedList.DoublyLinkedList,Linker:_Linker.Linker,LinkedList:_LinkedList.LinkedList,TreeLinker:_TreeLinker.TreeLinker,LinkedTreeList:_LinkedTreeList.LinkedTreeList,Queueable:_Queueable.Queueable,Queue:_Queue.Queue,TaskQueue:_TaskQueue.TaskQueue,Stackable:_Stackable.Stackable,Stack:_Stack.Stack,TaskStack:_TaskStack.TaskStack,recipes:_recipes.recipes,services:_services.services};var _default=exports.default=collectYourStuff;"undefined"!=typeof window&&(window.collectYourStuff=collectYourStuff);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Queue recipe.
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
* @memberOf module:collect-your-stuff
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Define a first-in-first-out queue: items are added to the back (enqueue) and taken from the front (dequeue).
|
|
9
|
+
* This is the shape which si-funciona's queueManager / queueTimeout expect of a queue.
|
|
10
|
+
*/
|
|
11
|
+
export interface IsQueue<T = any> {
|
|
12
|
+
/**
|
|
13
|
+
* Take the item from the front of the queue.
|
|
14
|
+
* @return {T|null} The item, or null when the queue is empty
|
|
15
|
+
*/
|
|
16
|
+
dequeue: () => T | null;
|
|
17
|
+
/**
|
|
18
|
+
* Check whether the queue has no items.
|
|
19
|
+
* @return {boolean}
|
|
20
|
+
*/
|
|
21
|
+
empty: () => boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Add an item to the back of the queue.
|
|
24
|
+
* @param {T} data The item to add
|
|
25
|
+
*/
|
|
26
|
+
enqueue: (data: T) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Look at the item at the front of the queue, without removing it.
|
|
29
|
+
* @return {T|null} The item, or null when the queue is empty
|
|
30
|
+
*/
|
|
31
|
+
peek: () => T | null;
|
|
32
|
+
/**
|
|
33
|
+
* Count the items in the queue.
|
|
34
|
+
* @return {number}
|
|
35
|
+
*/
|
|
36
|
+
size: () => number;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Stack recipe.
|
|
3
|
+
* @author Joshua Heagle <joshuaheagle@gmail.com>
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
* @memberOf module:collect-your-stuff
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Define a last-in-first-out stack: items are added to the top (push) and taken from the top (pop).
|
|
9
|
+
*/
|
|
10
|
+
export interface IsStack<T = any> {
|
|
11
|
+
/**
|
|
12
|
+
* Check whether the stack has no items.
|
|
13
|
+
* @return {boolean}
|
|
14
|
+
*/
|
|
15
|
+
empty: () => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Look at the item on the top of the stack, without removing it.
|
|
18
|
+
* @return {T|null} The item, or null when the stack is empty
|
|
19
|
+
*/
|
|
20
|
+
peek: () => T | null;
|
|
21
|
+
/**
|
|
22
|
+
* Take the item from the top of the stack.
|
|
23
|
+
* @return {T|null} The item, or null when the stack is empty
|
|
24
|
+
*/
|
|
25
|
+
pop: () => T | null;
|
|
26
|
+
/**
|
|
27
|
+
* Add an item to the top of the stack.
|
|
28
|
+
* @param {T} data The item to add
|
|
29
|
+
*/
|
|
30
|
+
push: (data: T) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Count the items in the stack.
|
|
33
|
+
* @return {number}
|
|
34
|
+
*/
|
|
35
|
+
size: () => number;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
package/package.json
CHANGED