@woosh/meep-engine 2.43.40 → 2.43.42
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/core/binary/BitSet.js +4 -18
- package/core/model/node-graph/Connection.js +41 -0
- package/core/model/node-graph/Connection.spec.js +21 -0
- package/core/model/node-graph/DataType.js +23 -1
- package/core/model/node-graph/DataType.spec.js +28 -0
- package/core/model/node-graph/NodeGraph.js +16 -7
- package/core/model/node-graph/node/NodeDescription.js +12 -5
- package/core/model/node-graph/node/NodeInstance.js +9 -3
- package/core/model/node-graph/node/NodeInstancePortReference.js +18 -0
- package/core/model/node-graph/node/NodeRegistry.js +36 -10
- package/core/model/node-graph/node/NodeRegistry.spec.js +25 -0
- package/core/model/node-graph/node/Port.js +12 -1
- package/core/model/node-graph/node/PortDirection.js +1 -1
- package/engine/graphics/render/frame_graph/RenderGraph.js +5 -1
- package/engine/intelligence/behavior/SelectorBehavior.js +3 -1
- package/engine/intelligence/behavior/behavior_to_dot.js +251 -0
- package/engine/intelligence/behavior/behavior_to_dot.prototype.js +55 -0
- package/engine/intelligence/behavior/composite/CompositeBehavior.js +6 -0
- package/engine/intelligence/behavior/composite/ParallelBehavior.js +10 -0
- package/engine/intelligence/behavior/composite/SequenceBehavior.js +6 -50
- package/engine/intelligence/behavior/composite/SequenceBehaviorSerializationAdapter.js +52 -0
- package/engine/intelligence/blackboard/Blackboard.js +26 -14
- package/engine/intelligence/blackboard/Blackboard.spec.js +62 -0
- package/engine/intelligence/blackboard/{Blacboard.spec.js → BlackboardSerializationAdapter.spec.js} +1 -1
- package/engine/intelligence/mcts/README.md +7 -0
- package/engine/intelligence/optimization/RandomOptimizer.js +2 -1
- package/engine/intelligence/resource/ResourceAllocationBid.js +3 -3
- package/engine/intelligence/resource/ResourceAllocationSolver.js +1 -1
- package/engine/intelligence/resource/StrategicResourceAllocator.js +6 -4
- package/engine/intelligence/resource/TacticalModule.js +7 -0
- package/engine/knowledge/database/StaticKnowledgeDataTableDescriptor.js +5 -5
- package/engine/navigation/grid/GridField.js +1 -0
- package/engine/notify/NotificationLog.js +2 -2
- package/package.json +1 -1
package/core/binary/BitSet.js
CHANGED
|
@@ -86,7 +86,6 @@ function BitSet() {
|
|
|
86
86
|
this.__data_uint32 = new Uint32Array(this.__capacity >> 5);
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
90
89
|
* @type {number}
|
|
91
90
|
*/
|
|
92
91
|
this.__shrinkFactor = SHRINK_FACTOR;
|
|
@@ -201,7 +200,7 @@ BitSet.prototype.__setLength = function (new_length) {
|
|
|
201
200
|
* @returns {int} Index of previous set bit, or -1 if no set bit found
|
|
202
201
|
*/
|
|
203
202
|
BitSet.prototype.previousSetBit = function (fromIndex) {
|
|
204
|
-
assert.
|
|
203
|
+
assert.isNonNegativeInteger(fromIndex, `fromIndex`);
|
|
205
204
|
|
|
206
205
|
const index = min2(fromIndex, this.__length - 1);
|
|
207
206
|
|
|
@@ -354,21 +353,6 @@ BitSet.prototype.nextClearBit = function (fromIndex) {
|
|
|
354
353
|
return set_length;
|
|
355
354
|
};
|
|
356
355
|
|
|
357
|
-
/**
|
|
358
|
-
* Slow method for scanning through bitset, used for debugging
|
|
359
|
-
* @param {BitSet} set
|
|
360
|
-
* @returns {number}
|
|
361
|
-
*/
|
|
362
|
-
function scanToFirstClearBit(set) {
|
|
363
|
-
for (let i = 0; i <= set.size(); i++) {
|
|
364
|
-
if (set.get(i) === false) {
|
|
365
|
-
return i;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
return -1;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
356
|
/**
|
|
373
357
|
*
|
|
374
358
|
* @param {int} bitIndex
|
|
@@ -443,7 +427,9 @@ BitSet.prototype.setRange = function (startIndex, endIndex) {
|
|
|
443
427
|
* @param {number} endIndex clear up to here, excluding this position
|
|
444
428
|
*/
|
|
445
429
|
BitSet.prototype.clearRange = function (startIndex, endIndex) {
|
|
446
|
-
|
|
430
|
+
assert.greaterThanOrEqual(startIndex, 0, "invalid start index");
|
|
431
|
+
assert.greaterThanOrEqual(endIndex, 0, "invalid end index");
|
|
432
|
+
|
|
447
433
|
for (let i = startIndex; i < endIndex; i++) {
|
|
448
434
|
this.set(i, false);
|
|
449
435
|
}
|
|
@@ -3,13 +3,26 @@ import { noop } from "../../function/Functions.js";
|
|
|
3
3
|
import { objectKeyByValue } from "../object/objectKeyByValue.js";
|
|
4
4
|
import { PortDirection } from "./node/PortDirection.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @type {number}
|
|
9
|
+
*/
|
|
10
|
+
let id_counter = 0;
|
|
11
|
+
|
|
6
12
|
export class Connection {
|
|
7
13
|
constructor() {
|
|
14
|
+
/**
|
|
15
|
+
* @readonly
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
this.id = id_counter++;
|
|
19
|
+
|
|
8
20
|
/**
|
|
9
21
|
*
|
|
10
22
|
* @type {NodeInstancePortReference}
|
|
11
23
|
*/
|
|
12
24
|
this.source = null;
|
|
25
|
+
|
|
13
26
|
/**
|
|
14
27
|
*
|
|
15
28
|
* @type {NodeInstancePortReference}
|
|
@@ -93,4 +106,32 @@ export class Connection {
|
|
|
93
106
|
|
|
94
107
|
return this.source.instance.id === id || this.target.instance.id === id;
|
|
95
108
|
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
* @param {Connection} other
|
|
113
|
+
* @returns {boolean}
|
|
114
|
+
*/
|
|
115
|
+
equals(other) {
|
|
116
|
+
return this.target === other.target
|
|
117
|
+
&& this.source === other.source
|
|
118
|
+
;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
hash() {
|
|
122
|
+
const source_hash = this.source !== null ? this.source.id : 0;
|
|
123
|
+
const target_hash = this.target !== null ? this.target.id : 0;
|
|
124
|
+
|
|
125
|
+
// shuffle bits a bit to get better spread
|
|
126
|
+
return ((source_hash << 16) | (source_hash >>> 16))
|
|
127
|
+
^ (target_hash)
|
|
128
|
+
;
|
|
129
|
+
}
|
|
96
130
|
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @readonly
|
|
135
|
+
* @type {boolean}
|
|
136
|
+
*/
|
|
137
|
+
Connection.prototype.isConnection = true;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Connection } from "./Connection.js";
|
|
2
|
+
|
|
3
|
+
test("stable hash", () => {
|
|
4
|
+
const a = new Connection();
|
|
5
|
+
const b = new Connection();
|
|
6
|
+
|
|
7
|
+
expect(a.hash()).toEqual(b.hash());
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("equality of fresh instances", () => {
|
|
11
|
+
const a = new Connection();
|
|
12
|
+
const b = new Connection();
|
|
13
|
+
|
|
14
|
+
expect(a.equals(b)).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("equality on self", () => {
|
|
18
|
+
const thing = new Connection();
|
|
19
|
+
|
|
20
|
+
expect(thing.equals(thing)).toBe(true);
|
|
21
|
+
});
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
1
3
|
export class DataType {
|
|
2
4
|
constructor() {
|
|
3
5
|
/**
|
|
@@ -14,7 +16,15 @@ export class DataType {
|
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
toString() {
|
|
17
|
-
return
|
|
19
|
+
return `{DataType: id=${this.id}, name='${this.name}' }`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @return {number}
|
|
25
|
+
*/
|
|
26
|
+
hash() {
|
|
27
|
+
return this.id;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
/**
|
|
@@ -26,6 +36,18 @@ export class DataType {
|
|
|
26
36
|
return this.id === other.id && this.name === other.name;
|
|
27
37
|
}
|
|
28
38
|
|
|
39
|
+
toJSON() {
|
|
40
|
+
return { ...this };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fromJSON({ id, name }) {
|
|
44
|
+
assert.isNonNegativeInteger(id, 'id');
|
|
45
|
+
assert.isString(name, 'name');
|
|
46
|
+
|
|
47
|
+
this.id = id;
|
|
48
|
+
this.name = name;
|
|
49
|
+
}
|
|
50
|
+
|
|
29
51
|
/**
|
|
30
52
|
*
|
|
31
53
|
* @param {number} id
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DataType } from "./DataType.js";
|
|
2
|
+
|
|
3
|
+
test('to/from json', () => {
|
|
4
|
+
const a = DataType.from(7, 'kitty');
|
|
5
|
+
|
|
6
|
+
const b = new DataType();
|
|
7
|
+
|
|
8
|
+
b.fromJSON(a.toJSON());
|
|
9
|
+
|
|
10
|
+
expect(b.id).toBe(a.id);
|
|
11
|
+
expect(b.name).toBe(a.name);
|
|
12
|
+
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('equals', () => {
|
|
16
|
+
const a = DataType.from(7, 'kitty');
|
|
17
|
+
const b = DataType.from(7, 'kitty');
|
|
18
|
+
const c = DataType.from(7, 'fluffy');
|
|
19
|
+
const d = DataType.from(9, 'kitty');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
expect(a.equals(b)).toBe(true);
|
|
23
|
+
|
|
24
|
+
expect(a.equals(c)).toBe(false);
|
|
25
|
+
expect(a.equals(d)).toBe(false);
|
|
26
|
+
|
|
27
|
+
expect(c.equals(d)).toBe(false);
|
|
28
|
+
});
|
|
@@ -43,7 +43,7 @@ export class NodeGraph {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
*
|
|
46
|
-
* @param {function(NodeInstance)} visitor
|
|
46
|
+
* @param {function(NodeInstance):*} visitor
|
|
47
47
|
* @param [thisArg]
|
|
48
48
|
*/
|
|
49
49
|
traverseNodes(visitor, thisArg) {
|
|
@@ -52,7 +52,7 @@ export class NodeGraph {
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
*
|
|
55
|
-
* @param {function(Connection)} visitor
|
|
55
|
+
* @param {function(Connection):*} visitor
|
|
56
56
|
* @param [thisArg]
|
|
57
57
|
*/
|
|
58
58
|
traverseConnections(visitor, thisArg) {
|
|
@@ -105,15 +105,18 @@ export class NodeGraph {
|
|
|
105
105
|
*
|
|
106
106
|
* @param {number} node_id
|
|
107
107
|
* @param {number} port_id
|
|
108
|
-
* @returns {NodeInstancePortReference}
|
|
108
|
+
* @returns {NodeInstancePortReference|undefined}
|
|
109
109
|
*/
|
|
110
110
|
getConnectionEndpoint(node_id, port_id) {
|
|
111
111
|
|
|
112
112
|
const nodeInstance = this.getNode(node_id);
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
if (nodeInstance === undefined) {
|
|
115
|
+
// no node
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
115
118
|
|
|
116
|
-
return
|
|
119
|
+
return nodeInstance.getEndpoint(port_id);
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
/**
|
|
@@ -219,13 +222,13 @@ export class NodeGraph {
|
|
|
219
222
|
//get endpoints
|
|
220
223
|
const sourceEndpoint = sourceNodeInstance.getEndpoint(sourcePort);
|
|
221
224
|
|
|
222
|
-
if (sourceEndpoint ===
|
|
225
|
+
if (sourceEndpoint === undefined) {
|
|
223
226
|
throw new Error(`Source port '${sourcePort}' not found`);
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
const targetEndpoint = targetNodeInstance.getEndpoint(targetPort);
|
|
227
230
|
|
|
228
|
-
if (targetEndpoint ===
|
|
231
|
+
if (targetEndpoint === undefined) {
|
|
229
232
|
throw new Error(`Target port '${targetPort}' not found`);
|
|
230
233
|
}
|
|
231
234
|
|
|
@@ -287,3 +290,9 @@ export class NodeGraph {
|
|
|
287
290
|
return count;
|
|
288
291
|
}
|
|
289
292
|
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* @readonly
|
|
296
|
+
* @type {boolean}
|
|
297
|
+
*/
|
|
298
|
+
NodeGraph.prototype.isNodeGraph = true;
|
|
@@ -67,19 +67,20 @@ export class NodeDescription {
|
|
|
67
67
|
assert.typeOf(name, 'string', 'name');
|
|
68
68
|
assert.enum(type, NodeParameterDataType, 'type');
|
|
69
69
|
|
|
70
|
+
let _default = defaultValue;
|
|
70
71
|
|
|
71
72
|
//if default value is not given, pick one
|
|
72
|
-
if (
|
|
73
|
+
if (_default === undefined) {
|
|
73
74
|
switch (type) {
|
|
74
75
|
//intended fallthrough
|
|
75
76
|
case NodeParameterDataType.Number:
|
|
76
|
-
|
|
77
|
+
_default = 0;
|
|
77
78
|
break;
|
|
78
79
|
case NodeParameterDataType.Boolean:
|
|
79
|
-
|
|
80
|
+
_default = false;
|
|
80
81
|
break;
|
|
81
82
|
case NodeParameterDataType.String:
|
|
82
|
-
|
|
83
|
+
_default = "";
|
|
83
84
|
break;
|
|
84
85
|
default:
|
|
85
86
|
throw new Error(`Unknown data type '${type}'`);
|
|
@@ -93,7 +94,7 @@ export class NodeDescription {
|
|
|
93
94
|
|
|
94
95
|
pd.name = name;
|
|
95
96
|
pd.type = type;
|
|
96
|
-
pd.defaultValue =
|
|
97
|
+
pd.defaultValue = _default;
|
|
97
98
|
pd.id = id;
|
|
98
99
|
|
|
99
100
|
assert.ok(pd.validate(console.error), 'parameter is not valid');
|
|
@@ -188,3 +189,9 @@ export class NodeDescription {
|
|
|
188
189
|
return this.ports
|
|
189
190
|
}
|
|
190
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @readonly
|
|
195
|
+
* @type {boolean}
|
|
196
|
+
*/
|
|
197
|
+
NodeDescription.prototype.isNodeDescription = true;
|
|
@@ -4,13 +4,19 @@ import { NodeInstancePortReference } from "./NodeInstancePortReference.js";
|
|
|
4
4
|
import { PortDirection } from "./PortDirection.js";
|
|
5
5
|
import { isArrayEqual } from "../../../collection/array/isArrayEqual.js";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @type {number}
|
|
10
|
+
*/
|
|
11
|
+
let id_counter = 0;
|
|
12
|
+
|
|
7
13
|
export class NodeInstance {
|
|
8
14
|
constructor() {
|
|
9
15
|
/**
|
|
10
16
|
*
|
|
11
17
|
* @type {number}
|
|
12
18
|
*/
|
|
13
|
-
this.id =
|
|
19
|
+
this.id = id_counter++;
|
|
14
20
|
|
|
15
21
|
/**
|
|
16
22
|
*
|
|
@@ -149,7 +155,7 @@ export class NodeInstance {
|
|
|
149
155
|
/**
|
|
150
156
|
*
|
|
151
157
|
* @param {number} port Port ID
|
|
152
|
-
* @returns {NodeInstancePortReference|
|
|
158
|
+
* @returns {NodeInstancePortReference|undefined}
|
|
153
159
|
*/
|
|
154
160
|
getEndpoint(port) {
|
|
155
161
|
const endpoints = this.endpoints;
|
|
@@ -161,7 +167,7 @@ export class NodeInstance {
|
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
//not found
|
|
164
|
-
return
|
|
170
|
+
return undefined;
|
|
165
171
|
}
|
|
166
172
|
|
|
167
173
|
hash() {
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { assert } from "../../../assert.js";
|
|
2
2
|
import { computeHashIntegerArray } from "../../../collection/array/computeHashIntegerArray.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @type {number}
|
|
7
|
+
*/
|
|
8
|
+
let id_counter = 0;
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* Reference for a port of a node instance
|
|
6
12
|
*/
|
|
7
13
|
export class NodeInstancePortReference {
|
|
8
14
|
|
|
9
15
|
constructor() {
|
|
16
|
+
/**
|
|
17
|
+
* @readonly
|
|
18
|
+
* @type {number}
|
|
19
|
+
*/
|
|
20
|
+
this.id = id_counter++;
|
|
21
|
+
|
|
10
22
|
/**
|
|
11
23
|
*
|
|
12
24
|
* @type {NodeInstance}
|
|
@@ -75,3 +87,9 @@ export class NodeInstancePortReference {
|
|
|
75
87
|
;
|
|
76
88
|
}
|
|
77
89
|
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @readonly
|
|
93
|
+
* @type {boolean}
|
|
94
|
+
*/
|
|
95
|
+
NodeInstancePortReference.prototype.isNodeInstancePortReference = true;
|
|
@@ -4,16 +4,25 @@ import { DataType } from "../DataType.js";
|
|
|
4
4
|
import { NodeDescription } from "./NodeDescription.js";
|
|
5
5
|
import { Port } from "./Port.js";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {Port} port
|
|
10
|
+
* @return {DataType}
|
|
11
|
+
*/
|
|
12
|
+
function getPortType(port) {
|
|
13
|
+
return port.dataType;
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
export class NodeRegistry {
|
|
8
17
|
constructor() {
|
|
9
18
|
/**
|
|
10
|
-
*
|
|
19
|
+
* ID -> Node mapping
|
|
11
20
|
* @type {Map<number, NodeDescription>}
|
|
12
21
|
*/
|
|
13
22
|
this.nodes = new Map();
|
|
14
23
|
|
|
15
24
|
/**
|
|
16
|
-
*
|
|
25
|
+
* ID -> DataType mapping
|
|
17
26
|
* @type {Map<number, DataType>}
|
|
18
27
|
*/
|
|
19
28
|
this.types = new Map();
|
|
@@ -31,19 +40,17 @@ export class NodeRegistry {
|
|
|
31
40
|
* @param {NodeDescription} node
|
|
32
41
|
*/
|
|
33
42
|
addNode(node) {
|
|
34
|
-
assert.
|
|
35
|
-
assert.
|
|
43
|
+
assert.defined(node, "node");
|
|
44
|
+
assert.notNull(node, "node");
|
|
36
45
|
|
|
37
46
|
if (this.nodes.has(node.id)) {
|
|
38
|
-
console.warn(`Node with id ${node.id} already exists`);
|
|
47
|
+
// console.warn(`Node with id ${node.id} already exists`);
|
|
39
48
|
|
|
40
49
|
return false;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
//extract types
|
|
44
|
-
node.getPorts().forEach(
|
|
45
|
-
this.addType(port.dataType);
|
|
46
|
-
});
|
|
53
|
+
node.getPorts().map(getPortType).forEach(this.addType, this);
|
|
47
54
|
|
|
48
55
|
this.nodes.set(node.id, node);
|
|
49
56
|
|
|
@@ -55,14 +62,27 @@ export class NodeRegistry {
|
|
|
55
62
|
* @param {DataType} type
|
|
56
63
|
*/
|
|
57
64
|
addType(type) {
|
|
58
|
-
if (this.
|
|
65
|
+
if (this.hasType(type)) {
|
|
59
66
|
return false;
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
this.types.set(type.id, type);
|
|
70
|
+
|
|
63
71
|
return true;
|
|
64
72
|
}
|
|
65
73
|
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @param {DataType} type
|
|
77
|
+
* @return {boolean}
|
|
78
|
+
*/
|
|
79
|
+
hasType(type) {
|
|
80
|
+
assert.defined(type, 'type');
|
|
81
|
+
assert.notNull(type, 'type');
|
|
82
|
+
|
|
83
|
+
return this.types.has(type.id);
|
|
84
|
+
}
|
|
85
|
+
|
|
66
86
|
/**
|
|
67
87
|
*
|
|
68
88
|
* @returns {number}
|
|
@@ -123,7 +143,7 @@ export class NodeRegistry {
|
|
|
123
143
|
}
|
|
124
144
|
|
|
125
145
|
/**
|
|
126
|
-
*
|
|
146
|
+
* NOTE: this only works with un-extended node descriptions
|
|
127
147
|
* @param json
|
|
128
148
|
* @returns {NodeDescription}
|
|
129
149
|
*/
|
|
@@ -215,3 +235,9 @@ export class NodeRegistry {
|
|
|
215
235
|
};
|
|
216
236
|
}
|
|
217
237
|
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @readonly
|
|
241
|
+
* @type {boolean}
|
|
242
|
+
*/
|
|
243
|
+
NodeRegistry.prototype.isNodeRegistry = true;
|
|
@@ -50,3 +50,28 @@ test("serialize/deserialize 1 node with 1 port", () => {
|
|
|
50
50
|
expect(port.dataType.name).toBe("kitty");
|
|
51
51
|
expect(port.dataType.id).toBe(42);
|
|
52
52
|
});
|
|
53
|
+
|
|
54
|
+
test("port types are added automatically when node is added", () => {
|
|
55
|
+
const registry = new NodeRegistry();
|
|
56
|
+
|
|
57
|
+
const type = DataType.from(0, 'a');
|
|
58
|
+
|
|
59
|
+
const node = new NodeDescription();
|
|
60
|
+
node.createPort(type, "port name", PortDirection.In);
|
|
61
|
+
|
|
62
|
+
registry.addNode(node);
|
|
63
|
+
|
|
64
|
+
expect(registry.hasType(type));
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("hasType", () => {
|
|
68
|
+
const registry = new NodeRegistry();
|
|
69
|
+
|
|
70
|
+
const type = DataType.from(0, 'a');
|
|
71
|
+
|
|
72
|
+
expect(registry.hasType(type)).toBe(false);
|
|
73
|
+
|
|
74
|
+
registry.addType(type);
|
|
75
|
+
|
|
76
|
+
expect(registry.hasType(type)).toBe(true);
|
|
77
|
+
});
|
|
@@ -2,6 +2,11 @@ import { computeStringHash } from "../../../primitives/strings/computeStringHash
|
|
|
2
2
|
import { PortDirection } from "./PortDirection.js";
|
|
3
3
|
import { computeHashIntegerArray } from "../../../collection/array/computeHashIntegerArray.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @type {number}
|
|
7
|
+
*/
|
|
8
|
+
let id_counter = 0;
|
|
9
|
+
|
|
5
10
|
export class Port {
|
|
6
11
|
constructor() {
|
|
7
12
|
/**
|
|
@@ -14,7 +19,7 @@ export class Port {
|
|
|
14
19
|
* ID uniquely identifies object within some context. Ids are assumed to be immutable
|
|
15
20
|
* @type {number}
|
|
16
21
|
*/
|
|
17
|
-
this.id =
|
|
22
|
+
this.id = id_counter++;
|
|
18
23
|
|
|
19
24
|
/**
|
|
20
25
|
*
|
|
@@ -53,3 +58,9 @@ export class Port {
|
|
|
53
58
|
|
|
54
59
|
}
|
|
55
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @readonly
|
|
64
|
+
* @type {boolean}
|
|
65
|
+
*/
|
|
66
|
+
Port.prototype.isPort = true;
|
|
@@ -338,6 +338,10 @@ export class RenderGraph {
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
/**
|
|
342
|
+
* @see https://en.wikipedia.org/wiki/DOT_(graph_description_language)
|
|
343
|
+
* @return {string}
|
|
344
|
+
*/
|
|
341
345
|
exportToDot() {
|
|
342
346
|
const out = new LineBuilder();
|
|
343
347
|
|
|
@@ -397,9 +401,9 @@ export class RenderGraph {
|
|
|
397
401
|
out.dedent();
|
|
398
402
|
out.add("} [color=olivedrab3]");
|
|
399
403
|
}
|
|
404
|
+
// -- Clusters:
|
|
400
405
|
out.dedent();
|
|
401
406
|
out.add("}");
|
|
402
|
-
// -- Clusters:
|
|
403
407
|
return out.build();
|
|
404
408
|
}
|
|
405
409
|
}
|