drakongen 1.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.
Files changed (157) hide show
  1. package/.vscode/launch.json +18 -0
  2. package/LICENSE +24 -0
  3. package/README.md +80 -0
  4. package/browser/drakongen.js +1303 -0
  5. package/browsertest.html +84 -0
  6. package/buildbrowser +4 -0
  7. package/buildexamples.js +61 -0
  8. package/examples/00.Empty.drakon +1 -0
  9. package/examples/00.Empty.txt +5 -0
  10. package/examples/01. /320/221/320/265/320/273/321/213/320/270/314/206.drakon" +13 -0
  11. package/examples/01. /320/221/320/265/320/273/321/213/320/271.json" +16 -0
  12. package/examples/01. /320/221/320/265/320/273/321/213/320/271.txt" +4 -0
  13. package/examples/02. /320/247/320/265/314/210/321/200/320/275/321/213/320/270/314/206.drakon" +28 -0
  14. package/examples/02. /320/247/321/221/321/200/320/275/321/213/320/271.json" +31 -0
  15. package/examples/02. /320/247/321/221/321/200/320/275/321/213/320/271.txt" +10 -0
  16. package/examples/03. /320/241/320/265/321/200/321/213/320/270/314/206.drakon" +20 -0
  17. package/examples/03. /320/241/320/265/321/200/321/213/320/271.json" +23 -0
  18. package/examples/03. /320/241/320/265/321/200/321/213/320/271.txt" +6 -0
  19. package/examples/04. /320/221/321/203/321/200/321/213/320/270/314/206.drakon" +25 -0
  20. package/examples/04. /320/221/321/203/321/200/321/213/320/271.json" +29 -0
  21. package/examples/04. /320/221/321/203/321/200/321/213/320/271.txt" +7 -0
  22. package/examples/05. /320/226/320/265/314/210/320/273/321/202/321/213/320/270/314/206.drakon" +25 -0
  23. package/examples/05. /320/226/321/221/320/273/321/202/321/213/320/271.json" +29 -0
  24. package/examples/05. /320/226/321/221/320/273/321/202/321/213/320/271.txt" +7 -0
  25. package/examples/06. /320/221/320/260/320/263/321/200/320/276/320/262/321/213/320/270/314/206.drakon" +30 -0
  26. package/examples/06. /320/221/320/260/320/263/321/200/320/276/320/262/321/213/320/271.json" +35 -0
  27. package/examples/06. /320/221/320/260/320/263/321/200/320/276/320/262/321/213/320/271.txt" +10 -0
  28. package/examples/07. /320/244/320/270/320/276/320/273/320/265/321/202/320/276/320/262/321/213/320/270/314/206.drakon" +42 -0
  29. package/examples/07. /320/244/320/270/320/276/320/273/320/265/321/202/320/276/320/262/321/213/320/271.json" +49 -0
  30. package/examples/07. /320/244/320/270/320/276/320/273/320/265/321/202/320/276/320/262/321/213/320/271.txt" +14 -0
  31. package/examples/08. /320/221/320/270/321/200/321/216/320/267/320/276/320/262/321/213/320/270/314/206.drakon" +27 -0
  32. package/examples/08. /320/221/320/270/321/200/321/216/320/267/320/276/320/262/321/213/320/271.json" +27 -0
  33. package/examples/08. /320/221/320/270/321/200/321/216/320/267/320/276/320/262/321/213/320/271.txt" +6 -0
  34. package/examples/09. /320/236/321/200/320/260/320/275/320/266/320/265/320/262/321/213/320/270/314/206.drakon" +37 -0
  35. package/examples/09. /320/236/321/200/320/260/320/275/320/266/320/265/320/262/321/213/320/271.json" +39 -0
  36. package/examples/09. /320/236/321/200/320/260/320/275/320/266/320/265/320/262/321/213/320/271.txt" +10 -0
  37. package/examples/10. /320/240/320/276/320/267/320/276/320/262/321/213/320/270/314/206.drakon" +42 -0
  38. package/examples/10. /320/240/320/276/320/267/320/276/320/262/321/213/320/271.json" +54 -0
  39. package/examples/10. /320/240/320/276/320/267/320/276/320/262/321/213/320/271.txt" +16 -0
  40. package/examples/11. /320/227/320/260/321/211/320/270/321/202/320/275/321/213/320/270/314/206.drakon" +37 -0
  41. package/examples/11. /320/227/320/260/321/211/320/270/321/202/320/275/321/213/320/271.json" +39 -0
  42. package/examples/11. /320/227/320/260/321/211/320/270/321/202/320/275/321/213/320/271.txt" +10 -0
  43. package/examples/12. /320/221/320/276/320/273/320/276/321/202/320/275/321/213/320/270/314/206.drakon" +44 -0
  44. package/examples/12. /320/221/320/276/320/273/320/276/321/202/320/275/321/213/320/271.json" +43 -0
  45. package/examples/12. /320/221/320/276/320/273/320/276/321/202/320/275/321/213/320/271.txt" +10 -0
  46. package/examples/13. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/270/314/206.drakon" +54 -0
  47. package/examples/13. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.json" +63 -0
  48. package/examples/13. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.txt" +18 -0
  49. package/examples/14. /320/227/320/276/320/273/320/276/321/202/320/276/320/270/314/206.drakon" +64 -0
  50. package/examples/14. /320/227/320/276/320/273/320/276/321/202/320/276/320/271.json" +73 -0
  51. package/examples/14. /320/227/320/276/320/273/320/276/321/202/320/276/320/271.txt" +22 -0
  52. package/examples/15. /320/241/320/270/320/275/320/270/320/270/314/206.drakon" +54 -0
  53. package/examples/15. /320/241/320/270/320/275/320/270/320/271.json" +87 -0
  54. package/examples/15. /320/241/320/270/320/275/320/270/320/271.txt" +26 -0
  55. package/examples/16. /320/223/320/276/320/273/321/203/320/261/320/276/320/270/314/206.drakon" +37 -0
  56. package/examples/16. /320/223/320/276/320/273/321/203/320/261/320/276/320/271.json" +48 -0
  57. package/examples/16. /320/223/320/276/320/273/321/203/320/261/320/276/320/271.txt" +13 -0
  58. package/examples/17. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/270/314/206.drakon" +39 -0
  59. package/examples/17. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.json" +41 -0
  60. package/examples/17. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.txt" +10 -0
  61. package/examples/18. /320/241/321/202/320/260/320/273/321/214/320/275/320/276/320/270/314/206.drakon" +49 -0
  62. package/examples/18. /320/241/321/202/320/260/320/273/321/214/320/275/320/276/320/271.json" +67 -0
  63. package/examples/18. /320/241/321/202/320/260/320/273/321/214/320/275/320/276/320/271.txt" +19 -0
  64. package/examples/19. Lilla.drakon +39 -0
  65. package/examples/19. Lilla.json +45 -0
  66. package/examples/19. Lilla.txt +11 -0
  67. package/examples/Adaptive design.drakon +116 -0
  68. package/examples/Adaptive design.json +153 -0
  69. package/examples/Adaptive design.txt +47 -0
  70. package/examples/And test.drakon +46 -0
  71. package/examples/And test.json +46 -0
  72. package/examples/And test.txt +10 -0
  73. package/examples/Arrow - double exit.drakon +41 -0
  74. package/examples/Arrow - double exit.json +62 -0
  75. package/examples/Arrow - double exit.txt +14 -0
  76. package/examples/Complex arrow.drakon +93 -0
  77. package/examples/Complex arrow.json +162 -0
  78. package/examples/Complex arrow.txt +43 -0
  79. package/examples/DoubleArrow.drakon +53 -0
  80. package/examples/DoubleArrow.json +86 -0
  81. package/examples/DoubleArrow.txt +18 -0
  82. package/examples/Find pointing nodes.drakon +104 -0
  83. package/examples/Find pointing nodes.json +137 -0
  84. package/examples/Find pointing nodes.txt +29 -0
  85. package/examples/How to tune PID on a quadcopter.drakon +488 -0
  86. package/examples/How to tune PID on a quadcopter.json +734 -0
  87. package/examples/How to tune PID on a quadcopter.txt +169 -0
  88. package/examples/Or test.drakon +47 -0
  89. package/examples/Or test.json +46 -0
  90. package/examples/Or test.txt +10 -0
  91. package/examples/Silhouette test 1.drakon +47 -0
  92. package/examples/Silhouette test 1.json +82 -0
  93. package/examples/Silhouette test 1.txt +24 -0
  94. package/examples/Work out action-check.drakon +30 -0
  95. package/examples/Work out action-check.json +45 -0
  96. package/examples/Work out action-check.txt +9 -0
  97. package/examples/Workout foreach.drakon +63 -0
  98. package/examples/Workout foreach.json +62 -0
  99. package/examples/Workout foreach.txt +14 -0
  100. package/examples/ar01.drakon +25 -0
  101. package/examples/ar01.json +40 -0
  102. package/examples/ar01.txt +7 -0
  103. package/examples/ar02.drakon +30 -0
  104. package/examples/ar02.json +45 -0
  105. package/examples/ar02.txt +10 -0
  106. package/examples/ar03.drakon +32 -0
  107. package/examples/ar03.json +44 -0
  108. package/examples/ar03.txt +7 -0
  109. package/examples/ar04.drakon +37 -0
  110. package/examples/ar04.json +49 -0
  111. package/examples/ar04.txt +10 -0
  112. package/examples/ar05.drakon +37 -0
  113. package/examples/ar05.json +59 -0
  114. package/examples/ar05.txt +11 -0
  115. package/examples/ar06.drakon +40 -0
  116. package/examples/ar06.json +70 -0
  117. package/examples/ar06.txt +13 -0
  118. package/examples/ar07.drakon +40 -0
  119. package/examples/ar07.json +70 -0
  120. package/examples/ar07.txt +13 -0
  121. package/examples/ar08.drakon +47 -0
  122. package/examples/ar08.json +81 -0
  123. package/examples/ar08.txt +16 -0
  124. package/examples/ar09.drakon +52 -0
  125. package/examples/ar09.json +87 -0
  126. package/examples/ar09.txt +17 -0
  127. package/examples/ar10.drakon +52 -0
  128. package/examples/ar10.json +88 -0
  129. package/examples/ar10.txt +18 -0
  130. package/examples/ar11.drakon +47 -0
  131. package/examples/ar11.json +82 -0
  132. package/examples/ar11.txt +17 -0
  133. package/examples/ar12.drakon +37 -0
  134. package/examples/ar12.json +49 -0
  135. package/examples/ar12.txt +10 -0
  136. package/examples/getToken.drakon +76 -0
  137. package/examples/getToken.json +88 -0
  138. package/examples/getToken.txt +41 -0
  139. package/examples/tmp.drakon +49 -0
  140. package/examples/tmp.json +82 -0
  141. package/examples/tmp.txt +37 -0
  142. package/package.json +21 -0
  143. package/prompts/drakonToPrompt.txt +139 -0
  144. package/prompts/index.txt +17 -0
  145. package/prompts/printPseudo.txt +116 -0
  146. package/src/browserTools.js +39 -0
  147. package/src/drakonToPromptStruct.js +44 -0
  148. package/src/drakonToStruct.js +416 -0
  149. package/src/drakongen.js +16 -0
  150. package/src/index.js +17 -0
  151. package/src/main.js +157 -0
  152. package/src/nodeTools.js +38 -0
  153. package/src/printPseudo.js +167 -0
  154. package/src/structFlow.js +382 -0
  155. package/src/technicalTree.js +84 -0
  156. package/src/tools.js +36 -0
  157. package/src/translate.js +108 -0
