|
const conversions = require('./conversions'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function buildGraph() { |
|
const graph = {}; |
|
|
|
const models = Object.keys(conversions); |
|
|
|
for (let len = models.length, i = 0; i < len; i++) { |
|
graph[models[i]] = { |
|
|
|
|
|
distance: -1, |
|
parent: null |
|
}; |
|
} |
|
|
|
return graph; |
|
} |
|
|
|
|
|
function deriveBFS(fromModel) { |
|
const graph = buildGraph(); |
|
const queue = [fromModel]; |
|
|
|
graph[fromModel].distance = 0; |
|
|
|
while (queue.length) { |
|
const current = queue.pop(); |
|
const adjacents = Object.keys(conversions[current]); |
|
|
|
for (let len = adjacents.length, i = 0; i < len; i++) { |
|
const adjacent = adjacents[i]; |
|
const node = graph[adjacent]; |
|
|
|
if (node.distance === -1) { |
|
node.distance = graph[current].distance + 1; |
|
node.parent = current; |
|
queue.unshift(adjacent); |
|
} |
|
} |
|
} |
|
|
|
return graph; |
|
} |
|
|
|
function link(from, to) { |
|
return function (args) { |
|
return to(from(args)); |
|
}; |
|
} |
|
|
|
function wrapConversion(toModel, graph) { |
|
const path = [graph[toModel].parent, toModel]; |
|
let fn = conversions[graph[toModel].parent][toModel]; |
|
|
|
let cur = graph[toModel].parent; |
|
while (graph[cur].parent) { |
|
path.unshift(graph[cur].parent); |
|
fn = link(conversions[graph[cur].parent][cur], fn); |
|
cur = graph[cur].parent; |
|
} |
|
|
|
fn.conversion = path; |
|
return fn; |
|
} |
|
|
|
module.exports = function (fromModel) { |
|
const graph = deriveBFS(fromModel); |
|
const conversion = {}; |
|
|
|
const models = Object.keys(graph); |
|
for (let len = models.length, i = 0; i < len; i++) { |
|
const toModel = models[i]; |
|
const node = graph[toModel]; |
|
|
|
if (node.parent === null) { |
|
|
|
continue; |
|
} |
|
|
|
conversion[toModel] = wrapConversion(toModel, graph); |
|
} |
|
|
|
return conversion; |
|
}; |
|
|
|
|