@painekillers/tree-builder-core 1.0.0 → 1.1.1

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/graph.js CHANGED
@@ -79,8 +79,28 @@ export class LayoutNode {
79
79
  }
80
80
  }
81
81
 
82
+ /*
83
+ Recursion settings
84
+ Null: No recursion
85
+ False: Creates fake nodes when encountering recursion
86
+ True: Connects back to existing instance of a node when recursing
87
+ #: Real recursion to depths #
88
+ */
89
+
90
+ /*
91
+ Strategies
92
+ - [X] Current BFS (First) — Layer by shortest distance from root; first discovery determines placement.
93
+ - [X] Undirected BFS (Undirected) — Shortest distance to root; layering is one directional.
94
+ - [X] Directed BFS, outward only (Outwards) — Follow prerequisite-to-dependent edges only.
95
+ - [X] Furthest-parent layering (Furthest) — Place each node one layer below its deepest prerequisite.
96
+ */
97
+
82
98
  export class LayoutGraph {
83
- constructor(graph, root, recurse) {
99
+ constructor(graph, root, recurse, strategy = "First") {
100
+ if(strategy == "First" && typeof recurse == "number") {
101
+ throw new Error(`Cannot use strategy ${strategy} with numeric recursion setting`);
102
+ }
103
+
84
104
  this.layers = new Map()
85
105
 
86
106
  const rootNode = graph.nodeFromId(root)
@@ -96,13 +116,13 @@ export class LayoutGraph {
96
116
  const visited = new Map()
97
117
  const connections = new Set()
98
118
 
99
- const addConnection = (ln, from) => {
119
+ const addConnection = (ln, from, lnPos) => {
100
120
  const fromNode =
101
121
  this.layers.get(from.layer)?.[from.ind]
102
122
 
103
123
  if(!fromNode) return
104
124
 
105
- const a = `${ln.layer}:${ln.ind}`
125
+ const a = `${lnPos.layer}:${lnPos.ind}`
106
126
  const b = `${from.layer}:${from.ind}`
107
127
 
108
128
  const key = [a, b].sort().join("|")
@@ -145,13 +165,29 @@ export class LayoutGraph {
145
165
 
146
166
  //holy crap i cannot think bruh
147
167
  if(((recurse === false) || (recurse === null)) && pos.layer !== layer) {
148
- if(recurse === null) { continue }
168
+ if (
169
+ recurse === null ||
170
+ strategy == "Outwards" &&
171
+ from !== null &&
172
+ Math.abs(layer) < Math.abs(from.layer)
173
+ ) { continue }
174
+
175
+ if (
176
+ strategy == "Furthest" &&
177
+ (
178
+ (layer > 0 && !node.parents.every(val => visited.has(val.id)))
179
+ ||
180
+ (layer < 0 && !node.children.every(val => visited.has(val.id)))
181
+ )
182
+ ) { continue }
183
+
184
+ //this part makes the fake node btw
149
185
  const fn = new LayoutNode(node, layer, this.layers.get(pos.layer)[pos.ind])
150
186
  this.layers.get(layer).push(fn)
151
187
 
152
- addConnection(fn, from)
188
+ addConnection(fn, from, pos)
153
189
  } else {
154
- addConnection(ln, from)
190
+ addConnection(ln, from, pos)
155
191
 
156
192
  }
157
193
  }
@@ -159,6 +195,37 @@ export class LayoutGraph {
159
195
  continue
160
196
  }
161
197
 
198
+ if (
199
+ strategy == "Outwards" &&
200
+ from !== null &&
201
+ Math.abs(layer) < Math.abs(from.layer)
202
+ ) { continue }
203
+
204
+ if (strategy == "Furthest") {
205
+ if (layer > 0 && !node.parents.every(val => visited.has(val.id))) {
206
+ for (const parent of node.parents) {
207
+ queue.push({
208
+ node: parent,
209
+ layer: layer - 1,
210
+ from: null
211
+ })
212
+ }
213
+
214
+ continue
215
+ } else
216
+ if (layer < 0 && !node.children.every(val => visited.has(val.id))) {
217
+ for (const child of node.children) {
218
+ queue.push({
219
+ node: child,
220
+ layer: layer + 1,
221
+ from: null
222
+ })
223
+ }
224
+
225
+ continue
226
+ }
227
+ }
228
+
162
229
  const ln = new LayoutNode(node, layer)
163
230
 
164
231
  this.layers.get(layer).push(ln)
@@ -171,7 +238,7 @@ export class LayoutGraph {
171
238
  visited.set(key, pos)
172
239
 
173
240
  if(from) {
174
- addConnection(ln, from)
241
+ addConnection(ln, from, pos)
175
242
  }
176
243
 
177
244
  for (const child of node.children) {
@@ -185,10 +252,11 @@ export class LayoutGraph {
185
252
  for (const parent of node.parents) {
186
253
  queue.push({
187
254
  node: parent,
188
- layer: layer - 1,
255
+ layer: strategy !== "Undirected" ? layer - 1: layer + 1,
189
256
  from: pos
190
257
  })
191
258
  }
259
+
192
260
  }
193
261
  }
194
262
  }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@painekillers/tree-builder-core",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
7
7
  "./themes/*": "./themes/*"
8
8
  }
9
- }
9
+ }
package/world/bridge.js CHANGED
@@ -25,8 +25,8 @@ export default class Bridge {
25
25
  }
26
26
  }
27
27
 
28
- calculateLayout(root, recurse){ // Real maxdepth, since we cant actually make it infinite
29
- this.layout = new LayoutGraph(this.graph, root, recurse)
28
+ calculateLayout(root, recurse, strategy = "First"){ // Real maxdepth, since we cant actually make it infinite
29
+ this.layout = new LayoutGraph(this.graph, root, recurse, strategy)
30
30
  // Since JS is goofy like this ill just have recurse be a number when we want recursive
31
31
  this.root = this.graph.nodes.get(root)
32
32