drakongen 1.4.7 → 1.7.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/browser/drakongen.js +945 -375
- package/browsertest.html +9 -1
- package/buildexamples.js +51 -4
- package/exampleproject/foo.txt +2 -0
- package/examples/20. /320/227/320/276/320/273/320/276/321/202/320/276/320/271 - /320/273/320/265/320/262/321/213/320/271 final.drakon" +66 -0
- package/examples/21. /320/227/320/276/320/273/320/276/321/202/320/276/320/271 - /320/277/321/200/320/260/320/262/321/213/320/271 final.drakon" +66 -0
- package/examples/Complex arrow-parallel.drakon +116 -0
- package/examples/Complex arrow-parallel.txt +40 -0
- package/examples/Complex arrow.txt +1 -0
- package/examples/How to tune PID on a quadcopter.txt +1 -0
- package/examples/NestedArrowLoop.drakon +38 -0
- package/examples/NestedArrowLoop.txt +20 -0
- package/examples/all icons.drakon +227 -0
- package/examples/all icons.txt +68 -0
- package/examples/ar01-action.drakon +31 -0
- package/examples/ar01-action.txt +9 -0
- package/examples/ar10-parallel.drakon +70 -0
- package/examples/ar10-parallel.txt +20 -0
- package/examples/badShortCircuit.drakon +34 -0
- package/examples/badShortCircuit.txt +7 -0
- package/examples/getToken.txt +2 -0
- package/examples/monitorPaymentStatus.drakon +56 -0
- package/examples/monitorPaymentStatus.txt +25 -0
- package/examples/no-loop/00.Empty.txt +6 -0
- package/examples/no-loop/01. /320/221/320/265/320/273/321/213/320/271.txt" +5 -0
- package/examples/no-loop/02. /320/247/321/221/321/200/320/275/321/213/320/271.txt" +8 -0
- package/examples/no-loop/03. /320/241/320/265/321/200/321/213/320/271.txt" +7 -0
- package/examples/no-loop/04. /320/221/321/203/321/200/321/213/320/271.txt" +7 -0
- package/examples/no-loop/05. /320/226/321/221/320/273/321/202/321/213/320/271.txt" +7 -0
- package/examples/no-loop/06. /320/221/320/260/320/263/321/200/320/276/320/262/321/213/320/271.txt" +9 -0
- package/examples/no-loop/07. /320/244/320/270/320/276/320/273/320/265/321/202/320/276/320/262/321/213/320/271.txt" +12 -0
- package/examples/no-loop/08. /320/221/320/270/321/200/321/216/320/267/320/276/320/262/321/213/320/271.txt" +7 -0
- package/examples/no-loop/09. /320/236/321/200/320/260/320/275/320/266/320/265/320/262/321/213/320/271.txt" +9 -0
- package/examples/no-loop/10. /320/240/320/276/320/267/320/276/320/262/321/213/320/271.txt" +13 -0
- package/examples/no-loop/11. /320/227/320/260/321/211/320/270/321/202/320/275/321/213/320/271.txt" +9 -0
- package/examples/no-loop/12. /320/221/320/276/320/273/320/276/321/202/320/275/321/213/320/271.txt" +9 -0
- package/examples/no-loop/13. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.txt" +15 -0
- package/examples/no-loop/14. /320/227/320/276/320/273/320/276/321/202/320/276/320/271.txt" +17 -0
- package/examples/no-loop/15. /320/241/320/270/320/275/320/270/320/271.txt" +20 -0
- package/examples/no-loop/16. /320/223/320/276/320/273/321/203/320/261/320/276/320/271.txt" +11 -0
- package/examples/no-loop/17. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.txt" +10 -0
- package/examples/no-loop/18. /320/241/321/202/320/260/320/273/321/214/320/275/320/276/320/271.txt" +15 -0
- package/examples/no-loop/19. Lilla.txt +11 -0
- package/examples/no-loop/20. /320/227/320/276/320/273/320/276/321/202/320/276/320/271 - /320/273/320/265/320/262/321/213/320/271 final.txt" +16 -0
- package/examples/no-loop/21. /320/227/320/276/320/273/320/276/321/202/320/276/320/271 - /320/277/321/200/320/260/320/262/321/213/320/271 final.txt" +17 -0
- package/examples/no-loop/Adaptive design.txt +31 -0
- package/examples/no-loop/And test.txt +9 -0
- package/examples/no-loop/Comments.txt +19 -0
- package/examples/no-loop/Logical_And.txt +9 -0
- package/examples/no-loop/Logical_And_Inv.txt +9 -0
- package/examples/no-loop/Logical_And_Inv_x2.txt +15 -0
- package/examples/no-loop/Logical_Or.txt +9 -0
- package/examples/no-loop/Logical_Or_Inv.txt +9 -0
- package/examples/no-loop/Mind one.txt +18 -0
- package/examples/no-loop/Or test.txt +9 -0
- package/examples/no-loop/Silhouette test 1.txt +31 -0
- package/examples/no-loop/badShortCircuit.txt +7 -0
- package/examples/no-loop/getToken.txt +34 -0
- package/examples/no-loop/monitorPaymentStatus.txt +25 -0
- package/examples/no-loop/sil2.txt +29 -0
- package/examples/no-loop/tmp.txt +35 -0
- package/examples/no-loop//320/241/320/265/320/274/320/260/320/275/321/202/320/270/321/207/320/265/321/201/320/272/320/276/320/265 /321/217/320/264/321/200/320/276.txt" +36 -0
- package/examples/parallel-3.drakon +49 -0
- package/examples/parallel-3.txt +12 -0
- package/examples/parallel-arrow-loop.drakon +44 -0
- package/examples/parallel-arrow-loop.txt +12 -0
- package/examples/parallel-empty-nested.drakon +40 -0
- package/examples/parallel-empty-nested.txt +11 -0
- package/examples/parallel-empty.drakon +27 -0
- package/examples/parallel-empty.txt +8 -0
- package/examples/parallel-nested.drakon +67 -0
- package/examples/parallel-nested.txt +16 -0
- package/examples/sil2.txt +1 -0
- package/examples/tmp.txt +2 -0
- package/examples//320/241/320/265/320/274/320/260/320/275/321/202/320/270/321/207/320/265/321/201/320/272/320/276/320/265 /321/217/320/264/321/200/320/276.free" +130 -0
- package/examples//320/241/320/265/320/274/320/260/320/275/321/202/320/270/321/207/320/265/321/201/320/272/320/276/320/265 /321/217/320/264/321/200/320/276.txt" +36 -0
- package/package.json +1 -1
- package/prompts/noloop/decrement_if_count.drakon +34 -0
- package/prompts/noloop/flow_no_loop.drakon +26 -0
- package/prompts/noloop/group_stack_by_id.drakon +56 -0
- package/prompts/noloop/increment_if_count.drakon +34 -0
- package/prompts/noloop/merge_incoming_branches.drakon +105 -0
- package/prompts/noloop/recurse_traversal.drakon +88 -0
- package/prompts/noloop/traverse_node.drakon +62 -0
- package/secondary/Secondary.drakon +72 -0
- package/src/browserTools.js +1 -1
- package/src/drakonToPromptStruct.js +4 -3
- package/src/drakonToStruct.js +170 -15
- package/src/drakongen.js +44 -19
- package/src/free.js +69 -0
- package/src/index.js +42 -15
- package/src/main.js +10 -4
- package/src/nodeTools.js +1 -1
- package/src/noloop.js +181 -0
- package/src/printPseudo.js +29 -3
- package/src/structFlow.js +381 -334
- package/src/technicalTree.js +24 -1
- package/src/translate.js +21 -3
- package/src/treeTools.js +21 -0
- package/test_secondary.js +14 -0
- package/.vscode/launch.json +0 -18
- package/exampleproject/.drakontech/history.json +0 -12
- package/exampleproject/.drakontech/opened.txt +0 -1
- package/examples/.drakontech/history.json +0 -124
- package/examples/.drakontech/opened.txt +0 -1
package/browser/drakongen.js
CHANGED
|
@@ -14,7 +14,7 @@ function htmlToString(html) {
|
|
|
14
14
|
|
|
15
15
|
root.childNodes.forEach((node) => {
|
|
16
16
|
if (node.tagName === 'P') {
|
|
17
|
-
output.push(node.textContent
|
|
17
|
+
output.push(node.textContent);
|
|
18
18
|
} else if (node.tagName === 'UL') {
|
|
19
19
|
node.childNodes.forEach((item) => {
|
|
20
20
|
if (item.tagName === 'LI') {
|
|
@@ -39,16 +39,17 @@ const {drakonToStruct} = require("./drakonToStruct");
|
|
|
39
39
|
const {printPseudo, printWithIndent, makeIndent} = require('./printPseudo');
|
|
40
40
|
const {addRange, sortByProperty} = require("./tools")
|
|
41
41
|
|
|
42
|
-
function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate) {
|
|
43
|
-
var diagram = drakonToStruct(drakonJson, name, filename, translate)
|
|
42
|
+
function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate, options) {
|
|
43
|
+
var diagram = drakonToStruct(drakonJson, name, filename, translate, htmlToString, options)
|
|
44
44
|
var lines = []
|
|
45
45
|
|
|
46
46
|
lines.push("## " + translate("Procedure") + " \"" + diagram.name + "\"")
|
|
47
|
+
lines.push("")
|
|
47
48
|
if (diagram.params) {
|
|
48
49
|
lines.push(translate("Parameters") + ":")
|
|
49
50
|
addRange(lines, htmlToString(diagram.params))
|
|
51
|
+
lines.push("")
|
|
50
52
|
}
|
|
51
|
-
lines.push("")
|
|
52
53
|
lines.push(translate("Algorithm") + ":")
|
|
53
54
|
|
|
54
55
|
if (diagram.branches.length === 0) {
|
|
@@ -153,13 +154,21 @@ function createMindNode(name) {
|
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
module.exports = { drakonToPseudocode, mindToTree };
|
|
156
|
-
},{"./drakonToStruct":3,"./printPseudo":
|
|
157
|
+
},{"./drakonToStruct":3,"./printPseudo":7,"./tools":10}],3:[function(require,module,exports){
|
|
157
158
|
const { structFlow, redirectNode } = require("./structFlow");
|
|
158
159
|
const { createError, remove } = require("./tools");
|
|
159
160
|
|
|
160
161
|
var translate;
|
|
161
162
|
|
|
162
|
-
function drakonToStruct(
|
|
163
|
+
function drakonToStruct(
|
|
164
|
+
drakonJson,
|
|
165
|
+
name,
|
|
166
|
+
filename,
|
|
167
|
+
translateFunction,
|
|
168
|
+
htmlToString,
|
|
169
|
+
options,
|
|
170
|
+
) {
|
|
171
|
+
options = options || {};
|
|
163
172
|
translate = translateFunction;
|
|
164
173
|
let drakonGraph;
|
|
165
174
|
try {
|
|
@@ -186,23 +195,112 @@ function drakonToStruct(drakonJson, name, filename, translateFunction) {
|
|
|
186
195
|
};
|
|
187
196
|
}
|
|
188
197
|
|
|
189
|
-
|
|
198
|
+
handleParallel(nodes, undefined, firstNodeId, {}, undefined);
|
|
199
|
+
buildTwoWayConnections(nodes, firstNodeId, htmlToString);
|
|
190
200
|
|
|
191
201
|
rewireSelectsMarkLoops(nodes, filename);
|
|
192
202
|
branches.forEach((branch) =>
|
|
193
|
-
checkBranchIsReferenced(
|
|
203
|
+
checkBranchIsReferenced(
|
|
204
|
+
branch,
|
|
205
|
+
firstNodeId,
|
|
206
|
+
filename,
|
|
207
|
+
options,
|
|
208
|
+
htmlToString,
|
|
209
|
+
),
|
|
194
210
|
);
|
|
195
211
|
rewireShortcircuit(nodes, filename);
|
|
196
212
|
branches.forEach((branch) => cutOffBranch(nodes, branch));
|
|
197
|
-
var branchTrees = structFlow(nodes, branches, filename, translate);
|
|
213
|
+
var branchTrees = structFlow(nodes, branches, filename, translate, options);
|
|
198
214
|
return {
|
|
199
215
|
name: name,
|
|
200
216
|
params: drakonGraph.params || "",
|
|
201
217
|
description: drakonGraph.description || "",
|
|
202
218
|
branches: branchTrees,
|
|
219
|
+
secondary: findSecondary(branchTrees, options, htmlToString),
|
|
203
220
|
};
|
|
204
221
|
}
|
|
205
222
|
|
|
223
|
+
function findSecondary(branchTrees, options, htmlToString) {
|
|
224
|
+
if (!options || !options.secondary) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
var ordinal = 0;
|
|
228
|
+
for (var branch of branchTrees) {
|
|
229
|
+
var name = htmlToString(branch.name)[0];
|
|
230
|
+
if (name === options.secondary) {
|
|
231
|
+
return ordinal;
|
|
232
|
+
}
|
|
233
|
+
ordinal++;
|
|
234
|
+
}
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function handleParallel(nodes, prevNode, nodeId, visited, proc) {
|
|
239
|
+
if (!nodeId) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
var node = nodes[nodeId];
|
|
243
|
+
if (node.type === "parend") {
|
|
244
|
+
if (!proc) {
|
|
245
|
+
throw new Error("handleParallel: no proc for parend");
|
|
246
|
+
}
|
|
247
|
+
var endId = proc.end;
|
|
248
|
+
var end;
|
|
249
|
+
if (endId) {
|
|
250
|
+
end = nodes[endId];
|
|
251
|
+
} else {
|
|
252
|
+
end = {
|
|
253
|
+
type: "end",
|
|
254
|
+
id: proc.id + "-" + proc.ordinal + "-end",
|
|
255
|
+
prev: [],
|
|
256
|
+
};
|
|
257
|
+
nodes[end.id] = end;
|
|
258
|
+
proc.end = end.id;
|
|
259
|
+
proc.next = node.one;
|
|
260
|
+
}
|
|
261
|
+
redirectNode(nodes, prevNode, nodeId, end.id);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (nodeId in visited) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
visited[nodeId] = true;
|
|
268
|
+
if (node.type === "parbegin") {
|
|
269
|
+
node.procs = [];
|
|
270
|
+
var ordinal = 0;
|
|
271
|
+
var current = node;
|
|
272
|
+
while (true) {
|
|
273
|
+
var start = {
|
|
274
|
+
id: nodeId + "-" + ordinal + "-start",
|
|
275
|
+
type: "action",
|
|
276
|
+
prev: [],
|
|
277
|
+
one: current.one,
|
|
278
|
+
};
|
|
279
|
+
nodes[start.id] = start;
|
|
280
|
+
var childProc = {
|
|
281
|
+
id: nodeId,
|
|
282
|
+
ordinal: ordinal,
|
|
283
|
+
start: start.id,
|
|
284
|
+
};
|
|
285
|
+
var next = current.two;
|
|
286
|
+
node.procs.push(childProc);
|
|
287
|
+
handleParallel(nodes, start, start.one, {}, childProc);
|
|
288
|
+
delete current.one;
|
|
289
|
+
delete current.two;
|
|
290
|
+
if (!next) {
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
current = nodes[next];
|
|
294
|
+
ordinal++;
|
|
295
|
+
}
|
|
296
|
+
node.one = node.procs[0].next;
|
|
297
|
+
handleParallel(nodes, node, node.one, visited, proc);
|
|
298
|
+
} else {
|
|
299
|
+
handleParallel(nodes, node, node.one, visited, proc);
|
|
300
|
+
handleParallel(nodes, node, node.two, visited, proc);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
206
304
|
function drakonToGraph(drakonJson, name, filename, translateFunction) {
|
|
207
305
|
translate = translateFunction;
|
|
208
306
|
let drakonGraph;
|
|
@@ -227,7 +325,13 @@ function drakonToGraph(drakonJson, name, filename, translateFunction) {
|
|
|
227
325
|
rewireSelectsMarkLoops(nodes, filename);
|
|
228
326
|
rewireShortcircuit(nodes, filename);
|
|
229
327
|
branches.forEach((branch) =>
|
|
230
|
-
checkBranchIsReferenced(
|
|
328
|
+
checkBranchIsReferenced(
|
|
329
|
+
branch,
|
|
330
|
+
firstNodeId,
|
|
331
|
+
filename,
|
|
332
|
+
undefined,
|
|
333
|
+
undefined,
|
|
334
|
+
),
|
|
231
335
|
);
|
|
232
336
|
branches.forEach((branch) => cutOffBranch(nodes, branch));
|
|
233
337
|
|
|
@@ -241,16 +345,35 @@ function drakonToGraph(drakonJson, name, filename, translateFunction) {
|
|
|
241
345
|
};
|
|
242
346
|
}
|
|
243
347
|
|
|
244
|
-
function checkBranchIsReferenced(
|
|
348
|
+
function checkBranchIsReferenced(
|
|
349
|
+
branch,
|
|
350
|
+
firstNodeId,
|
|
351
|
+
filename,
|
|
352
|
+
options,
|
|
353
|
+
htmlToString,
|
|
354
|
+
) {
|
|
245
355
|
if (branch.id === firstNodeId) {
|
|
246
356
|
return;
|
|
247
357
|
}
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
358
|
+
if (options && htmlToString) {
|
|
359
|
+
var branchName = htmlToString(branch.content)[0];
|
|
360
|
+
if (branchName === options.secondary) {
|
|
361
|
+
if (branch.prev.length > 0) {
|
|
362
|
+
throw createError(
|
|
363
|
+
translate("A secondary branch is referenced"),
|
|
364
|
+
filename,
|
|
365
|
+
branch.id,
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
if (branch.prev.length === 0) {
|
|
370
|
+
throw createError(
|
|
371
|
+
translate("A silhouette branch is not referenced"),
|
|
372
|
+
filename,
|
|
373
|
+
branch.id,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
254
377
|
}
|
|
255
378
|
}
|
|
256
379
|
|
|
@@ -327,14 +450,18 @@ function addFakeEnd(nodes, prev, node, end, addresses) {
|
|
|
327
450
|
node.prev = remove(node.prev, prev.id);
|
|
328
451
|
}
|
|
329
452
|
|
|
330
|
-
function buildTwoWayConnections(nodes, firstNodeId) {
|
|
453
|
+
function buildTwoWayConnections(nodes, firstNodeId, htmlToString) {
|
|
331
454
|
for (var id in nodes) {
|
|
332
455
|
var node = nodes[id];
|
|
333
456
|
node.id = id;
|
|
334
457
|
node.prev = [];
|
|
335
458
|
}
|
|
336
459
|
|
|
337
|
-
|
|
460
|
+
var visitor = function (nodes, node) {
|
|
461
|
+
return connectBack(nodes, node, htmlToString);
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
traverse(nodes, firstNodeId, {}, visitor);
|
|
338
465
|
}
|
|
339
466
|
|
|
340
467
|
function findStartNode(nodes, filename, branches) {
|
|
@@ -373,6 +500,9 @@ function findStartNode(nodes, filename, branches) {
|
|
|
373
500
|
id,
|
|
374
501
|
);
|
|
375
502
|
}
|
|
503
|
+
} else if (node.final) {
|
|
504
|
+
delete node.one
|
|
505
|
+
delete node.two
|
|
376
506
|
}
|
|
377
507
|
}
|
|
378
508
|
|
|
@@ -395,6 +525,7 @@ function rewireSelectsMarkLoops(nodes, filename) {
|
|
|
395
525
|
|
|
396
526
|
function rewireSelect(nodes, selectNode, filename) {
|
|
397
527
|
var caseNodeId = selectNode.one;
|
|
528
|
+
var caseNode0 = nodes[caseNodeId];
|
|
398
529
|
while (caseNodeId) {
|
|
399
530
|
var caseNode = nodes[caseNodeId];
|
|
400
531
|
caseNodeId = caseNode.two;
|
|
@@ -434,6 +565,7 @@ function rewireSelect(nodes, selectNode, filename) {
|
|
|
434
565
|
removeNodeOne(nodes, caseNode.id);
|
|
435
566
|
}
|
|
436
567
|
}
|
|
568
|
+
caseNode0.side = selectNode.side;
|
|
437
569
|
removeNodeOne(nodes, selectNode.id);
|
|
438
570
|
}
|
|
439
571
|
|
|
@@ -608,9 +740,14 @@ function traverse(nodes, nodeId, visited, action) {
|
|
|
608
740
|
action(nodes, node);
|
|
609
741
|
traverse(nodes, node.one, visited, action);
|
|
610
742
|
traverse(nodes, node.two, visited, action);
|
|
743
|
+
if (node.procs) {
|
|
744
|
+
for (var proc of node.procs) {
|
|
745
|
+
traverse(nodes, proc.start, visited, action);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
611
748
|
}
|
|
612
749
|
|
|
613
|
-
function connectBack(nodes, node) {
|
|
750
|
+
function connectBack(nodes, node, htmlToString) {
|
|
614
751
|
if (node.one) {
|
|
615
752
|
var one = nodes[node.one];
|
|
616
753
|
one.prev.push(node.id);
|
|
@@ -619,6 +756,25 @@ function connectBack(nodes, node) {
|
|
|
619
756
|
var two = nodes[node.two];
|
|
620
757
|
two.prev.push(node.id);
|
|
621
758
|
}
|
|
759
|
+
|
|
760
|
+
if (node.side) {
|
|
761
|
+
var side = nodes[node.side].content;
|
|
762
|
+
if (side) {
|
|
763
|
+
node.side = decodeSide(side, htmlToString);
|
|
764
|
+
} else {
|
|
765
|
+
delete node.side;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function decodeSide(content, htmlToString) {
|
|
771
|
+
var text = htmlToString(content);
|
|
772
|
+
var oneLine = text.join(" ");
|
|
773
|
+
if (oneLine.indexOf("=") === -1) {
|
|
774
|
+
return translate("Do for") + " " + oneLine;
|
|
775
|
+
} else {
|
|
776
|
+
return translate("Start at") + " " + oneLine;
|
|
777
|
+
}
|
|
622
778
|
}
|
|
623
779
|
|
|
624
780
|
function markLoopBody(nodes, start, filename) {
|
|
@@ -641,32 +797,310 @@ function markLoopBody(nodes, start, filename) {
|
|
|
641
797
|
|
|
642
798
|
module.exports = { drakonToStruct, drakonToGraph };
|
|
643
799
|
|
|
644
|
-
},{"./structFlow":
|
|
645
|
-
const { drakonToPseudocode, mindToTree } = require(
|
|
646
|
-
const { htmlToString } = require("./browserTools")
|
|
647
|
-
const { setUpLanguage, translate } = require("./translate")
|
|
800
|
+
},{"./structFlow":8,"./tools":10}],4:[function(require,module,exports){
|
|
801
|
+
const { drakonToPseudocode, mindToTree } = require("./drakonToPromptStruct");
|
|
802
|
+
const { htmlToString } = require("./browserTools");
|
|
803
|
+
const { setUpLanguage, translate } = require("./translate");
|
|
648
804
|
const { drakonToStruct } = require("./drakonToStruct");
|
|
649
|
-
|
|
805
|
+
const { freeDiagramToText } = require("./free");
|
|
650
806
|
|
|
651
807
|
window.drakongen = {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
808
|
+
toPseudocode: function (drakonJson, name, filename, language) {
|
|
809
|
+
setUpLanguage(language);
|
|
810
|
+
return drakonToPseudocode(
|
|
811
|
+
drakonJson,
|
|
812
|
+
name,
|
|
813
|
+
filename,
|
|
814
|
+
htmlToString,
|
|
815
|
+
translate,
|
|
816
|
+
).text;
|
|
817
|
+
},
|
|
818
|
+
|
|
819
|
+
toMindTree: function (mindJson, name, filename, language) {
|
|
820
|
+
setUpLanguage(language);
|
|
821
|
+
var result = mindToTree(mindJson, name, filename, htmlToString);
|
|
822
|
+
return result.text;
|
|
823
|
+
},
|
|
824
|
+
|
|
825
|
+
freeToText: function (freeJson, name, filename, language) {
|
|
826
|
+
setUpLanguage(language);
|
|
827
|
+
var result = freeDiagramToText(
|
|
828
|
+
freeJson,
|
|
829
|
+
name,
|
|
830
|
+
filename,
|
|
831
|
+
translate,
|
|
832
|
+
htmlToString,
|
|
833
|
+
);
|
|
834
|
+
return result.text;
|
|
835
|
+
},
|
|
836
|
+
|
|
837
|
+
toTree: function (drakonJson, name, filename, language, options) {
|
|
838
|
+
setUpLanguage(language);
|
|
839
|
+
var result = drakonToStruct(
|
|
840
|
+
drakonJson,
|
|
841
|
+
name,
|
|
842
|
+
filename,
|
|
843
|
+
translate,
|
|
844
|
+
htmlToString,
|
|
845
|
+
options,
|
|
846
|
+
);
|
|
847
|
+
return JSON.stringify(result, null, 4);
|
|
848
|
+
},
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
},{"./browserTools":1,"./drakonToPromptStruct":2,"./drakonToStruct":3,"./free":5,"./translate":11}],5:[function(require,module,exports){
|
|
852
|
+
var {addRange} = require("./tools")
|
|
853
|
+
const { createError } = require("./tools");
|
|
656
854
|
|
|
657
|
-
|
|
658
|
-
setUpLanguage(language)
|
|
659
|
-
var result = mindToTree(mindJson, name, filename, htmlToString)
|
|
660
|
-
return result.text
|
|
661
|
-
},
|
|
855
|
+
var translate
|
|
662
856
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
857
|
+
function compareVertically(box1, box2) {
|
|
858
|
+
if (box1.top + box1.height <= box2.top) return -1;
|
|
859
|
+
if (box2.top + box2.height <= box1.top) return 1;
|
|
860
|
+
return 0;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function compareHorizontally(box1, box2) {
|
|
864
|
+
if (box1.left + box1.width <= box2.left) return -1;
|
|
865
|
+
if (box2.left + box2.width <= box1.left) return 1;
|
|
866
|
+
return 0;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
function byTopLeft(box1, box2) {
|
|
870
|
+
var vertical = compareVertically(box1, box2)
|
|
871
|
+
if (vertical == 0) {
|
|
872
|
+
return compareHorizontally(box1, box2)
|
|
873
|
+
}
|
|
874
|
+
return vertical
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
function parseDiagram(freeJson, filename) {
|
|
878
|
+
let diagram;
|
|
879
|
+
try {
|
|
880
|
+
freeJson = freeJson || ""
|
|
881
|
+
freeJson = freeJson.trim()
|
|
882
|
+
freeJson = freeJson || "{}"
|
|
883
|
+
diagram = JSON.parse(freeJson);
|
|
884
|
+
} catch (error) {
|
|
885
|
+
var message = translate("Error parsing JSON") + ": " + error.message
|
|
886
|
+
throw createError(message, filename)
|
|
887
|
+
}
|
|
888
|
+
return diagram
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
function sortedItems(diagram) {
|
|
892
|
+
var items = diagram.items || {};
|
|
893
|
+
var result = [];
|
|
894
|
+
for (var id in items) {
|
|
895
|
+
var item = items[id];
|
|
896
|
+
if (item.content && item.top && item.left && item.width && item.height) {
|
|
897
|
+
result.push(item);
|
|
898
|
+
}
|
|
667
899
|
}
|
|
900
|
+
result.sort(byTopLeft);
|
|
901
|
+
return result;
|
|
668
902
|
}
|
|
669
|
-
|
|
903
|
+
|
|
904
|
+
function freeDiagramToText(freeJson, name, filename, translateFunction, htmlToString) {
|
|
905
|
+
translate = translateFunction
|
|
906
|
+
var diagram = parseDiagram(freeJson, filename)
|
|
907
|
+
var sorted = sortedItems(diagram)
|
|
908
|
+
var lines = []
|
|
909
|
+
lines.push("## " + name)
|
|
910
|
+
lines.push("")
|
|
911
|
+
for (var item of sorted) {
|
|
912
|
+
var content = htmlToString(item.content)
|
|
913
|
+
addRange(lines, content)
|
|
914
|
+
lines.push("")
|
|
915
|
+
}
|
|
916
|
+
var text = lines.join("\n")
|
|
917
|
+
return {text:text}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
module.exports = {freeDiagramToText}
|
|
921
|
+
},{"./tools":10}],6:[function(require,module,exports){
|
|
922
|
+
"use strict";
|
|
923
|
+
|
|
924
|
+
function decrement_if_count(context, node) {
|
|
925
|
+
var i;
|
|
926
|
+
var if_id;
|
|
927
|
+
var if_node;
|
|
928
|
+
|
|
929
|
+
for (i = 0; i < node.stack.length; i++) {
|
|
930
|
+
if_id = node.stack[i];
|
|
931
|
+
if_node = context.nodes[if_id];
|
|
932
|
+
if_node.branching--;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
function flow_no_loop(nodes, start_node_id) {
|
|
937
|
+
var context;
|
|
938
|
+
|
|
939
|
+
context = {
|
|
940
|
+
nodes: nodes
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
traverse_node(
|
|
944
|
+
context,
|
|
945
|
+
start_node_id,
|
|
946
|
+
[]
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
function group_stack_by_id(stack) {
|
|
951
|
+
var counts_by_id;
|
|
952
|
+
var i;
|
|
953
|
+
var element;
|
|
954
|
+
var existing;
|
|
955
|
+
|
|
956
|
+
counts_by_id = {};
|
|
957
|
+
|
|
958
|
+
for (i = 0; i < stack.length; i++) {
|
|
959
|
+
element = stack[i];
|
|
960
|
+
|
|
961
|
+
if (element in counts_by_id) {
|
|
962
|
+
existing = counts_by_id[element];
|
|
963
|
+
} else {
|
|
964
|
+
existing = 0;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
counts_by_id[element] = existing + 1;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
return counts_by_id;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function increment_if_count(context, node) {
|
|
974
|
+
var i;
|
|
975
|
+
var if_id;
|
|
976
|
+
var if_node;
|
|
977
|
+
|
|
978
|
+
for (i = 0; i < node.stack.length; i++) {
|
|
979
|
+
if_id = node.stack[i];
|
|
980
|
+
if_node = context.nodes[if_id];
|
|
981
|
+
if_node.branching++;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
function merge_incoming_branches(context, node_id, node, stack) {
|
|
986
|
+
var common;
|
|
987
|
+
var counts_by_id;
|
|
988
|
+
var processed_stack;
|
|
989
|
+
var ids;
|
|
990
|
+
var i;
|
|
991
|
+
var id;
|
|
992
|
+
var count;
|
|
993
|
+
var if_node;
|
|
994
|
+
|
|
995
|
+
common = node.stack.concat(stack);
|
|
996
|
+
counts_by_id = group_stack_by_id(common);
|
|
997
|
+
processed_stack = [];
|
|
998
|
+
|
|
999
|
+
ids = Object.keys(counts_by_id);
|
|
1000
|
+
|
|
1001
|
+
for (i = 0; i < ids.length; i++) {
|
|
1002
|
+
id = ids[i];
|
|
1003
|
+
count = counts_by_id[id];
|
|
1004
|
+
|
|
1005
|
+
if_node = context.nodes[id];
|
|
1006
|
+
|
|
1007
|
+
if (!if_node.next) {
|
|
1008
|
+
if (if_node.branching === 1) {
|
|
1009
|
+
if_node.next = node_id;
|
|
1010
|
+
} else {
|
|
1011
|
+
if_node.branching -= count - 1;
|
|
1012
|
+
|
|
1013
|
+
if (if_node.branching === 1) {
|
|
1014
|
+
if_node.next = node_id;
|
|
1015
|
+
} else {
|
|
1016
|
+
processed_stack.push(id);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
node.stack = processed_stack;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function recurse_traversal(context, node_id, node) {
|
|
1026
|
+
var stack1;
|
|
1027
|
+
var stack2;
|
|
1028
|
+
|
|
1029
|
+
if (node.type === "question") {
|
|
1030
|
+
increment_if_count(
|
|
1031
|
+
context,
|
|
1032
|
+
node
|
|
1033
|
+
);
|
|
1034
|
+
|
|
1035
|
+
stack1 = node.stack.slice();
|
|
1036
|
+
stack1.push(node_id);
|
|
1037
|
+
|
|
1038
|
+
stack2 = node.stack.slice();
|
|
1039
|
+
stack2.push(node_id);
|
|
1040
|
+
|
|
1041
|
+
traverse_node(
|
|
1042
|
+
context,
|
|
1043
|
+
node.one,
|
|
1044
|
+
stack1
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
traverse_node(
|
|
1048
|
+
context,
|
|
1049
|
+
node.two,
|
|
1050
|
+
stack2
|
|
1051
|
+
);
|
|
1052
|
+
} else {
|
|
1053
|
+
if (node.final) {
|
|
1054
|
+
decrement_if_count(
|
|
1055
|
+
context,
|
|
1056
|
+
node
|
|
1057
|
+
);
|
|
1058
|
+
} else {
|
|
1059
|
+
stack1 = node.stack.slice();
|
|
1060
|
+
|
|
1061
|
+
traverse_node(
|
|
1062
|
+
context,
|
|
1063
|
+
node.one,
|
|
1064
|
+
stack1
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
function traverse_node(context, node_id, stack) {
|
|
1071
|
+
var node;
|
|
1072
|
+
|
|
1073
|
+
if (node_id) {
|
|
1074
|
+
node = context.nodes[node_id];
|
|
1075
|
+
|
|
1076
|
+
if (!node.stack) {
|
|
1077
|
+
node.stack = [];
|
|
1078
|
+
node.refs = node.prev.length;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
node.refs--;
|
|
1082
|
+
|
|
1083
|
+
merge_incoming_branches(
|
|
1084
|
+
context,
|
|
1085
|
+
node_id,
|
|
1086
|
+
node,
|
|
1087
|
+
stack
|
|
1088
|
+
);
|
|
1089
|
+
|
|
1090
|
+
if (!(node.refs > 0)) {
|
|
1091
|
+
recurse_traversal(
|
|
1092
|
+
context,
|
|
1093
|
+
node_id,
|
|
1094
|
+
node
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
module.exports = {
|
|
1101
|
+
flow_no_loop: flow_no_loop
|
|
1102
|
+
};
|
|
1103
|
+
},{}],7:[function(require,module,exports){
|
|
670
1104
|
var {addRange} = require("./tools")
|
|
671
1105
|
|
|
672
1106
|
function makeIndent(depth) {
|
|
@@ -679,8 +1113,11 @@ function printWithIndent(lines, indent, output) {
|
|
|
679
1113
|
}
|
|
680
1114
|
|
|
681
1115
|
function printPseudo(algorithm, translate, output, htmlToString) {
|
|
682
|
-
function printStructuredContent(content, indent, output) {
|
|
1116
|
+
function printStructuredContent(content, indent, output, side) {
|
|
683
1117
|
var lines = printStructuredContentNoIdent(content)
|
|
1118
|
+
if (side) {
|
|
1119
|
+
lines[0] = side + ": " + lines[0]
|
|
1120
|
+
}
|
|
684
1121
|
printWithIndent(lines, indent, output)
|
|
685
1122
|
}
|
|
686
1123
|
|
|
@@ -744,19 +1181,39 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
744
1181
|
printError(step, indent, output)
|
|
745
1182
|
} else if (step.type === "break") {
|
|
746
1183
|
output.push(indent + translate("break"))
|
|
1184
|
+
} else if (step.type === "parbegin") {
|
|
1185
|
+
printParbegin(step, depth, output)
|
|
747
1186
|
} else {
|
|
748
1187
|
printOther(step, indent, output)
|
|
749
1188
|
}
|
|
750
1189
|
}
|
|
751
1190
|
}
|
|
1191
|
+
|
|
1192
|
+
function printParbegin(step, depth, output) {
|
|
1193
|
+
const indent2 = makeIndent(depth + 1)
|
|
1194
|
+
const indent = makeIndent(depth)
|
|
1195
|
+
printWithIndent([translate("Group of parallel processes")], indent, output)
|
|
1196
|
+
for (var proc of step.procs) {
|
|
1197
|
+
printWithIndent([translate("Parallel process") + " " + (proc.ordinal + 1)], indent2, output)
|
|
1198
|
+
printSteps(proc.body, depth + 2, output)
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
752
1201
|
|
|
753
1202
|
function printOther(step, indent, output) {
|
|
1203
|
+
var side = step.side
|
|
754
1204
|
if (!step.content && !step.secondary) {return}
|
|
755
1205
|
if (step.secondary) {
|
|
756
|
-
printStructuredContent(step.secondary, indent, output)
|
|
1206
|
+
printStructuredContent(step.secondary, indent, output, side)
|
|
1207
|
+
side = undefined
|
|
757
1208
|
}
|
|
758
1209
|
if (step.content) {
|
|
759
|
-
|
|
1210
|
+
var content = step.content
|
|
1211
|
+
if (step.type === "pause") {
|
|
1212
|
+
content = translate("Pause") + " " + htmlToString(content).join(" ")
|
|
1213
|
+
} else if (step.type === "timer") {
|
|
1214
|
+
content = translate("Start timer") + " " + htmlToString(content).join(" ")
|
|
1215
|
+
}
|
|
1216
|
+
printStructuredContent(content, indent, output, side)
|
|
760
1217
|
}
|
|
761
1218
|
}
|
|
762
1219
|
|
|
@@ -797,6 +1254,9 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
797
1254
|
var content = step.content
|
|
798
1255
|
var lines = printStructuredContentNoIdent(content)
|
|
799
1256
|
lines[0] = translate("if") + " " + lines[0]
|
|
1257
|
+
if (step.side) {
|
|
1258
|
+
lines[0] = step.side + ": " + lines[0]
|
|
1259
|
+
}
|
|
800
1260
|
printWithIndent(lines, indent, output)
|
|
801
1261
|
addRange(output, yesBody)
|
|
802
1262
|
if (!empty(noBody)) {
|
|
@@ -825,392 +1285,440 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
825
1285
|
}
|
|
826
1286
|
|
|
827
1287
|
module.exports = {printPseudo, printWithIndent, makeIndent}
|
|
828
|
-
},{"./tools":
|
|
829
|
-
var {buildTree} = require("./technicalTree")
|
|
1288
|
+
},{"./tools":10}],8:[function(require,module,exports){
|
|
1289
|
+
var { buildTree } = require("./technicalTree");
|
|
830
1290
|
const { createError, sortByProperty } = require("./tools");
|
|
831
|
-
const { optimizeTree } = require("./treeTools")
|
|
1291
|
+
const { optimizeTree } = require("./treeTools");
|
|
1292
|
+
const { flow_no_loop } = require("./noloop")
|
|
832
1293
|
|
|
833
1294
|
function redirectNode(nodes, node, from, to) {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
}
|
|
1295
|
+
if (node.one === from) {
|
|
1296
|
+
node.one = to;
|
|
1297
|
+
}
|
|
1298
|
+
if (node.two === from) {
|
|
1299
|
+
node.two = to;
|
|
1300
|
+
}
|
|
1301
|
+
if (node.next === from) {
|
|
1302
|
+
node.next = to;
|
|
1303
|
+
}
|
|
1304
|
+
if (node.start && node.type === "loopend") {
|
|
1305
|
+
start = nodes[node.start];
|
|
1306
|
+
if (start.next === from) {
|
|
1307
|
+
start.next = to;
|
|
848
1308
|
}
|
|
1309
|
+
}
|
|
849
1310
|
}
|
|
850
1311
|
|
|
851
|
-
function structFlow(nodes, branches, filename, translate) {
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
if (!nodeId) {return;}
|
|
857
|
-
|
|
858
|
-
const node = nodes[nodeId];
|
|
1312
|
+
function structFlow(nodes, branches, filename, translate, options) {
|
|
1313
|
+
function flowGraph(nodes, nodeId, branchingStack) {
|
|
1314
|
+
if (!nodeId) {
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
859
1317
|
|
|
860
|
-
|
|
861
|
-
node.stack = [];
|
|
862
|
-
node.remaining = node.prev.length;
|
|
863
|
-
}
|
|
864
|
-
node.remaining--;
|
|
1318
|
+
const node = nodes[nodeId];
|
|
865
1319
|
|
|
866
|
-
|
|
867
|
-
|
|
1320
|
+
if (!node.stack) {
|
|
1321
|
+
node.stack = [];
|
|
1322
|
+
node.remaining = node.prev.length;
|
|
1323
|
+
}
|
|
1324
|
+
node.remaining--;
|
|
868
1325
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
question.branching++;
|
|
874
|
-
}
|
|
1326
|
+
mergeBranchingStack(nodes, node, branchingStack);
|
|
1327
|
+
if (node.remaining > 0) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
875
1330
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
1331
|
+
if (node.type === "question") {
|
|
1332
|
+
for (let i = 0; i < node.stack.length; i++) {
|
|
1333
|
+
const questionId = node.stack[i];
|
|
1334
|
+
const question = nodes[questionId];
|
|
1335
|
+
question.branching++;
|
|
1336
|
+
}
|
|
880
1337
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1338
|
+
const stackOne = node.stack.slice();
|
|
1339
|
+
const stackTwo = node.stack.slice();
|
|
1340
|
+
stackOne.push(nodeId);
|
|
1341
|
+
stackTwo.push(nodeId);
|
|
1342
|
+
|
|
1343
|
+
flowGraph(nodes, node.two, stackTwo);
|
|
1344
|
+
flowGraph(nodes, node.one, stackOne);
|
|
1345
|
+
} else if (node.type === "arrow-loop") {
|
|
1346
|
+
const stackOne = node.stack.slice();
|
|
1347
|
+
stackOne.push(nodeId);
|
|
1348
|
+
flowGraph(nodes, node.one, stackOne);
|
|
1349
|
+
} else if (node.type === "arrow-stub") {
|
|
1350
|
+
decrementBranchingForArrow(nodes, node);
|
|
1351
|
+
} else if (node.type === "parbegin") {
|
|
1352
|
+
for (var proc of node.procs) {
|
|
1353
|
+
flowGraph(nodes, proc.start, []);
|
|
1354
|
+
}
|
|
1355
|
+
flowGraph(nodes, node.one, node.stack);
|
|
1356
|
+
} else {
|
|
1357
|
+
flowGraph(nodes, node.one, node.stack);
|
|
892
1358
|
}
|
|
1359
|
+
}
|
|
893
1360
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1361
|
+
function decrementBranchingForArrow(nodes, node) {
|
|
1362
|
+
var algonode = nodes[node.arrow];
|
|
1363
|
+
algonode.branching--;
|
|
1364
|
+
}
|
|
898
1365
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
}
|
|
1366
|
+
function decrementQuestions(nodes, algonode, dictionary) {
|
|
1367
|
+
var stub = nodes[algonode.stub];
|
|
1368
|
+
for (var id of stub.stack) {
|
|
1369
|
+
var snode = nodes[id];
|
|
1370
|
+
if (id !== algonode.id) {
|
|
1371
|
+
if (id in dictionary) {
|
|
1372
|
+
snode.branching--;
|
|
908
1373
|
}
|
|
909
|
-
|
|
1374
|
+
}
|
|
910
1375
|
}
|
|
1376
|
+
return stub;
|
|
1377
|
+
}
|
|
911
1378
|
|
|
1379
|
+
function mergeBranchingStack(nodes, node, branchingStack) {
|
|
1380
|
+
// Append all elements of the branching stack to node.stack
|
|
1381
|
+
addRange(node.stack, branchingStack);
|
|
912
1382
|
|
|
1383
|
+
// Build a dictionary of occurrences
|
|
1384
|
+
const dictionary = buildDictionaryOfOccurences(node);
|
|
913
1385
|
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
addRange(node.stack, branchingStack)
|
|
1386
|
+
// Merge all nodes
|
|
1387
|
+
mergeAll(nodes, node, dictionary);
|
|
917
1388
|
|
|
918
|
-
|
|
919
|
-
|
|
1389
|
+
// Rebuild the stack
|
|
1390
|
+
node.stack = buildStackFromDictionary(dictionary);
|
|
1391
|
+
}
|
|
920
1392
|
|
|
921
|
-
|
|
922
|
-
|
|
1393
|
+
function addRange(dst, src) {
|
|
1394
|
+
for (let i = 0; i < src.length; i++) {
|
|
1395
|
+
dst.push(src[i]);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
923
1398
|
|
|
924
|
-
|
|
925
|
-
|
|
1399
|
+
function buildStackFromDictionary(dictionary) {
|
|
1400
|
+
const rebuiltStack = [];
|
|
1401
|
+
for (const id in dictionary) {
|
|
1402
|
+
if (dictionary[id] > 0) {
|
|
1403
|
+
rebuiltStack.push(id);
|
|
1404
|
+
}
|
|
926
1405
|
}
|
|
1406
|
+
return rebuiltStack;
|
|
1407
|
+
}
|
|
927
1408
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1409
|
+
function buildDictionaryOfOccurences(node) {
|
|
1410
|
+
const dictionary = {};
|
|
1411
|
+
for (let i = 0; i < node.stack.length; i++) {
|
|
1412
|
+
const id = node.stack[i];
|
|
1413
|
+
dictionary[id] = (dictionary[id] || 0) + 1;
|
|
932
1414
|
}
|
|
1415
|
+
return dictionary;
|
|
1416
|
+
}
|
|
933
1417
|
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1418
|
+
function mergeAll(nodes, node, dictionary) {
|
|
1419
|
+
for (const id in dictionary) {
|
|
1420
|
+
const occurrences = dictionary[id];
|
|
1421
|
+
const algonode = nodes[id];
|
|
1422
|
+
if (occurrences > 1) {
|
|
1423
|
+
algonode.branching--;
|
|
1424
|
+
dictionary[id] = occurrences - 1;
|
|
1425
|
+
}
|
|
1426
|
+
if (algonode.branching === 1) {
|
|
1427
|
+
if (algonode.type === "arrow-loop" && !algonode.next) {
|
|
1428
|
+
if (!isInMap(node.astack, id)) {
|
|
1429
|
+
algonode.next = node.id;
|
|
1430
|
+
dictionary[algonode.id] = 0;
|
|
1431
|
+
var stub = decrementQuestions(nodes, algonode, dictionary);
|
|
1432
|
+
stub.one = node.id;
|
|
1433
|
+
}
|
|
940
1434
|
}
|
|
941
|
-
|
|
1435
|
+
}
|
|
942
1436
|
}
|
|
943
1437
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1438
|
+
for (const id in dictionary) {
|
|
1439
|
+
const algonode = nodes[id];
|
|
1440
|
+
if (algonode.branching === 1) {
|
|
1441
|
+
if (algonode.type === "question") {
|
|
1442
|
+
algonode.next = node.id;
|
|
1443
|
+
dictionary[algonode.id] = 0;
|
|
949
1444
|
}
|
|
950
|
-
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
function isInMap(map, key) {
|
|
1449
|
+
if (!map) {
|
|
1450
|
+
return false;
|
|
951
1451
|
}
|
|
1452
|
+
return key in map;
|
|
1453
|
+
}
|
|
952
1454
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
if (algonode.branching === 1) {
|
|
962
|
-
if (algonode.type === "arrow-loop" && !algonode.next) {
|
|
963
|
-
if (!isInMap(node.astack, id)) {
|
|
964
|
-
algonode.next = node.id
|
|
965
|
-
dictionary[algonode.id] = 0;
|
|
966
|
-
var stub = decrementQuestions(nodes, algonode, dictionary)
|
|
967
|
-
stub.one = node.id
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
for (const id in dictionary) {
|
|
974
|
-
const algonode = nodes[id];
|
|
975
|
-
if (algonode.branching === 1) {
|
|
976
|
-
if (algonode.type === "question") {
|
|
977
|
-
algonode.next = node.id;
|
|
978
|
-
dictionary[algonode.id] = 0;
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
}
|
|
1455
|
+
function prepareQuestions(nodes) {
|
|
1456
|
+
for (const nodeId in nodes) {
|
|
1457
|
+
const node = nodes[nodeId];
|
|
1458
|
+
if (node.type === "question") {
|
|
1459
|
+
node.branching = 2;
|
|
1460
|
+
} else if (node.type === "arrow-loop") {
|
|
1461
|
+
node.branching = 1;
|
|
1462
|
+
}
|
|
982
1463
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
function rewireArrows(nodes, branches) {
|
|
1467
|
+
branches.forEach((branch) =>
|
|
1468
|
+
rewireArrowsInBranch(nodes, branch.id, branch.next, []),
|
|
1469
|
+
);
|
|
1470
|
+
for (var id in nodes) {
|
|
1471
|
+
var node = nodes[id];
|
|
1472
|
+
if (node.type === "arrow-loop") {
|
|
1473
|
+
var stub = insertArrowStub(nodes, node);
|
|
1474
|
+
var visited = {};
|
|
1475
|
+
fillAStack(nodes, stub, stub.arrow, visited);
|
|
1476
|
+
}
|
|
986
1477
|
}
|
|
1478
|
+
}
|
|
987
1479
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
if (node.type === "question") {
|
|
992
|
-
node.branching = 2;
|
|
993
|
-
} else if (node.type === "arrow-loop") {
|
|
994
|
-
node.branching = 1;
|
|
995
|
-
}
|
|
996
|
-
}
|
|
1480
|
+
function fillAStack(nodes, node, arrowId, visited) {
|
|
1481
|
+
if (node.id in visited) {
|
|
1482
|
+
return;
|
|
997
1483
|
}
|
|
1484
|
+
visited[node.id] = true;
|
|
1485
|
+
if (!node.astack) {
|
|
1486
|
+
node.astack = {};
|
|
1487
|
+
}
|
|
1488
|
+
node.astack[arrowId] = true;
|
|
1489
|
+
if (node.id === arrowId) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
for (var prevId of node.prev) {
|
|
1493
|
+
var prev = nodes[prevId];
|
|
1494
|
+
fillAStack(nodes, prev, arrowId, visited);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
998
1497
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
var node = nodes[id]
|
|
1003
|
-
if (node.type === "arrow-loop") {
|
|
1004
|
-
var stub = insertArrowStub(nodes, node)
|
|
1005
|
-
fillAStack(nodes, stub, stub.arrow)
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1498
|
+
function rewireArrowsInBranch(nodes, prevNodeId, nodeId, arrowStack) {
|
|
1499
|
+
if (!nodeId) {
|
|
1500
|
+
return;
|
|
1008
1501
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
node.astack = {}
|
|
1013
|
-
}
|
|
1014
|
-
node.astack[arrowId] = true
|
|
1015
|
-
if (node.id === arrowId) {
|
|
1016
|
-
return
|
|
1017
|
-
}
|
|
1018
|
-
for (var prevId of node.prev) {
|
|
1019
|
-
var prev = nodes[prevId]
|
|
1020
|
-
fillAStack(nodes, prev, arrowId)
|
|
1021
|
-
}
|
|
1502
|
+
var node = nodes[nodeId];
|
|
1503
|
+
if (node.type === "branch") {
|
|
1504
|
+
return;
|
|
1022
1505
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
} else {
|
|
1047
|
-
rewireArrowsInBranch(nodes, nodeId, node.one, arrowStack)
|
|
1048
|
-
}
|
|
1506
|
+
if (node.type === "arrow-loop") {
|
|
1507
|
+
if (!node.noloop) {
|
|
1508
|
+
node.noloop = {};
|
|
1509
|
+
}
|
|
1510
|
+
if (arrowStack.includes(nodeId)) {
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
node.noloop[prevNodeId] = true;
|
|
1514
|
+
arrowStack = arrowStack.slice();
|
|
1515
|
+
arrowStack.push(nodeId);
|
|
1516
|
+
rewireArrowsInBranch(nodes, nodeId, node.one, arrowStack);
|
|
1517
|
+
} else if (node.type === "question") {
|
|
1518
|
+
var left = arrowStack.slice();
|
|
1519
|
+
var right = arrowStack.slice();
|
|
1520
|
+
rewireArrowsInBranch(nodes, nodeId, node.one, left);
|
|
1521
|
+
rewireArrowsInBranch(nodes, nodeId, node.two, right);
|
|
1522
|
+
} else if (node.type === "parbegin") {
|
|
1523
|
+
for (var proc of node.procs) {
|
|
1524
|
+
rewireArrowsInBranch(nodes, undefined, proc.start, []);
|
|
1525
|
+
}
|
|
1526
|
+
rewireArrowsInBranch(nodes, nodeId, node.one, arrowStack);
|
|
1527
|
+
} else {
|
|
1528
|
+
rewireArrowsInBranch(nodes, nodeId, node.one, arrowStack);
|
|
1049
1529
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
node.prev = prev2
|
|
1071
|
-
return stub
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
function insertArrowStub(nodes, node) {
|
|
1533
|
+
var stub = {
|
|
1534
|
+
type: "arrow-stub",
|
|
1535
|
+
id: "arrow-stub-" + node.id,
|
|
1536
|
+
arrow: node.id,
|
|
1537
|
+
prev: [],
|
|
1538
|
+
};
|
|
1539
|
+
nodes[stub.id] = stub;
|
|
1540
|
+
node.stub = stub.id;
|
|
1541
|
+
var prev2 = [];
|
|
1542
|
+
for (var prevId of node.prev) {
|
|
1543
|
+
if (prevId in node.noloop) {
|
|
1544
|
+
prev2.push(prevId);
|
|
1545
|
+
} else {
|
|
1546
|
+
stub.prev.push(prevId);
|
|
1547
|
+
var prev = nodes[prevId];
|
|
1548
|
+
redirectNode(nodes, prev, node.id, stub.id);
|
|
1549
|
+
}
|
|
1072
1550
|
}
|
|
1551
|
+
node.prev = prev2;
|
|
1552
|
+
return stub;
|
|
1553
|
+
}
|
|
1073
1554
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
index++
|
|
1078
|
-
if (endId && node.id === endId) {
|
|
1079
|
-
return index
|
|
1080
|
-
}
|
|
1081
|
-
if (node.type === "question") {
|
|
1082
|
-
var transformed = rewriteQuestionTree(node, output)
|
|
1083
|
-
if (endId) {
|
|
1084
|
-
var breakYes = findLoopEnd(transformed.yes, endId)
|
|
1085
|
-
var breakNo = findLoopEnd(transformed.no, endId)
|
|
1086
|
-
if (breakYes || breakNo) {
|
|
1087
|
-
var toBreak = []
|
|
1088
|
-
findPlacesToBreak(transformed.yes, endId, toBreak)
|
|
1089
|
-
findPlacesToBreak(transformed.no, endId, toBreak)
|
|
1090
|
-
addBreaks(toBreak)
|
|
1091
|
-
return index
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
} else if (node.type === "loopbegin") {
|
|
1095
|
-
var body2 = []
|
|
1096
|
-
index = rewriteTree(body, index, node.end, body2)
|
|
1097
|
-
output.push({
|
|
1098
|
-
id: node.id,
|
|
1099
|
-
type: "loop",
|
|
1100
|
-
content: node.content,
|
|
1101
|
-
body: body2
|
|
1102
|
-
})
|
|
1103
|
-
} else {
|
|
1104
|
-
output.push(node)
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1555
|
+
function copySide(dst, src) {
|
|
1556
|
+
if (src.side) {
|
|
1557
|
+
dst.side = src.side;
|
|
1107
1558
|
}
|
|
1559
|
+
}
|
|
1108
1560
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1561
|
+
function rewriteTree(body, index, endId, output) {
|
|
1562
|
+
while (index < body.length) {
|
|
1563
|
+
var node = body[index];
|
|
1564
|
+
index++;
|
|
1565
|
+
if (endId && node.id === endId) {
|
|
1566
|
+
return index;
|
|
1567
|
+
}
|
|
1568
|
+
if (node.type === "question") {
|
|
1569
|
+
var transformed = rewriteQuestionTree(node, output);
|
|
1570
|
+
copySide(transformed, node);
|
|
1571
|
+
if (endId) {
|
|
1572
|
+
var breakYes = findLoopEnd(transformed.yes, endId);
|
|
1573
|
+
var breakNo = findLoopEnd(transformed.no, endId);
|
|
1574
|
+
if (breakYes || breakNo) {
|
|
1575
|
+
var toBreak = [];
|
|
1576
|
+
findPlacesToBreak(transformed.yes, endId, toBreak);
|
|
1577
|
+
findPlacesToBreak(transformed.no, endId, toBreak);
|
|
1578
|
+
addBreaks(toBreak);
|
|
1579
|
+
return index;
|
|
1580
|
+
}
|
|
1113
1581
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1582
|
+
} else if (node.type === "loopbegin") {
|
|
1583
|
+
var body2 = [];
|
|
1584
|
+
index = rewriteTree(body, index, node.end, body2);
|
|
1585
|
+
output.push({
|
|
1586
|
+
id: node.id,
|
|
1587
|
+
type: "loop",
|
|
1588
|
+
content: node.content,
|
|
1589
|
+
body: body2,
|
|
1590
|
+
});
|
|
1591
|
+
} else if (node.type === "parbegin") {
|
|
1592
|
+
var copy = {
|
|
1593
|
+
id: node.id,
|
|
1594
|
+
type: node.type,
|
|
1595
|
+
procs: [],
|
|
1596
|
+
};
|
|
1597
|
+
for (var proc of node.procs) {
|
|
1598
|
+
var procCopy = {
|
|
1599
|
+
ordinal: proc.ordinal,
|
|
1600
|
+
body: [],
|
|
1601
|
+
};
|
|
1602
|
+
copy.procs.push(procCopy);
|
|
1603
|
+
rewriteTree(proc.body, 0, undefined, procCopy.body);
|
|
1131
1604
|
}
|
|
1605
|
+
output.push(copy);
|
|
1606
|
+
} else {
|
|
1607
|
+
output.push(node);
|
|
1608
|
+
}
|
|
1132
1609
|
}
|
|
1610
|
+
}
|
|
1133
1611
|
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
if (i === body.length - 1) {
|
|
1139
|
-
return true
|
|
1140
|
-
} else {
|
|
1141
|
-
throw createError(
|
|
1142
|
-
translate("An exit from the loop must lead to the point right after the loop end"),
|
|
1143
|
-
filename,
|
|
1144
|
-
node.id
|
|
1145
|
-
);
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
if (node.type === "question") {
|
|
1149
|
-
if (findLoopEnd(node.yes, endId)) {
|
|
1150
|
-
return true
|
|
1151
|
-
}
|
|
1152
|
-
if (findLoopEnd(node.no, endId)) {
|
|
1153
|
-
return true
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
return false
|
|
1612
|
+
function findPlacesToBreak(body, endId, output) {
|
|
1613
|
+
if (body.length === 0) {
|
|
1614
|
+
output.push(body);
|
|
1615
|
+
return;
|
|
1158
1616
|
}
|
|
1617
|
+
var last = body[body.length - 1];
|
|
1618
|
+
if (last.id === endId) {
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
if (last.type === "question") {
|
|
1622
|
+
var qends = [];
|
|
1623
|
+
findPlacesToBreak(last.yes, endId, qends);
|
|
1624
|
+
findPlacesToBreak(last.no, endId, qends);
|
|
1625
|
+
if (qends.length === 2 && qends[0] === last.yes && qends[1] === last.no) {
|
|
1626
|
+
output.push(body);
|
|
1627
|
+
} else {
|
|
1628
|
+
addRange(output, qends);
|
|
1629
|
+
}
|
|
1630
|
+
} else {
|
|
1631
|
+
output.push(body);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1159
1634
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1635
|
+
function findLoopEnd(body, endId) {
|
|
1636
|
+
for (var i = 0; i < body.length; i++) {
|
|
1637
|
+
var node = body[i];
|
|
1638
|
+
if (node.id === endId) {
|
|
1639
|
+
if (i === body.length - 1) {
|
|
1640
|
+
return true;
|
|
1641
|
+
} else {
|
|
1642
|
+
throw createError(
|
|
1643
|
+
translate(
|
|
1644
|
+
"An exit from the loop must lead to the point right after the loop end",
|
|
1645
|
+
),
|
|
1646
|
+
filename,
|
|
1647
|
+
node.id,
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
if (node.type === "question") {
|
|
1652
|
+
if (findLoopEnd(node.yes, endId)) {
|
|
1653
|
+
return true;
|
|
1165
1654
|
}
|
|
1655
|
+
if (findLoopEnd(node.no, endId)) {
|
|
1656
|
+
return true;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1166
1659
|
}
|
|
1660
|
+
return false;
|
|
1661
|
+
}
|
|
1167
1662
|
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
var transformed = {
|
|
1174
|
-
type: "question",
|
|
1175
|
-
id: question.id,
|
|
1176
|
-
content: question.content,
|
|
1177
|
-
yes: yes,
|
|
1178
|
-
no: no
|
|
1179
|
-
}
|
|
1180
|
-
output.push(transformed)
|
|
1181
|
-
return transformed
|
|
1663
|
+
function addBreaks(toBreak) {
|
|
1664
|
+
for (var body of toBreak) {
|
|
1665
|
+
body.push({
|
|
1666
|
+
type: "break",
|
|
1667
|
+
});
|
|
1182
1668
|
}
|
|
1183
|
-
|
|
1669
|
+
}
|
|
1184
1670
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1671
|
+
function rewriteQuestionTree(question, output) {
|
|
1672
|
+
var yes = [];
|
|
1673
|
+
var no = [];
|
|
1674
|
+
rewriteTree(question.yes, 0, undefined, yes);
|
|
1675
|
+
rewriteTree(question.no, 0, undefined, no);
|
|
1676
|
+
var transformed = {
|
|
1677
|
+
type: "question",
|
|
1678
|
+
id: question.id,
|
|
1679
|
+
content: question.content,
|
|
1680
|
+
yes: yes,
|
|
1681
|
+
no: no,
|
|
1682
|
+
};
|
|
1683
|
+
output.push(transformed);
|
|
1684
|
+
return transformed;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
function structMain() {
|
|
1688
|
+
rewireArrows(nodes, branches);
|
|
1689
|
+
prepareQuestions(nodes);
|
|
1690
|
+
var result = [];
|
|
1691
|
+
|
|
1692
|
+
for (var branch of branches) {
|
|
1693
|
+
if (options.noLoop) {
|
|
1694
|
+
flow_no_loop(nodes, branch.next, []);
|
|
1695
|
+
} else {
|
|
1696
|
+
flowGraph(nodes, branch.next, []);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1206
1699
|
|
|
1207
|
-
|
|
1700
|
+
for (var branch of branches) {
|
|
1701
|
+
var body = [];
|
|
1702
|
+
buildTree(nodes, branch.next, body, "<dummy id>");
|
|
1703
|
+
var body2 = [];
|
|
1704
|
+
rewriteTree(body, 0, undefined, body2);
|
|
1705
|
+
result.push({
|
|
1706
|
+
name: branch.content,
|
|
1707
|
+
branchId: branch.branchId,
|
|
1708
|
+
start: branch.next,
|
|
1709
|
+
refs: branch.prev.length,
|
|
1710
|
+
body: optimizeTree(body2),
|
|
1711
|
+
});
|
|
1208
1712
|
}
|
|
1209
1713
|
|
|
1210
|
-
return
|
|
1714
|
+
return sortByProperty(result, "branchId");
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
return structMain();
|
|
1211
1718
|
}
|
|
1212
1719
|
module.exports = { structFlow, redirectNode };
|
|
1213
|
-
|
|
1720
|
+
|
|
1721
|
+
},{"./noloop":6,"./technicalTree":9,"./tools":10,"./treeTools":12}],9:[function(require,module,exports){
|
|
1214
1722
|
function buildTree(nodes, nodeId, body, stopId) {
|
|
1215
1723
|
while (nodeId) {
|
|
1216
1724
|
if (nodeId === stopId) {return;}
|
|
@@ -1250,6 +1758,21 @@ function buildTree(nodes, nodeId, body, stopId) {
|
|
|
1250
1758
|
start: node.arrow
|
|
1251
1759
|
};
|
|
1252
1760
|
|
|
1761
|
+
next = node.one;
|
|
1762
|
+
} else if (node.type === "parbegin") {
|
|
1763
|
+
transformed = {
|
|
1764
|
+
id: node.id,
|
|
1765
|
+
type: node.type,
|
|
1766
|
+
procs: []
|
|
1767
|
+
}
|
|
1768
|
+
for (var proc of node.procs) {
|
|
1769
|
+
var childProc = {
|
|
1770
|
+
ordinal: proc.ordinal,
|
|
1771
|
+
body: []
|
|
1772
|
+
}
|
|
1773
|
+
transformed.procs.push(childProc)
|
|
1774
|
+
buildTree(nodes, proc.start, childProc.body, undefined)
|
|
1775
|
+
}
|
|
1253
1776
|
next = node.one;
|
|
1254
1777
|
} else {
|
|
1255
1778
|
transformed = {
|
|
@@ -1268,8 +1791,13 @@ function buildTree(nodes, nodeId, body, stopId) {
|
|
|
1268
1791
|
]
|
|
1269
1792
|
)
|
|
1270
1793
|
next = node.one;
|
|
1794
|
+
if (node.final) {
|
|
1795
|
+
next = undefined
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
if (node.side) {
|
|
1799
|
+
transformed.side = node.side
|
|
1271
1800
|
}
|
|
1272
|
-
|
|
1273
1801
|
body.push(transformed);
|
|
1274
1802
|
nodeId = next;
|
|
1275
1803
|
}
|
|
@@ -1285,6 +1813,9 @@ function copyFields(dst, src, fields) {
|
|
|
1285
1813
|
}
|
|
1286
1814
|
|
|
1287
1815
|
function reserveNext(nodes, node) {
|
|
1816
|
+
if (!node.next) {
|
|
1817
|
+
return undefined
|
|
1818
|
+
}
|
|
1288
1819
|
const target = nodes[node.next];
|
|
1289
1820
|
if (target.targetTaken) {
|
|
1290
1821
|
return undefined;
|
|
@@ -1296,7 +1827,7 @@ function reserveNext(nodes, node) {
|
|
|
1296
1827
|
|
|
1297
1828
|
module.exports = {buildTree}
|
|
1298
1829
|
|
|
1299
|
-
},{}],
|
|
1830
|
+
},{}],10:[function(require,module,exports){
|
|
1300
1831
|
|
|
1301
1832
|
function createError(message, filename, nodeId) {
|
|
1302
1833
|
var error = new Error(message)
|
|
@@ -1337,7 +1868,7 @@ function addRange(to, from) {
|
|
|
1337
1868
|
}
|
|
1338
1869
|
}
|
|
1339
1870
|
module.exports = { createError, sortByProperty, addRange, remove }
|
|
1340
|
-
},{}],
|
|
1871
|
+
},{}],11:[function(require,module,exports){
|
|
1341
1872
|
var translationsRu = {
|
|
1342
1873
|
"error": "ОШИБКА",
|
|
1343
1874
|
"not": "не",
|
|
@@ -1366,7 +1897,13 @@ var translationsRu = {
|
|
|
1366
1897
|
"Description": "Описание",
|
|
1367
1898
|
"Algorithm": "Алгоритм",
|
|
1368
1899
|
Remarks: "Замечания",
|
|
1369
|
-
Parameters: "Параметры"
|
|
1900
|
+
Parameters: "Параметры",
|
|
1901
|
+
"Group of parallel processes": "Группа параллельных процессов",
|
|
1902
|
+
"Parallel process": "Параллельный процесс",
|
|
1903
|
+
"Start at": "Начать в",
|
|
1904
|
+
"Do for": "Делать в течение",
|
|
1905
|
+
"Pause": "Пауза",
|
|
1906
|
+
"Start timer": "Запустить таймер"
|
|
1370
1907
|
}
|
|
1371
1908
|
|
|
1372
1909
|
var translationsEn = {
|
|
@@ -1397,7 +1934,13 @@ var translationsEn = {
|
|
|
1397
1934
|
Description: 'Description',
|
|
1398
1935
|
Algorithm: 'Algorithm',
|
|
1399
1936
|
Remarks: "Remarks",
|
|
1400
|
-
Parameters: "Parameters"
|
|
1937
|
+
Parameters: "Parameters",
|
|
1938
|
+
"Group of parallel processes": "Group of parallel processes",
|
|
1939
|
+
"Parallel process": "Parallel process",
|
|
1940
|
+
"Start at": "Start at",
|
|
1941
|
+
"Do for": "Do for",
|
|
1942
|
+
"Pause": "Pause",
|
|
1943
|
+
"Start timer": "Start timer",
|
|
1401
1944
|
}
|
|
1402
1945
|
|
|
1403
1946
|
var translationsNo = {
|
|
@@ -1428,7 +1971,13 @@ var translationsNo = {
|
|
|
1428
1971
|
Description: 'Beskrivelse',
|
|
1429
1972
|
Algorithm: 'Algoritme',
|
|
1430
1973
|
Remarks: "Bemerkninger",
|
|
1431
|
-
Parameters: "Parametere"
|
|
1974
|
+
Parameters: "Parametere",
|
|
1975
|
+
"Group of parallel processes": "Gruppe av parallelle prosesser",
|
|
1976
|
+
"Parallel process": "Parallell prosess",
|
|
1977
|
+
"Start at": "Start ved",
|
|
1978
|
+
"Do for": "Gjør i",
|
|
1979
|
+
"Pause": "Pause",
|
|
1980
|
+
"Start timer": "Start tidtaker"
|
|
1432
1981
|
};
|
|
1433
1982
|
|
|
1434
1983
|
|
|
@@ -1452,7 +2001,7 @@ function setUpLanguage(language) {
|
|
|
1452
2001
|
|
|
1453
2002
|
|
|
1454
2003
|
module.exports = { setUpLanguage, translate };
|
|
1455
|
-
},{}],
|
|
2004
|
+
},{}],12:[function(require,module,exports){
|
|
1456
2005
|
|
|
1457
2006
|
function optimizeTree(steps) {
|
|
1458
2007
|
var result = []
|
|
@@ -1463,6 +2012,8 @@ function optimizeTree(steps) {
|
|
|
1463
2012
|
var copy
|
|
1464
2013
|
if (step.type === "question") {
|
|
1465
2014
|
copy = optimizeQuestion(step)
|
|
2015
|
+
} else if (step.type === "parbegin") {
|
|
2016
|
+
copy = optimizeParbegin(step)
|
|
1466
2017
|
} else if (step.type === "loop") {
|
|
1467
2018
|
copy = optimizeLoop(step)
|
|
1468
2019
|
} else {
|
|
@@ -1474,6 +2025,22 @@ function optimizeTree(steps) {
|
|
|
1474
2025
|
return result
|
|
1475
2026
|
}
|
|
1476
2027
|
|
|
2028
|
+
function optimizeParbegin(step) {
|
|
2029
|
+
var procs = []
|
|
2030
|
+
for (var proc of step.procs) {
|
|
2031
|
+
var procCopy = {
|
|
2032
|
+
ordinal: proc.ordinal,
|
|
2033
|
+
body: optimizeTree(proc.body)
|
|
2034
|
+
}
|
|
2035
|
+
procs.push(procCopy)
|
|
2036
|
+
}
|
|
2037
|
+
return {
|
|
2038
|
+
id: step.id,
|
|
2039
|
+
type: step.type,
|
|
2040
|
+
procs: procs
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
|
|
1477
2044
|
function optimizeLoop(step) {
|
|
1478
2045
|
return {
|
|
1479
2046
|
id: step.id,
|
|
@@ -1488,6 +2055,7 @@ function optimizeQuestion(step) {
|
|
|
1488
2055
|
var no = optimizeTree(step.no)
|
|
1489
2056
|
if (yes.length === 0 && no.length === 0) {
|
|
1490
2057
|
return {
|
|
2058
|
+
side: step.side,
|
|
1491
2059
|
type: step.type,
|
|
1492
2060
|
content: step.content,
|
|
1493
2061
|
yes: [],
|
|
@@ -1496,6 +2064,7 @@ function optimizeQuestion(step) {
|
|
|
1496
2064
|
}
|
|
1497
2065
|
if (yes.length === 0) {
|
|
1498
2066
|
return {
|
|
2067
|
+
side: step.side,
|
|
1499
2068
|
type: step.type,
|
|
1500
2069
|
content: {operator:"not",operand:step.content},
|
|
1501
2070
|
yes: no,
|
|
@@ -1503,6 +2072,7 @@ function optimizeQuestion(step) {
|
|
|
1503
2072
|
}
|
|
1504
2073
|
}
|
|
1505
2074
|
return {
|
|
2075
|
+
side: step.side,
|
|
1506
2076
|
type: step.type,
|
|
1507
2077
|
content: step.content,
|
|
1508
2078
|
yes: yes,
|