MCPcopy Create free account
hub / github.com/p2r3/convert / searchPath

Method searchPath

src/TraversionGraph.ts:334–398  ·  view source on GitHub ↗
(from: ConvertPathNode, to: ConvertPathNode, simpleMode: boolean)

Source from the content-addressed store, hash-verified

332 }
333
334 public async* searchPath(from: ConvertPathNode, to: ConvertPathNode, simpleMode: boolean) : AsyncGenerator<ConvertPathNode[]> {
335 // Dijkstra's algorithm
336 // Priority queue of {index, cost, path}
337 let queue: PriorityQueue<QueueNode> = new PriorityQueue<QueueNode>(
338 1000,
339 (a: QueueNode, b: QueueNode) => a.cost - b.cost
340 );
341 let visited = new Array<number>();
342 const fromIdentifier = from.format.mime + `(${from.format.format})`;
343 const toIdentifier = to.format.mime + `(${to.format.format})`;
344 let fromIndex = this.nodes.findIndex(node => node.identifier === fromIdentifier);
345 let toIndex = this.nodes.findIndex(node => node.identifier === toIdentifier);
346 if (fromIndex === -1 || toIndex === -1) return []; // If either format is not in the graph, return empty array
347 queue.add({index: fromIndex, cost: 0, path: [from], visitedBorder: visited.length });
348 console.log(`Starting path search from ${from.format.mime}(${from.handler?.name}) to ${to.format.mime}(${to.handler?.name}) (simple mode: ${simpleMode})`);
349 let iterations = 0;
350 let pathsFound = 0;
351 while (queue.size() > 0) {
352 iterations++;
353 // Get the node with the lowest cost
354 let current = queue.poll()!;
355 const indexInVisited = visited.indexOf(current.index);
356 if (indexInVisited >= 0 && indexInVisited < current.visitedBorder) {
357 this.dispatchEvent("skipped", current.path);
358 continue;
359 }
360 if (current.index === toIndex) {
361 // Return the path of handlers and formats to get from the input format to the output format
362 const logString = `${iterations} with cost ${current.cost.toFixed(3)}: ${current.path.map(p => p.handler.name + "(" + p.format.mime + ")").join(" → ")}`;
363 const foundPathLast = current.path.at(-1);
364 if (simpleMode || !to.handler || to.handler.name === foundPathLast?.handler.name) {
365 console.log(`Found path at iteration ${logString}`);
366 this.dispatchEvent("found", current.path);
367 yield current.path;
368 pathsFound++;
369 }
370 else {
371 console.log(`Unvalid path at iteration ${logString}`);
372 this.dispatchEvent("skipped", current.path);
373 }
374 continue;
375 }
376 visited.push(current.index);
377 this.dispatchEvent("searching", current.path);
378 this.nodes[current.index].edges.forEach(edgeIndex => {
379 let edge = this.edges[edgeIndex];
380 const indexInVisited = visited.indexOf(edge.to.index);
381 if (indexInVisited >= 0 && indexInVisited < current.visitedBorder) return;
382 const handler = this.handlers.find(h => h.name === edge.handler);
383 if (!handler) return; // If the handler for this edge is not found, skip it
384
385 let path = current.path.concat({handler: handler, format: edge.to.format});
386 queue.add({
387 index: edge.to.index,
388 cost: current.cost + edge.cost + this.calculateAdaptiveCost(path),
389 path: path,
390 visitedBorder: visited.length
391 });

Callers 2

main.tsFile · 0.80

Calls 7

addMethod · 0.95
sizeMethod · 0.95
pollMethod · 0.95
dispatchEventMethod · 0.95
calculateAdaptiveCostMethod · 0.95
indexOfMethod · 0.80
mapMethod · 0.80

Tested by

no test coverage detected