@@ -0,0 +1,382 @@
1
+ var {buildTree} = require("./technicalTree")
2
+ const { createError, sortByProperty } = require("./tools");
3
+
4
+ function redirectNode(nodes, node, from, to) {
5
+ if (node.one === from) {
6
+ node.one = to;
7
+ }
8
+ if (node.two === from) {
9
+ node.two = to;
10
+ }
11
+ if (node.next === from) {
12
+ node.next = to
13
+ }
14
+ if (node.start && node.type === "loopend") {
15
+ start = nodes[node.start]
16
+ if (start.next === from) {
17
+ start.next = to
18
+ }
19
+ }
20
+ }
21
+
22
+ function structFlow(nodes, branches, filename, translate) {
23
+
24
+
25
+
26
+ function flowGraph(nodes, nodeId, branchingStack) {
27
+ if (!nodeId) {return;}
28
+
29
+ const node = nodes[nodeId];
30
+
31
+ if (!node.stack) {
32
+ node.stack = [];
33
+ node.remaining = node.prev.length;
34
+ }
35
+ node.remaining--;
36
+
37
+ mergeBranchingStack(nodes, node, branchingStack);
38
+ if (node.remaining > 0) {return;}
39
+
40
+ if (node.type === "question") {
41
+ for (let i = 0; i < node.stack.length; i++) {
42
+ const questionId = node.stack[i];
43
+ const question = nodes[questionId];
44
+ question.branching++;
45
+ }
46
+
47
+ const stackOne = node.stack.slice();
48
+ const stackTwo = node.stack.slice();
49
+ stackOne.push(nodeId);
50
+ stackTwo.push(nodeId);
51
+
52
+ flowGraph(nodes, node.two, stackTwo);
53
+ flowGraph(nodes, node.one, stackOne);
54
+ } else if (node.type === "arrow-loop") {
55
+ const stackOne = node.stack.slice();
56
+ stackOne.push(nodeId);
57
+ flowGraph(nodes, node.one, stackOne);
58
+ } else if (node.type === "arrow-stub") {
59
+ decrementBranchingForArrow(nodes, node)
60
+ } else {
61
+ flowGraph(nodes, node.one, node.stack);
62
+ }
63
+ }
64
+
65
+ function decrementBranchingForArrow(nodes, node) {
66
+ var algonode = nodes[node.arrow]
67
+ algonode.branching--
68
+ }
69
+
70
+ function decrementQuestions(nodes, algonode, dictionary) {
71
+ var stub = nodes[algonode.stub]
72
+ for (var id of stub.stack) {
73
+ var snode = nodes[id]
74
+ if (id != algonode) {
75
+ if (id in dictionary) {
76
+ snode.branching--
77
+ }
78
+ }
79
+ }
80
+ return stub
81
+ }
82
+
83
+
84
+
85
+ function mergeBranchingStack(nodes, node, branchingStack) {
86
+ // Append all elements of the branching stack to node.stack
87
+ addRange(node.stack, branchingStack)
88
+
89
+ // Build a dictionary of occurrences
90
+ const dictionary = buildDictionaryOfOccurences(node);
91
+
92
+ // Merge all nodes
93
+ mergeAll(nodes, node, dictionary);
94
+
95
+ // Rebuild the stack
96
+ node.stack = buildStackFromDictionary(dictionary);
97
+ }
98
+
99
+ function addRange(dst, src) {
100
+ for (let i = 0; i < src.length; i++) {
101
+ dst.push(src[i]);
102
+ }
103
+ }
104
+
105
+ function buildStackFromDictionary(dictionary) {
106
+ const rebuiltStack = [];
107
+ for (const id in dictionary) {
108
+ if (dictionary[id] > 0) {
109
+ rebuiltStack.push(id);
110
+ }
111
+ }
112
+ return rebuiltStack;
113
+ }
114
+
115
+ function buildDictionaryOfOccurences(node) {
116
+ const dictionary = {};
117
+ for (let i = 0; i < node.stack.length; i++) {
118
+ const id = node.stack[i];
119
+ dictionary[id] = (dictionary[id] || 0) + 1;
120
+ }
121
+ return dictionary;
122
+ }
123
+
124
+ function mergeAll(nodes, node, dictionary) {
125
+ for (const id in dictionary) {
126
+ const occurrences = dictionary[id];
127
+ const algonode = nodes[id];
128
+ if (occurrences > 1) {
129
+ algonode.branching--;
130
+ dictionary[id] = occurrences - 1;
131
+ }
132
+ if (algonode.branching === 1) {
133
+ if (algonode.type === "arrow-loop" && !algonode.next) {
134
+ if (!isInMap(node.astack, id)) {
135
+ algonode.next = node.id
136
+ dictionary[algonode.id] = 0;
137
+ var stub = decrementQuestions(nodes, algonode, dictionary)
138
+ stub.one = node.id
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ for (const id in dictionary) {
145
+ const algonode = nodes[id];
146
+ if (algonode.branching === 1) {
147
+ if (algonode.type === "question") {
148
+ algonode.next = node.id;
149
+ dictionary[algonode.id] = 0;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ function isInMap(map, key) {
155
+ if (!map) { return false }
156
+ return key in map
157
+ }
158
+
159
+ function prepareQuestions(nodes) {
160
+ for (const nodeId in nodes) {
161
+ const node = nodes[nodeId];
162
+ if (node.type === "question") {
163
+ node.branching = 2;
164
+ } else if (node.type === "arrow-loop") {
165
+ node.branching = 1;
166
+ }
167
+ }
168
+ }
169
+
170
+ function rewireArrows(nodes, branches) {
171
+ branches.forEach(branch => rewireArrowsInBranch(nodes, branch.id, branch.next, []))
172
+ for (var id in nodes) {
173
+ var node = nodes[id]
174
+ if (node.type === "arrow-loop") {
175
+ var stub = insertArrowStub(nodes, node)
176
+ fillAStack(nodes, stub, stub.arrow)
177
+ }
178
+ }
179
+ }
180
+
181
+ function fillAStack(nodes, node, arrowId) {
182
+ if (!node.astack) {
183
+ node.astack = {}
184
+ }
185
+ node.astack[arrowId] = true
186
+ if (node.id === arrowId) {
187
+ return
188
+ }
189
+ for (var prevId of node.prev) {
190
+ var prev = nodes[prevId]
191
+ fillAStack(nodes, prev, arrowId)
192
+ }
193
+ }
194
+
195
+ function rewireArrowsInBranch(nodes, prevNodeId, nodeId, arrowStack) {
196
+ if (!nodeId) {return}
197
+ var node = nodes[nodeId]
198
+ if (node.type === "branch") {
199
+ return
200
+ }
201
+ if (node.type === "arrow-loop") {
202
+ if (!node.noloop) {
203
+ node.noloop = {}
204
+ }
205
+ if (arrowStack.includes(nodeId)) {
206
+ return
207
+ }
208
+ node.noloop[prevNodeId] = true
209
+ arrowStack = arrowStack.slice()
210
+ arrowStack.push(nodeId)
211
+ rewireArrowsInBranch(nodes, nodeId, node.one, arrowStack)
212
+ } else if (node.type === "question") {
213
+ var left = arrowStack.slice()
214
+ var right = arrowStack.slice()
215
+ rewireArrowsInBranch(nodes, nodeId, node.one, left)
216
+ rewireArrowsInBranch(nodes, nodeId, node.two, right)
217
+ } else {
218
+ rewireArrowsInBranch(nodes, nodeId, node.one, arrowStack)
219
+ }
220
+ }
221
+
222
+ function insertArrowStub(nodes, node) {
223
+ var stub = {
224
+ type: "arrow-stub",
225
+ id: "arrow-stub-" + node.id,
226
+ arrow: node.id,
227
+ prev: []
228
+ }
229
+ nodes[stub.id] = stub
230
+ node.stub = stub.id
231
+ var prev2 = []
232
+ for (var prevId of node.prev) {
233
+ if (prevId in node.noloop) {
234
+ prev2.push(prevId)
235
+ } else {
236
+ stub.prev.push(prevId)
237
+ var prev = nodes[prevId]
238
+ redirectNode(nodes, prev, node.id, stub.id)
239
+ }
240
+ }
241
+ node.prev = prev2
242
+ return stub
243
+ }
244
+
245
+ function rewriteTree(body, index, endId, output) {
246
+ while (index < body.length) {
247
+ var node = body[index]
248
+ index++
249
+ if (endId && node.id === endId) {
250
+ return index
251
+ }
252
+ if (node.type === "question") {
253
+ var transformed = rewriteQuestionTree(node, output)
254
+ if (endId) {
255
+ var breakYes = findLoopEnd(transformed.yes, endId)
256
+ var breakNo = findLoopEnd(transformed.no, endId)
257
+ if (breakYes || breakNo) {
258
+ var toBreak = []
259
+ findPlacesToBreak(transformed.yes, endId, toBreak)
260
+ findPlacesToBreak(transformed.no, endId, toBreak)
261
+ addBreaks(toBreak)
262
+ return index
263
+ }
264
+ }
265
+ } else if (node.type === "loopbegin") {
266
+ var body2 = []
267
+ index = rewriteTree(body, index, node.end, body2)
268
+ output.push({
269
+ id: node.id,
270
+ type: "loop",
271
+ content: node.content,
272
+ body: body2
273
+ })
274
+ } else {
275
+ output.push(node)
276
+ }
277
+ }
278
+ }
279
+
280
+ function findPlacesToBreak(body, endId, output) {
281
+ if (body.length === 0) {
282
+ output.push(body)
283
+ return
284
+ }
285
+ var last = body[body.length - 1]
286
+ if (last.id === endId) {
287
+ return
288
+ }
289
+ if (last.type === "question") {
290
+ var qends = []
291
+ findPlacesToBreak(last.yes, endId, qends)
292
+ findPlacesToBreak(last.no, endId, qends)
293
+ if (qends.length === 2
294
+ && qends[0] === last.yes
295
+ && qends[1] === last.no) {
296
+ output.push(body)
297
+ } else {
298
+ addRange(output, qends)
299
+ }
300
+ } else {
301
+ output.push(body)
302
+ }
303
+ }
304
+
305
+ function findLoopEnd(body, endId) {
306
+ for (var i = 0; i < body.length; i++) {
307
+ var node = body[i]
308
+ if (node.id === endId) {
309
+ if (i === body.length - 1) {
310
+ return true
311
+ } else {
312
+ throw createError(
313
+ translate("An exit from the loop must lead to the point right after the loop end"),
314
+ filename,
315
+ node.id
316
+ );
317
+ }
318
+ }
319
+ if (node.type === "question") {
320
+ if (findLoopEnd(node.yes, endId)) {
321
+ return true
322
+ }
323
+ if (findLoopEnd(node.no, endId)) {
324
+ return true
325
+ }
326
+ }
327
+ }
328
+ return false
329
+ }
330
+
331
+ function addBreaks(toBreak) {
332
+ for (var body of toBreak) {
333
+ body.push({
334
+ type: "break"
335
+ })
336
+ }
337
+ }
338
+
339
+ function rewriteQuestionTree(question, output) {
340
+ var yes = []
341
+ var no = []
342
+ rewriteTree(question.yes, 0, undefined, yes)
343
+ rewriteTree(question.no, 0, undefined, no)
344
+ var transformed = {
345
+ type: "question",
346
+ id: question.id,
347
+ content: question.content,
348
+ yes: yes,
349
+ no: no
350
+ }
351
+ output.push(transformed)
352
+ return transformed
353
+ }
354
+
355
+
356
+ function structMain() {
357
+ rewireArrows(nodes, branches)
358
+ prepareQuestions(nodes)
359
+ var result = []
360
+ for (var branch of branches) {
361
+ flowGraph(nodes, branch.next, [])
362
+ }
363
+
364
+ for (var branch of branches) {
365
+ var body = []
366
+ buildTree(nodes, branch.next, body, "<dummy id>")
367
+ var body2 = []
368
+ rewriteTree(body, 0, undefined, body2)
369
+ result.push({
370
+ name: branch.content,
371
+ branchId: branch.branchId,
372
+ start: branch.next,
373
+ body: body2
374
+ })
375
+ }
376
+
377
+ return sortByProperty(result, "branchId")
378
+ }
379
+
380
+ return structMain()
381
+ }
382
+ module.exports = { structFlow, redirectNode };
@@ -0,0 +1,84 @@
1
+ function buildTree(nodes, nodeId, body, stopId) {
2
+ while (nodeId) {
3
+ if (nodeId === stopId) {return;}
4
+ const node = nodes[nodeId];
5
+ let transformed;
6
+ let next;
7
+
8
+ if (node.type === "question") {
9
+ next = reserveNext(nodes, node)
10
+
11
+ transformed = {
12
+ id: node.id,
13
+ type: "question",
14
+ content: node.content || "",
15
+ yes: [],
16
+ no: []
17
+ };
18
+
19
+ const yesNodeId = node.flag1 === 1 ? node.one : node.two;
20
+ const noNodeId = node.flag1 === 1 ? node.two : node.one;
21
+
22
+ buildTree(nodes, yesNodeId, transformed.yes, node.next);
23
+ buildTree(nodes, noNodeId, transformed.no, node.next);
24
+ } else if (node.type === "arrow-loop") {
25
+ transformed = {
26
+ id: node.id,
27
+ type: "loopbegin",
28
+ content: "",
29
+ end: node.stub
30
+ };
31
+
32
+ next = node.one;
33
+ } else if (node.type === "arrow-stub") {
34
+ transformed = {
35
+ id: node.id,
36
+ type: "loopend",
37
+ start: node.arrow
38
+ };
39
+
40
+ next = node.one;
41
+ } else {
42
+ transformed = {
43
+ id: node.id,
44
+ type: node.type,
45
+ }
46
+ copyFields(
47
+ transformed,
48
+ node,
49
+ [
50
+ "content",
51
+ "secondary",
52
+ "start",
53
+ "message",
54
+ "end"
55
+ ]
56
+ )
57
+ next = node.one;
58
+ }
59
+
60
+ body.push(transformed);
61
+ nodeId = next;
62
+ }
63
+ }
64
+
65
+ function copyFields(dst, src, fields) {
66
+ for (var field of fields) {
67
+ var value = src[field]
68
+ if (value !== "" && value !== undefined && value !== null) {
69
+ dst[field] = value
70
+ }
71
+ }
72
+ }
73
+
74
+ function reserveNext(nodes, node) {
75
+ const target = nodes[node.next];
76
+ if (target.targetTaken) {
77
+ return undefined;
78
+ } else {
79
+ target.targetTaken = true;
80
+ return node.next;
81
+ }
82
+ }
83
+
84
+ module.exports = {buildTree}
package/src/tools.js ADDED
@@ -0,0 +1,36 @@
1
+
2
+ function createError(message, filename, nodeId) {
3
+ var error = new Error(message)
4
+ error.nodeId = nodeId
5
+ error.filename = filename
6
+ return error
7
+ }
8
+
9
+ function sortByProperty(array, property, order = "asc") {
10
+ if (!Array.isArray(array)) {
11
+ throw new Error("First argument must be an array");
12
+ }
13
+
14
+ return array.slice().sort((a, b) => {
15
+ const valA = a[property];
16
+ const valB = b[property];
17
+
18
+ if (valA === null || valB === null || valA === undefined || valB === undefined) {
19
+ return 0; // Handle null or undefined values
20
+ }
21
+
22
+ if (valA < valB) {
23
+ return order === "asc" ? -1 : 1;
24
+ }
25
+ if (valA > valB) {
26
+ return order === "asc" ? 1 : -1;
27
+ }
28
+ return 0; // Values are equal
29
+ });
30
+ }
31
+ function addRange(to, from) {
32
+ for (var item of from) {
33
+ to.push(item)
34
+ }
35
+ }
36
+ module.exports = { createError, sortByProperty, addRange }
@@ -0,0 +1,108 @@
1
+ var translationsRu = {
2
+ "error": "ОШИБКА",
3
+ "not": "не",
4
+ break: 'выход из цикла',
5
+ "and": "и",
6
+ "or": "или",
7
+ "if": "Если",
8
+ "else": "Иначе",
9
+ "empty": "ПУСТОЙ",
10
+ "loop forever": "Бесконечный цикл",
11
+ "pass": "Пропустить",
12
+ "Only the rightmost Case icon can be empty": "Только самая правая икона Вариант может быть пустой",
13
+ "Error parsing JSON": "Ошибка парсинга JSON",
14
+ "A Loop begin icon must have content": "Икона начала цикла ДЛЯ должна содержать данные",
15
+ "A Question icon must have content": "Икона Вопрос должна содержать данные",
16
+ "A Select icon must have content": "Икона Выбор должна содержать данные",
17
+ "Loop end expected here": "Здесь ожидается конец цикла",
18
+ "An exit from the loop must lead to the point right after the loop end": "Выход из цикла должен вести в точку сразу за его концом",
19
+ "A silhouette branch is not referenced": "Нет ссылок на ветку силуэта",
20
+ "Call subroutine": "Вызвать подпрограмму",
21
+ "Procedure": "Процедура",
22
+ "End of procedure": "Конец процедуры",
23
+ "Subroutine": "Подпрограмма",
24
+ "End of subroutine": "Конец подпрограммы",
25
+ "Description": "Описание",
26
+ "Algorithm": "Алгоритм",
27
+ Remarks: "Замечания"
28
+ }
29
+
30
+ var translationsEn = {
31
+ error: 'Error',
32
+ not: 'not',
33
+ break: 'break',
34
+ and: 'and',
35
+ or: 'or',
36
+ if: 'If',
37
+ else: 'Else',
38
+ empty: 'Empty',
39
+ 'loop forever': 'Loop forever',
40
+ pass: 'Pass',
41
+ 'Only the rightmost Case icon can be empty': 'Only the rightmost Case icon can be empty',
42
+ 'Error parsing JSON': 'Error parsing JSON',
43
+ 'A Loop begin icon must have content': 'A Loop begin icon must have content',
44
+ 'A Question icon must have content': 'A Question icon must have content',
45
+ 'A Select icon must have content': 'A Select icon must have content',
46
+ 'Loop end expected here': 'Loop end expected here',
47
+ 'An exit from the loop must lead to the point right after the loop end': 'An exit from the loop must lead to the point right after the loop end',
48
+ 'A silhouette branch is not referenced': 'A silhouette branch is not referenced',
49
+ 'Call subroutine': 'Call subroutine',
50
+ Procedure: 'Procedure',
51
+ 'End of procedure': 'End of procedure',
52
+ Subroutine: 'Subroutine',
53
+ 'End of subroutine': 'End of subroutine',
54
+ Description: 'Description',
55
+ Algorithm: 'Algorithm',
56
+ Remarks: "Remarks"
57
+ }
58
+
59
+ var translationsNo = {
60
+ error: 'Feil',
61
+ not: 'ikke',
62
+ break: 'avslutt løkken',
63
+ and: 'og',
64
+ or: 'eller',
65
+ if: 'Hvis',
66
+ else: 'Ellers',
67
+ empty: 'Tom',
68
+ 'loop forever': 'Gjør evig',
69
+ pass: 'Hopp over',
70
+ 'Only the rightmost Case icon can be empty': 'Bare den ytterste høyre Case-ikonet kan være tomt',
71
+ 'Error parsing JSON': 'Feil ved parsing av JSON',
72
+ 'A Loop begin icon must have content': 'Et Loop-startikon må ha innhold',
73
+ 'A Question icon must have content': 'Et Spørsmål-ikon må ha innhold',
74
+ 'A Select icon must have content': 'Et Velg-ikon må ha innhold',
75
+ 'Loop end expected here': 'Slutt på løkke forventet her',
76
+ 'An exit from the loop must lead to the point right after the loop end': 'En utgang fra løkken må føre til punktet rett etter løkkens slutt',
77
+ 'A silhouette branch is not referenced': 'En silhuettgren er ikke referert',
78
+ 'Call subroutine': 'Kall delprosedyre',
79
+ Procedure: 'Prosedyre',
80
+ 'End of procedure': 'Slutt på prosedyre',
81
+ Subroutine: 'Delprosedyre',
82
+ 'End of subroutine': 'Slutt på delprosedyre',
83
+ Description: 'Beskrivelse',
84
+ Algorithm: 'Algoritme',
85
+ Remarks: "Bemerkninger"
86
+ };
87
+
88
+
89
+ var translations = translationsEn
90
+
91
+ function translate(text) {
92
+ return translations[text] || text;
93
+ }
94
+
95
+ function setUpLanguage(language) {
96
+ if (language === "ru") {
97
+ translations = translationsRu
98
+ } else if (language === "no") {
99
+ translations = translationsNo
100
+ } else if (language === "en") {
101
+ translations = translationsEn
102
+ } else {
103
+ translations = {}
104
+ }
105
+ }
106
+
107
+
108
+ module.exports = { setUpLanguage, translate };